3
votes

I have a geometry shader with the following push constant block:

layout(push_constant) uniform Instance {
    mat4 VP;
    vec3 posCam;
    float radius;
    float curvature;
} u_instance;

The push constants are defined in the pipeline layout like this:

uint32_t offset = 0;
uint32_t size = 21 *sizeof(float);
vk::PushConstantRange range {vk::ShaderStageFlagBits::eGeometry,offset,size};

However, the Vulkan validation layers throw this error:

Push constant range covering variable starting at offset 0 not accessible from stage VK_SHADER_STAGE_GEOMETRY_BIT

What does 'not accessible' mean here? Why wouldn't they be accessible? If I move the push constants to a different stage (e.g. fragment or vertex shader), no error occurs.

Additionally, I only get this error on a Nvidia GeForce GTX 650 Ti. I've also tried it on an AMD card, which worked fine.

Is there some kind of limitation on push constants for geometry shaders? I've checked the limitations for my Nvidia GPU, the total max push constant size is 256 bytes, and geometry shaders are supported. I also can't find anything in the Vulkan specification either.

2

2 Answers

2
votes

Can you please add some more code (or upload it to somewhere)? I just tested this with your push constant block on a GTX 980 with validation layers compiled from source and don't get any validation warnings.

Additionally, I only get this error on a Nvidia GeForce GTX 650 Ti. I've also tried it on an AMD card, which worked fine.

That's very odd, as the validation messages are not generated by the drivers and as such should not differ between implementations (unless it's a validation related to device limits).

Is there some kind of limitation on push constants for geometry shaders? I've checked the limitations for my Nvidia GPU, the total max push constant size is 256 bytes, and geometry shaders are supported. I also can't find anything in the Vulkan specification either.

There is no push constant limit specific to the geometry shader. If you exceed the push constant size limit the validation layers will throw an error.

I think that std430 packing rules (or 14.5.4. Offset and Stride Assignment of the Vulkan spec) can mess up the sizes. E.g. the vec3 would be laid out as vec4 (so maybe 22*sizeof(float)? - sorry not exactly confident in this myself).

Not sure if packing would be a problem here, but basically this should work without a validation layer message. If stride would be a problem the validation layers should still not trigger anything if you start with offset 0.

2
votes

I think that std430 packing rules (or 14.5.4. Offset and Stride Assignment of the Vulkan spec) can mess up the sizes. E.g. the vec3 would be laid out as vec4 (so maybe 22*sizeof(float)? - sorry not exactly confident in this myself).

The layer code is open if you would like to investigate yourself (and I found the line producing that report): https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/layers/core_validation.cpp#L1976

UPDATE: I don't think I was right above. What 1.0.17 SDK glslangValidator gives me is 84 bytes (21*float; with member offsets 0, 64, 76 and 80 respectively). The whole block is getting padded to multiple of 16 to me though (to whole block size of 96 B).

Besides the message is tied to the supplied stage enum (it compares it with the stage of the shader module). It is very strange the error message would differ between implementations... (make sure you have updated SDK and drivers, and be suspicious of the vkcpp wrapper or whatever that posted code is) and check pStages[n].stage member of the used VkGraphicsPipelineCreateInfo and the PushRange stage value (which the layer compares).