在 HLSL 中指定推送常量块偏移

问题描述

我正在尝试编写 Vulkan 渲染器,我将 glslangValidator 与 HLSL 用于着色器,并尝试实现推送常量。

[[vk::push_constant]]
cbuffer cbFragment {
    float4 imageColor;
    float4 aaaa;
};
 
[[vk::push_constant]]
cbuffer cbMatrices {
    float4 bbbb;
};

注释“[[vk::push_constant]]”有效,我使用 spirv_reflect 进行反射,两个推送常量都显示出来,它们按预期工作。 我遇到的问题是它们似乎重叠,如果我为“bbbb”分配一个值,“imageColor”会以完全相同的方式受到影响,反之亦然。在反射数据中,两个推送常量块的偏移量为 0,这就解释了这个问题。但是,我似乎完全无法更改任一推送常量的偏移量。 [[vk::offset(x)]] 根本不起作用,它既不影响单个成员偏移量,也不影响推送常量的偏移量。唯一有效的偏移量是 HLSL 内置的“packoffset”,它仅适用于缓冲区成员。虽然它实际上可能是一个解决方案,只是将一个推送常量的成员抵消到另一个范围之外,但我几乎不相信这是一个明智的解决方案,因为它也会导致验证层失败,因为抵消了个人成员只是不必要地增加了推送常量的大小,并且重叠本身仍然存在。

我非常感谢您对此事的任何帮助,并愿意提供任何必要的说明,非常感谢!

解决方法

推送常量存在于单个连续内存块中。编译器不会尝试将多个块附加到该内存中;与 GLSL syntax 一样,它的目的是让一个块包含所有推送常量数据。

这与编译器必须在块中打包变量的其他地方一致:它只打包在一个块内,而不是跨多个块。两个单独的非 pushconstant cbuffer 将引用内存中的两个不同的缓冲区,其内容从它们各自缓冲区中的偏移量零开始。只有一个“推送常量缓冲区”,因此您应该只用 cbuffer 装饰一个 vk::push_constant