Page MenuHome

GPU: Push Constants
Confirmed, NormalPublicTO DO

Description

Add the concept of push constants to GPUShader(Interface)
Branch: temp-gpu-push-constants.

What are push constants?

Push constants have been introduced with vulkan and the main difference with uniform buffers are that they are transported inside the command buffer and not bound. A shader can only have a single push constant (struct). Per shader stage the offset can be changed.

There is a minimum (specification) and maximum (physical device property) that should be respected.

GLSL example

layout(push_constant) uniform BlockName {
        int member1;
        float member2;
        ...
} InstanceName; // optional instance name

... = InstanceName.member2; // read a push constant

In openGL this could be written as a UBO

layout(std140) uniform BlockName {
        int member1;
        float member2;
        ...
} InstanceName; // optional instance name

... = InstanceName.member2; // read a push constant
Alternatives

Alternative1: Cross compilation using macros
Cross compilation can be done with a simple macro

#define LAYOUT_PUSH_CONSTANT layout(push_constant)
#define LAYOUT_PUSH_CONSTANT layout(std140)

challenge is that we still need to indetify the push constant in the shader interface for the API. if it is handled as a regular uniform there would be differences when using OpenGL vs Vulkan.

Alternative2: Source parsing.

Using a preprocessor we could detect the push constant and retrieve the needed information. For OpenGL we need the name for locating the binding. This could be written as a string parser.

Alternative3: Source parsing using GLSLANG.

For this case the source parsing could be done by the glslang. this library is already included in the shaderc lib that we want to use for SpirV compilation.

The biggest challenge is that we still need to rewrite the Vulkan GLSL to OpenGL GLSL. This could be done by walking the AST like (https://github.com/KhronosGroup/glslang/blob/master/glslang/MachineIndependent/intermOut.cpp) but that leads to different source code and reduces traceability.

TODO
Both doesn't seem active, but do what we want using AST.

Conclusion

I prefer to use Alternative2 as is a solution that works. Both 1 and 3 are limited and would need alternative 2 to fix their short comings.

The result of the parser would be passed to the ShaderInterface the shader interface can check if a uniform is actually a push constant and register it as a push constant.

Usages:

  • builtin uniforms can be partially moved to push constants. Shaders only uses a small subset of the builtin uniforms (largest internally = 61 floats/244 bytes MODEL, MVP, CLIPPLANES, COLOR, SRGB_TRANSFORM)
NOTE: On Linux/Mesa the maxPushConstatsSize = 128 bytes.

Revisions and Commits