Stages
A stage block groups declarations and functions that belong to a single shader stage.
Syntax
axsl
@stage vertex {
// in/out interface blocks, uniforms, buffers, structs, functions
}The @stage decorator accepts a stage name as a suffix (@stage vertex, @stage fragment, etc.) or followed by a keyword (@stage vertex { ... }). Both forms are equivalent.
Supported Stages
| Stage Name | Output Extension | Purpose |
|---|---|---|
vertex | .vert.glsl | Vertex processing |
fragment | .frag.glsl | Fragment/pixel shading |
geometry | .geom.glsl | Geometry processing (optional) |
compute | .comp.glsl | Compute shaders |
Stage-Local Declarations
Inside a @stage block, the following constructs are available:
Input Interface Block (Inline)
axsl
in Attributes {
@location(0) vec3 a_pos;
@location(1) vec2 a_uv;
} a;Output Interface Block (Inline)
axsl
out FragOut {
vec4 color;
} o;Interface Reference
Reference a global interface definition:
axsl
out Varyings v; // references global 'interface Varyings'
in Varyings v; // in a different stageSee the Interface System guide for details.
Stage-Local Uniform
axsl
@binding(1) uniform mat4 u_model;Stage-Local Buffer (SSBO)
axsl
@std430 @binding(0) buffer InstanceBuffer {
mat4 models[];
} instance;Uniform with Default Value
axsl
uniform float near_plane = -10.0;
uniform bool flag = false;Stage-Local Struct
axsl
struct LocalData {
vec3 color;
float intensity;
};Stage-Local Function
axsl
vec3 compute_lighting(vec3 normal) {
// ...
}Complete Vertex Stage Example
axsl
@stage vertex {
// Input attributes
in Attributes {
@location(0) vec3 a_pos;
@location(1) vec2 a_uv;
@location(2) vec3 a_normal;
} a;
// Output (references global interface)
out Varyings v;
// Uniforms
@binding(0) uniform mat4 u_mvp;
@binding(1) uniform mat4 u_model;
// Main function
void main() {
v.v_uv = a.a_uv;
v.v_normal = mat3(u_model) * a.a_normal;
gl_Position = u_mvp * vec4(a.a_pos, 1.0);
}
}Complete Fragment Stage Example
axsl
@stage fragment {
// Input (references global interface)
in Varyings v;
// Output
out vec4 o_color;
// Uniforms
@binding(2) uniform sampler2D u_texture;
@binding(3) uniform vec3 u_light_dir;
// Stage-local function
float diffuse(vec3 normal, vec3 light_dir) {
return max(dot(normal, light_dir), 0.0);
}
// Main function
void main() {
vec3 normal = normalize(v.v_normal);
float lighting = diffuse(normal, u_light_dir);
vec4 tex_color = texture(u_texture, v.v_uv);
o_color = tex_color * lighting;
}
}Compute Stage Example
axsl
@stage compute {
// Local work group size
layout(local_size_x = 16, local_size_y = 16) in;
// Input/output buffers
@std430 @binding(0) buffer InputBuffer {
float data[];
} input_buf;
@std430 @binding(1) buffer OutputBuffer {
float data[];
} output_buf;
void main() {
uint idx = gl_GlobalInvocationID.x +
gl_GlobalInvocationID.y * gl_NumWorkGroups.x * 16;
output_buf.data[idx] = input_buf.data[idx] * 2.0;
}
}Stage Order
Stages can appear in any order in the source file:
axsl
@stage fragment { ... }
@stage vertex { ... } // fragment before vertex is fineThe compiler will emit separate files for each stage regardless of order.
Optional Stages
You don't need to define all stages. Only define the stages you actually use:
axsl
@version 450;
// Only vertex and fragment, no geometry or compute
@stage vertex { ... }
@stage fragment { ... }This will emit only .vert.glsl and .frag.glsl.