【问题标题】:Can I create an Immutable Sampler in Vulkan without binding an image to that bind point?我可以在 Vulkan 中创建不可变采样器而不将图像绑定到该绑定点吗?
【发布时间】:2016-08-27 10:29:02
【问题描述】:

我一直在阅读 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 访问图像;您绑定的图像与该绑定处的不可变采样器配对

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

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

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

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

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

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

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

【问题讨论】:

  • 您是否使用与构建管道相同的集合布局为集合 0 创建了描述符集合?您在那里谈论使用“垃圾数据”创建一个,但不清楚这意味着什么。由于仅包含不可变采样器的描述符集将没有任何数据。那么“垃圾”从何而来?简而言之,给我们看一些实际的代码。
  • 很抱歉给您带来了困惑。在这个例子中,我没有绑定任何设置为 0 的描述符,因为没有什么要绑定的,对吧?我所说的绑定“垃圾数据”实际上是绑定任何描述符集。如果我绑定一个描述符集并且不更新它,尽管我会在验证中遇到另一个错误,所以我需要将它与某种数据绑定以避免这种情况。但还有其他问题;设置 0,绑定 0 是采样器,但规范明确说我不应该在那里绑定采样器。

标签: graphics vulkan


【解决方案1】:

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

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

错了。

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

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

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

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

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

这条规则没有例外。

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

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

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

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

添加了重点。

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

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

但你还是要分配和使用这样的一套。

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

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

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

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

【讨论】:

    猜你喜欢
    • 2022-07-04
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 2010-10-14
    相关资源
    最近更新 更多