0

While I'm aware that my question is probably wrong and that there "shouldn't be anything in the way of having a push constant as a 3x3 matrix", I get a strange issue. These are the relevant parts of the code:

// During command buffer recording
glm::mat3 m(1.0f);
vkCmdPushConstants(cmdBuf, layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat3), static_cast<void*>(&m));
vkCmdDraw(...);

// Vertex shader
layout (location = 0) in vec3 aPosition;
layout (push_constant) uniform PushConstants
{
    mat3 modelMatrix;
};
void main()
{
    vec3 worldPos = modelMatrix * aPosition;
    gl_Position = viewProjection * vec4(worldPos, 1.0f);
}

This results in a blank window where I expect my model to be rendered. YES I am aware that I need a 4x4 matrix to represent translation, right now the question at hand is just why a 3x3 matrix isn't working (assuming correct semantics of the initialization of glm::mat3(1.0f)).

I now make a choice of trying with a 4x4 matrix instead:

// During command buffer recording
glm::mat4 m(1.0f);
vkCmdPushConstants(cmdBuf, layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), static_cast<void*>(&m));
vkCmdDraw(...);

// Vertex shader
layout (location = 0) in vec3 aPosition;
layout (push_constant) uniform PushConstants
{
    mat4 modelMatrix;
};
void main()
{
    gl_Position = viewProjection * modelMatrix * vec4(aPosition, 1.0f);
}

This results in my model getting drawn as expected. Is there something unexpected that I should be handling, like padding the size of the push constant or aligning it somehow?

alexpanter
  • 1,222
  • 10
  • 25
  • I'd have to carefully read through the spec, but I'd guess that the alignment requirements of push constants is the same as uniform buffers (std470 IIRC). I've generally seen GPU alignment specs not directly allow a mat3x3, in the same way they don't directly allow a vec3. – vandench Jul 14 '23 at 14:10
  • @vandench Thank you, though I could also just look myself - just wanted to know if my intuition was completely skewed.. Btw., I have an application working just fine with a vec3 as push constant, so that sounds a bit strange. – alexpanter Jul 14 '23 at 14:13
  • 2
    @alexpanter: "*I have an application working just fine with a vec3 as push constant*" And what about an array of `vec3`? Or having a `vec4` after that `vec3`? `mat3` has all of the problems of a `vec3`, even in push constants. – Nicol Bolas Jul 14 '23 at 14:44
  • @NicolBolas Can I work around this? Your point makes perfect sense, but even when I place my `glm::mat3` in a struct and mark it `alignas(16)` it still doesn't work. Would the solution then be to pack a 3x3 matrix as 3 separate 4-vectors, and then recombine the matrix inside the shader? Simply avoiding 3x3 matrices seems a bit rash – alexpanter Jul 14 '23 at 15:19
  • 1
    *"Simply avoiding 3x3 matrices seems a bit rash"* Historically this was the best solution, not simply because dealing with them was so difficult, but because even some drivers didn't handle them correctly. I've not heard of this problem in the era of vulkan, everyone seems to have sorted it out now, but just not using them is a very common option. That's not to say you can't use them, but it's going to somewhat painful. – vandench Jul 14 '23 at 15:33
  • @vandench I see. Thank you for your input! – alexpanter Jul 14 '23 at 16:06

0 Answers0