Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using different push-constants in different shader stages

I have a vertex shader with a push-constant block containing one float:

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

And a fragment shader with another push-constant block with a different float value:

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

test1 and test2 are supposed to be different.

The push-constant ranges for the pipeline layout are defined like this:

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)
    }
};

The actual constants are then pushed during rendering like this:

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()
);

However, when checking the values inside the shaders, both have the value 123. It seems that the offsets are completely ignored. Am I using them incorrectly?

like image 758
Silverlan Avatar asked May 05 '16 16:05

Silverlan


1 Answers

In your pipeline layout, you stated that your vertex shader would access the range of data from [0, 4) bytes in the push constant range. You stated that your fragment shader would access the range of data from [4, 8) in the push constant range.

But your shaders tell a different story.

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

This definition very clearly says that the push constant range starts uses [0, 4). But you told Vulkan it uses [4, 8). Which should Vulkan believe: your shader, or your pipeline layout?

A general rule of thumb to remember is this: your shader means what it says it means. Parameters given to pipeline creation cannot change the meaning of your code.

If you intend to have the fragment shader really use [4, 8), then the fragment shader must really use it:

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

Since it has a different definition from the VS version, it should have a different block name too. The offset layout specifies the offset of the variable in question. That's standard stuff from GLSL, and compiling for Vulkan doesn't change that.

like image 168
Nicol Bolas Avatar answered Oct 24 '22 16:10

Nicol Bolas