我一直在阅读 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_SAMPLER
或VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
类型描述符,pImmutableSamplers
则可用于初始化一组不可变采样器。
现在,如果我的着色器按我预期的方式工作,我就不会问这个问题了。我遇到的问题是,在验证后,Vulkan 层抱怨我的 VkPipeline 正在使用从未绑定过的描述符集(设置 0,绑定 0 采样器所在的位置)!即使我在那里绑定垃圾数据,我仍然必须(至少一次)用垃圾更新描述符集,以抑制另一个验证错误。然而与此同时,Vulkan 规范说:
不可变采样器永久绑定到集合布局中;以后不允许将采样器绑定到描述符集中的不可变采样器槽
因此,甚至不允许将数据绑定到该绑定点!
我现在非常不确定我对不可变采样器的方法是否应该有效,因为它有点模棱两可。规范说我可以绑定一个没有图像的采样器,但是当我这样做时会抱怨,我发现的几个例子是绑定一个组合图像采样器。我只是做错了吗?
如果我的方法应该是有效的并且可以工作,我真的很喜欢这样,因为我正在尝试为 DirectX 12 和 Vulkan 构建一个系统。DX12 在其“根布局”(管道布局)中占有一席之地,所有不可变采样器都绑定在一起,没有与之关联的图像。我想模仿这种行为以保持渲染器之间的奇偶性,但我非常不确定 Vulkan 是否真的可以做到这一点,而且它在规范中非常模棱两可。