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