在不同着色器阶段使用不同的推式常量

时间:2016-05-05 16:58:19

标签: glsl shader vulkan

我有一个顶点着色器,其推送常量块包含一个浮点数:

layout(push_constant) uniform pushConstants {
    float test1;
} u_pushConstants;

带有另一个具有不同浮点值的推送常量块的片段着色器:

layout(push_constant) uniform pushConstants {
    float test2;
} u_pushConstants;

test1 test2 应该是不同的。

管道布局的推 - 常数范围定义如下:

std::array<vk::PushConstantRange,2> ranges = {
    vk::PushConstantRange{
        vk::ShaderStageFlagBits::eVertex,
        0,
        sizeof(float)
    },
    vk::PushConstantRange{
        vk::ShaderStageFlagBits::eFragment,
        sizeof(float), // Push-constant range offset (Start after vertex push constants)
        sizeof(float)
    }
};

然后在渲染期间推送实际常量,如下所示:

std::array<float,1> constants = {123.f};
commandBufferDraw.pushConstants(
    pipelineLayout,
    vk::ShaderStageFlagBits::eVertex,
    0,
    sizeof(float),
    constants.data()
);
std::array<float,1> constants = {456.f};
commandBufferDraw.pushConstants(
    pipelineLayout,
    vk::ShaderStageFlagBits::eFragment,
    sizeof(float), // Offset in bytes
    sizeof(float),
    constants.data()
);

但是,在检查着色器内的值时,两者的值都为123。 似乎完全忽略了抵消。我不正确地使用它们吗?

1 个答案:

答案 0 :(得分:12)

在管道布局中,您声明顶点着色器将在推送常量范围内访问[0,4]字节的数据范围。您声明片段着色器可以在推动常量范围内访问[4,8]中的数据范围。

但你的着色器讲的是另一个故事。

layout(push_constant) uniform pushConstants {
    float test2;
} u_pushConstants;

这个定义非常明确地说推动常数范围开始使用[0,4]。但你告诉Vulkan它使用[4,8]。 Vulkan应该相信哪个:你的着色器,还是你的管道布局?

要记住的一般经验法则是:你的着色器意味着它所说的意思。为管道创建提供的参数不能更改代码的含义。

如果您打算让片段着色器真正使用[4,8],那么片段着色器必须真正使用它:

layout(push_constant) uniform fragmentPushConstants {
    layout(offset = 4) float test2;
} u_pushConstants;

由于它与VS版本的定义不同,因此它也应具有不同的块名称。 offset布局指定了相关变量的偏移量。这是GLSL的标准内容,而compiling for Vulkan并没有改变它。