Search code examples
glslshadervulkan

Declare struct outside layout block to allow reuse in multiple shaders


I'm using GLSL for shaders in my Vulkan application. I'm refactoring some shader code to declare a struct in a common GLSL file. The struct is used in multiple uniforms across different shaders.

Shader code to refactor:

layout (set = 0, binding = 0) uniform Camera
{
    mat4 projection;
    mat4 view;
    vec3 position;
} u_camera;

I would like to move the definition of what is a Camera to a common GLSL include file, but I don't want to move the whole layout statement because the descriptor set index might change from shader to shader. I'd like to only move the definition of Camera.

Here's what I tried:
In my common GLSL file:

struct Camera
{
    mat4 projection;
    mat4 view;
    vec3 position;
};

Then in my shader:

layout (set = 0, binding = 0) uniform Camera u_camera;

However, I get a shader compiler error on that line in my shader: error: '' : syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON

I'm using version 450 (I can upgrade if necessary). No extensions enabled.
Is it possible to do what I want? If yes, please guide me towards how to do it. If not, please try to explain why if it's in the spec.


Solution

  • What you're describing is a legacy GLSL uniform, which can't be used in Vulkan. In Vulkan you have to create a uniform block instead:

    layout (set = 1, binding = 0) uniform CameraBlock {
        Camera u_camera;
    };
    

    While this looks like something nested, you can still access the members of your u_camera directly:

    vec3 some_vec = u_camera.position;