Vulkan GLSL & SPIR-V

Vulkan consumes SPIR-V bytecode, not GLSL source:

32.1 Compiling to SPIR-V

Vulkan consumes SPIR-V bytecode, not GLSL source:

OpenGL 4.6 can also load SPIR-V (glShaderBinary + glSpecializeShader).

glslc shader.vert -o vert.spv                    # shaderc (Google)
glslc -O shader.frag -o frag.spv -DUSE_SHADOWS=1
glslangValidator -V shader.comp -o comp.spv      # Khronos reference compiler
glslc --target-env=vulkan1.3 -fshader-stage=compute kernel.glsl -o kernel.spv
spirv-val vert.spv                               # validate
spirv-dis vert.spv                               # disassemble
spirv-opt -O vert.spv -o vert.opt.spv            # optimize
spirv-cross vert.spv --version 330 --no-es       # convert back to GLSL (or HLSL/MSL)

32.2 Vulkan GLSL differences (GL_KHR_vulkan_glsl)

Other differences:

No plain (non-block) uniforms except opaque types.

gl_VertexIndex, gl_InstanceIndex include base vertex/instance.

Clip space: Y points down, depth range [0, 1] (flip Y in the projection matrix or use a negative viewport height).

Subpass inputs for tile-based deferred rendering: layout (input_attachment_index = 0, set = 0, binding = 3) uniform subpassInput gAlbedo; → subpassLoad(gAlbedo).

Buffer device addresses (GL_EXT_buffer_reference): pointer-like references to buffers.

Descriptor indexing (GL_EXT_nonuniform_qualifier): uTextures[nonuniformEXT(index)] for bindless.

GL_EXT_scalar_block_layout for C-like buffer layout.

#version 450

// Descriptor sets and bindings instead of plain uniforms
layout (set = 0, binding = 0) uniform CameraUBO {
    mat4 view;
    mat4 proj;
} camera;

layout (set = 1, binding = 0) uniform sampler2D uAlbedo;               // combined image sampler
layout (set = 1, binding = 1) uniform texture2D uNormalTex;           // separate image...
layout (set = 1, binding = 2) uniform sampler uLinearSampler;         // ...and sampler
// vec4 n = texture(sampler2D(uNormalTex, uLinearSampler), uv);

// Push constants: small, fast per-draw data (≥ 128 bytes guaranteed)
layout (push_constant) uniform PushConstants {
    mat4 model;
    uint materialIndex;
} pc;

// Specialization constants: set at pipeline creation, enable compile-time optimization
layout (constant_id = 0) const int NUM_SAMPLES = 16;
layout (constant_id = 1) const bool USE_FOG = true;

layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNormal;
layout (location = 0) out vec3 outNormal;      // every interface variable needs an explicit location

void main() {
    outNormal = mat3(pc.model) * inNormal;
    gl_Position = camera.proj * camera.view * pc.model * vec4(inPos, 1.0);
    // gl_VertexIndex / gl
…