(I've seen similar questions but the answers didn't help me, that's why I'm asking)
I use push constant data for my vertex and tessellation evaluation shaders.
struct i declared for storing matrices:
struct push_constant_data {
// vertex shader
alignas(16) glm::mat4 model_matrix;
// tessellation evaluation shader
alignas(16) glm::mat4 view_matrix;
alignas(16) glm::mat4 projection_matrix;
};
vertex shader:
layout(push_constant) uniform push_data {
mat4 model_matrix;
} push;
tessellation evaluation shader:
layout(push_constant) uniform push_data {
layout(offset = 64)
mat4 view_matrix;
mat4 projection_matrix;
} push;
that's how I created the ranges:
vk::PushConstantRange vertex_range{};
vertex_range.offset = 0;
vertex_range.size = sizeof(glm::mat4);
vertex_range.stageFlags = vk::ShaderStageFlagBits::eVertex;
vk::PushConstantRange TES_range{};
TES_range.offset = sizeof(glm::mat4);
TES_range.size = 2 * sizeof(glm::mat4);
TES_range.stageFlags = vk::ShaderStageFlagBits::eTessellationEvaluation;
filling the struct:
push_constant_data push{
{glm::mat4(1.0f)}, //model
{glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f))}, //view
{glm::perspective(glm::radians(45.0f), swapchain_extent.width / (float)swapchain_extent.height, 0.1f, 10.0f)} //projection
};
binding push constants:
commandBuffer.pushConstants(pipeline_layout_, vk::ShaderStageFlagBits::eVertex, 0, sizeof(glm::mat4), &push);
commandBuffer.pushConstants(pipeline_layout_, vk::ShaderStageFlagBits::eTessellationEvaluation, sizeof(glm::mat4), 2 * sizeof(glm::mat4), &push);
as a result, I see nothing. When I use
commandBuffer.pushConstants(
pipeline_layout_,
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eTessellationEvaluation,
0,
sizeof(push),
&push
);
I get exactly what I need, and a validation layer message of course:
vkCmdPushConstants(): VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, VkPushConstantRange in VkPipelineLayout 0x9fde6b0000000014[] overlapping offset = 0 and size = 192, do not contain VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT. The Vulkan spec states: For each byte in the range specified by offset and size and for each shader stage in stageFlags, there must be a push constant range in layout that includes that byte and that stage (https://vulkan.lunarg.com/doc/view/1.3.275.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdPushConstants-offset-01795)
The vkCmdPushConstants
parameters offset
and size
are GPU-side only.
commandBuffer.pushConstants(pipeline_layout_, vk::ShaderStageFlagBits::eVertex, 0, sizeof(glm::mat4), &push.model_matrix);
std::array<glm::mat4, 2> matrices{ push.view_matrix, push.projection_matrix };
commandBuffer.pushConstants(pipeline_layout_, vk::ShaderStageFlagBits::eTessellationEvaluation, sizeof(glm::mat4), 2 * sizeof(glm::mat4), matrices.data());
Note offset
that is not applied to the push
variable, use Pointer Arithmetic instead: push + sizeof(glm::mat4)
(as the pValue
for vkCmdPushConstants
).