1
votes

I have been reading through Sascha Willem's example on push constants here and have attempted to implement them myself.

Oddly the VkPhysicalDeviceProperties.limits.maxPushConstantsSize is 1437341456 bytes which makes me think something else is very wrong. After rechecking it is showing as a more realistic value of 256 (I assume I did something incorrectly previously)

In my test project I have uniform buffers working, and I then started to tinker with push constants which will hopefully explain the inbetween state of my vertex shader

Here are some details of what I implemented: From what I understand, on creating a pipeline layout I need to specify the push constant ranges, which I do like so:

VkPushConstantRange pushConstantRange {};
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(ObjectPushConstantData);

And I add the push constant ranges to the pipeline layout CI like so:

pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;

When creating my command buffers, I'm calling vkCmdPushConstants before drawing like so:

vkCmdPushConstants(this->commandBuffers[i], this->pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, static_cast<uint32_t>(sizeof(ObjectPushConstantData)), &testObject);
vkCmdDrawIndexed(this->commandBuffers[i], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
   

The type ObjectPushConstantData looks like so:

struct ObjectPushConstantData {
    glm::vec3 position;
    glm::vec3 rotation;
};

My vertex shader looks like this:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform UniformBufferObject {
    mat4 model;
    mat4 view;
    mat4 proj;
} ubo;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;

layout(push_constant) uniform PushConsts {
    vec3 position;
    vec3 rotation;
} pushConsts;

layout(location = 0) out vec3 fragColor;

void main() {
    gl_Position = ubo.proj * ubo.view * ubo.model * vec4(pushConsts.position, 1.0);
    fragColor = inColor;
}    

 
1
Do you recreate command buffers per frame? Or do you only create them once? And I'm not sure about the usage of vec3 there might be alginment issues, try to use vec4 and gl::vec4 instead. - churill
In this case I create them when recreating the swapchain due to resize etc - Tom Martin
I have also tried vec4, with no success, I believe the alignment is 4bytes in push constants - Tom Martin
I'm not entirely sure, but I think you need to recreate them every frame, because the push constant data will be copied into the command buffer immediately (it doesn't store pointer but copies the actual data). That's at least how I understand them. - churill
The entire point of push constants is to push data per frame to a command buffer, they are constant from the perspective of the shader. Even if they couldn't change per frame, I would expect something to render. - Tom Martin

1 Answers

1
votes

After taking a look at your shader, this does not seem to be a problem related to the push constants, but rather the lack of taking the actual vertex position into account.

In this line:

gl_Position = ubo.proj * ubo.view * ubo.model * vec4(pushConsts.position, 1.0);

You only multiply the push constant position, which is uniform for all shader invocations.

It seems you forgot to include the actual vertex position, to which you'd typically just add your uniform push constant position like this:

gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition + pushConsts.position, 1.0);