VkRenderPassCreateInfo
包含用于深度,颜色和输入附件的附件索引。 VkFramebufferCreateInfo::pAttachments
中引用了相应的图像视图。
在着色器中input_attachment_index
标识着色器正在使用的输入附件。
鉴于帧缓冲在渲染过程中被绑定,这应该允许识别用于输入附件的图像视图,就像它对深度和颜色附件一样。
我不明白为什么Vulkan还要求在描述符集布局中提及输入附件(而不是其他附件),从而在绑定描述符集中提及。
我觉得我在这里错过了一些东西?什么是输入附件需要绑定描述符?
答案 0 :(得分:6)
它与管道布局和兼容性有关。
目前的情况是,管道布局完全由VkPipelineLayoutCreateInfo
定义。此结构包含一些标志,VkDescriptorSetLayout
数组和VkPushConstantRange
数组。这意味着管道的布局实际上并不关心着色器中定义的内容;它只关心描述符(和推送常量)。显然,着色器必须与描述符匹配,但这是着色器要处理的问题。
Vulkan根据管道布局的兼容性定义两个管道之间的描述符兼容性。这意味着,无论这些管道(或任何其他管道状态)中着色器的内容如何,共享相同管道布局的两个管道都是兼容的。
因此,如果我们从描述符集中删除输入附件,我们现在拥有着色器正在使用的概念资源,其中不是描述符。对于将输入附件实现为专用操作的硬件(TBR,其中输入附件只是从本地磁贴内存读取),这很好。对于实现输入附件实际从纹理读取的硬件,这不是很好。为什么呢?
由于布局兼容性规则。请记住:他们根据着色器中的内容不;它们仅基于管道布局中的内容。因此,如果我有两个使用相同布局的管道,它们必须兼容。但是,如果一个管道有一个使用输入附件的片段着色器而另一个没有,那么如何实现它以匹配布局兼容性规则,同时仍然有这个隐藏的纹理?
管道布局和描述符集映射到实现中的某种资源绑定机制。因此,布局定义了如何将各种描述符集应用于实现定义的资源绑定。如果我们将纹理绑定看作一个值数组,则设置0的纹理将在集合1' s之前分配,并在之后设置2' s,等等。
如果输入附件不是描述符,那么输入附件纹理(再次,对于将输入附件视为纹理的实现)与实现定义的资源绑定范围的绑定如何完成?
可以在子通道开始时完成,因为子通道知道它使用的所有输入附件。输入附件纹理将绑定到特定纹理阵列位置,并且在该子通道期间永远不会更改。假设我们有一个输入附件,它会选择纹理数组索引0作为绑定位置。
但那不可能发生;布局兼容性规则不允许它。 不使用输入附件的管道将假定索引0可由描述符集自由使用。因此,它们将与做使用输入附件的管道不兼容。但是Vulkan并不允许它们不兼容,因为兼容性仅针对管道布局定义,而不是针对管道对象本身的属性(如着色器)。
可以通过每个管道绑定调用来完成。也就是说,每次绑定使用输入附件的管道时,它也会有效地将纹理绑定到某个数组索引。对于不同的管道,该数组索引将有所不同。
但是,由于布局兼容性规则,这无法发生 。如果我有使用一些描述符集布局0和1的管道A,以及使用相同初始描述符集布局0的管道B,那么Vulkan说我可以将描述符集绑定到集合0和1(与布局匹配),以及我可以使用任何顺序的管道与绑定的那些描述符集。我不必在管道更改之间进行任何描述符集重新绑定。
如果管道B使用输入附件,则根据上述规则,它将在纹理数组中为该输入附件分配一个附加索引。但该数组索引当前可能被描述符集1使用,管道B 不知道。因此,绑定管道B将中断描述符集1.这违反了规范。
管道布局兼容性是Vulkan的非常有用的功能。它允许您知道何时需要绑定描述符集,以及何时可以在不必更改集的情况下切换管道。这些都是好东西,对运行时性能很有用。
他们根本就没有在输入附件作为纹理无形实现的世界中工作。因此,Vulkan要求你明确表达它们(因为明确的事情有点像Vulkan)。在没有制作纹理的实现上,它完全忽略了那些描述符。
还应该注意,according to this presentation (PDF),甚至TBR有时可以将输入附件视为纹理提取。当子通道不能融合时会发生这种情况。一起。当它无法将附件数据保留在子区域之间的区块中时,就会发生这种情况。这是基于渲染过程本身的属性,所以它可以在前面确定。
这就是为什么它是输入附件。
答案 1 :(得分:1)
某些GPU可以直接从绑定附件中读取,某些实现在内部有效地将其作为纹理(采样或存储图像)读取。 API允许两者,而不需要第二类GPU动态生成附件的描述符并管理隐藏/内部描述符集。