12

我一直在阅读 Vulkan 规范和来自 Khronos 的一些示例,但我一般找不到关于不可变采样器的大量信息。

我想要做的是有一个充满不可变采样器的描述符集(类型为 VK_DESCRIPTOR_TYPE_SAMPLER,而不是 ...COMBINED_IMAGE_SAMPLER),当我想对纹理进行采样时,我在我的着色器中访问这样的采样器:

layout (location = 0) out vec4 out_color;

layout (set = 0, binding = 0) uniform sampler immutableSampler;
layout (set = 3, binding = 0) uniform texture2D color;

void main()
{
    vec4 textureColor = texture(sampler2D(color, immutableSampler), in_uv);
    out_color = textureColor;
}

有了这个着色器,想法是:

  • 在管道布局中,我在 set 0 中的绑定点 0 处有一个不可变的采样器
  • 我还有一个描述符集 (3),其中包含在绑定点 0 处描述的图像,我将其绑定为我的命令缓冲区的一部分
  • 我将不可变采样器应用于着色器中的图像
  • 然后实际访问图像作为sampler2D

但是,我在 Khronos 示例中看到它的方式是:

  • 在管道布局中的绑定点描述 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 的不可变采样器(仅提供采样器)
  • 创建图像并将其绑定到相同的绑定点(没有采样器)
  • sampler2D在着色器中以 a 访问图像;您绑定的图像与该绑定处的不可变采样器配对

在 Vulkan 规范中,它没有说明哪种方式是“正确的”,只是指出:

如果descriptorType指定一个VK_DESCRIPTOR_TYPE_SAMPLERVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER类型描述符,pImmutableSamplers则可用于初始化一组不可变采样器。

现在,如果我的着色器按我预期的方式工作,我就不会问这个问题了。我遇到的问题是,在验证后,Vulkan 层抱怨我的 VkPipeline 正在使用从未绑定过的描述符集(设置 0,绑定 0 采样器所在的位置)!即使我在那里绑定垃圾数据,我仍然必须(至少一次)用垃圾更新描述符集,以抑制另一个验证错误。然而与此同时,Vulkan 规范说:

不可变采样器永久绑定到集合布局中;以后不允许将采样器绑定到描述符集中的不可变采样器槽

因此,甚至不允许将数据绑定到该绑定点!

我现在非常不确定我对不可变采样器的方法是否应该有效,因为它有点模棱两可。规范说我可以绑定一个没有图像的采样器,但是当我这样做时会抱怨,我发现的几个例子是绑定一个组合图像采样器。我只是做错了吗?

如果我的方法应该是有效的并且可以工作,我真的很喜欢这样,因为我正在尝试为 DirectX 12 和 Vulkan 构建一个系统。DX12 在其“根布局”(管道布局)中占有一席之地,所有不可变采样器都绑定在一起,没有与之关联的图像。我想模仿这种行为以保持渲染器之间的奇偶性,但我非常不确定 Vulkan 是否真的可以做到这一点,而且它在规范中非常模棱两可。

4

1 回答 1

15

你想做的事情是完全可能和合法的。您遇到的问题是由于您对 Vulkan 规范没有说明的事情做出的假设。你正在创造不存在的影响。

在这个例子中,我没有绑定任何设置为 0 的描述符,因为没有什么要绑定的,对吧?

错误的。

您在这里所做的假设是不可变的采样器描述符驻留在管道对象中。他们不这样做,而且 Vulkan 规范从未声称他们这样做。

哦,是的,管道对象被赋予了描述符布局,其中包含不可变的采样器。因此,允许实现在构造函数调用时使用该不可变采样器数据texture

但是描述符数据并不存在于管道中。它存在于描述符集中。

Vulkan 规范在这一点上没有任何含糊之处。如果管道的布局包含一个描述符集,并且着色器在执行时使用该集,则必须在执行时绑定一个描述符集,该描述符集与该集索引的管道布局布局兼容。

实现是否真的会从不可变的采样器描述符中获取数据?这些不可变的描述符实际上会将数据存储在描述符内存中,还是将数据存储在管道中?谁在乎; Vulkan 规范说所有使用的描述符都需要绑定。

这条规定没有例外。

但还有其他问题;set 0, binding 0 是一个采样器,但规范明确说我不应该在那里绑定一个采样器。

“绑定采样器”意味着调用vkUpdateDescriptorSets. 该函数更新各种集合中描述符中的数据。但它只会更新您为其选择的数据。

此外,如果您尝试更新不可变采样器的采样器,它将忽略samplerin的值pImageInfo。这是由标准指定的(虽然是间接的):

sampler是一个采样器句柄,用于类型的描述符更新VK_DESCRIPTOR_TYPE_SAMPLERVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 如果正在更新的绑定不使用不可变采样器。

重点补充。

由于存在该条件,因此sampler如果描述符绑定使用不可变采样器,则将被忽略。毕竟,您可以将不可变采样器与组合图像/采样器一起使用。sampler在这种pImageInfo情况下,必须忽略 in。

这并不意味着这些描述符没有内容。您只是不允许更改它们。您可以调用vkUpdateDescriptorSets仅包含不可变采样器的描述符集;它不会做任何事情。

但是您仍然必须分配和使用这样的集合。

如果我绑定一个描述符集并且不更新它,尽管我会在验证中遇到另一个错误,所以我需要将它与某种数据绑定以避免这种情况。

那么这是验证层中的一个错误。你应该报告它。

Vulkan 规范中没有规定必须先更新集合中的所有描述符,然后才能使用该集合。

要关闭错误的验证层,请随意使用vkUpdateDescriptorSets验证构建。不要费心传递有效sampler的句柄,因为它实际上不会做任何事情。

于 2016-05-03T01:14:04.477 回答