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
…