我可以在Vulkan中创建一个不可变采样器而不将图像绑定到该绑定点吗?

时间:2016-05-02 15:30:35

标签: graphics vulkan

我一直在阅读Vulkan规范以及Khronos的一些例子,但我总体上找不到关于不可变采样器的大量信息。

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

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的形式访问图像;您绑定的图像与该绑定的不可变采样器配对

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

  

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

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

  

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

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

我现在非常不确定我对不可变采样器的处理方式是否应该是有效的,因为它有点含糊不清。该规范说我可以在没有图像的情况下绑定一个采样器,但是当我这样做时会抱怨,而我发现的几个例子都是绑定一个组合图像采样器。我只是做错了吗?

如果我的方法假设有效且可行,我真的很喜欢,因为我正在尝试为DirectX 12和Vulkan构建一个系统。 DX12在其“根布局”(管道布局)中占有一席之地,其中所有不可变采样器都被绑定而没有与它们相关联的图像。我想模仿这种行为以保持渲染器之间的平等,但我不确定是否真的可以使用Vulkan并且它在规范中非常模糊。

1 个答案:

答案 0 :(得分:9)

你想做的事情是完全可能和合法的。您遇到的问题是由于您对Vulkan规范未提及的事情所做的假设。你正在创造那些不存在的含义。

  

我没有将任何描述符集绑定到本例中的0,因为没有什么可绑定的,对吗?

错误。

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

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

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

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

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

此规则没有例外。

  

但是还有其他问题;设置0,绑定0是一个采样器,但规范清楚地说我不应该在那里绑定一个采样器。

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

此外,如果您尝试更新不可变采样器的采样器,它将忽略samplerpImageInfo的值。这由标准规定(虽然倾斜):

  

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

强调补充。

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

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

但你仍然需要分配和使用这样的一套。

  

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

然后,这是验证层中的错误。你应该举报。

Vulkan规范中没有任何内容表明在使用集合之前必须更新集合中的所有描述符。

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