Language Syntax
Learn the fundamentals of GPULang syntax and modern language features
Language Basics
GPULang is designed to be familiar to developers coming from C/C++ and modern shader languages, while introducing improvements that make GPU programming more accessible and expressive.
Key Principles
Cross-Platform
Write once, compile to multiple targets including SPIR-V, DXIL, and more.
Program Assembly
Assemble programs in the shader, allowing for link time validation and trivial runtime pipeline setup.
Type Inference
GPULang supports basic type inference, reducing verbosity while maintaining clarity.
Data Types
GPULang provides a comprehensive set of data types optimized for GPU computation.
Scalar Types
Loading types from syntax definition...
Vector Types
GPULang supports vector types from 2 to 4 components:
Loading vector types...
Matrix Types
Matrices are specified as type x rows x columns
:
Loading matrix types...
Texture Types
Various texture types for different dimensionalities and use cases. Texture types containing the Sampled
word is a combined texture and sampler and can't be used with for example textureLoad
.
Loading texture types...
Special Types
Additional specialized types for specific GPU operations:
Loading special types...
Variables and Constants
Variable Declaration
Variables can be declared with explicit types or using type inference:
// Explicit type declaration
var position : f32x3 = f32x3(0.0f, 1.0f, 0.0f);
var count : i32 = 42;
// Type inferred from right hand side
var color = f32x4(1.0f, 0.5f, 0.2f, 1.0f); // inferred as f32x4
var isVisible = true; // inferred as bool
Constants
Constants are declared using the const
keyword:
// Constants
const PI = 3.14159f;
const MAX_LIGHTS = 8;
const DEFAULT_COLOR = f32x4(1.0f, 1.0f, 1.0f, 1.0f);
Type Aliasing
Type aliases can be created using the alias
keyword:
alias Vec3 as f32x3;
alias RGBA as f32x4;
Uniform Variables
Uniform variables are declared using the uniform
keyword. Uniform variables denote an externally provided resource:
// Uniform declarations
uniform ViewConstants : *View;
uniform DiffuseTexture : *texture2D;
Functions
Function Declaration
Functions are declared with return type trailing the parameter list:
// Function with multiple parameters
calculateLighting(position : f32x3, normal : f32x3, lightPos : f32x3) f32x4
{
const lightDir = normalize(lightPos - position);
const intensity = max(dot(normal, lightDir), 0.0f);
return f32x4(f32x3(intensity), 1.0f);
}
Entry Points
Shader entry points are declared using the entry_point
keyword:
// Vertex shader entry point
entry_point
VertexMain(
binding(0) in position : f32x3,
binding(1) in normal : f32x3,
out worldPos : f32x4,
out worldNormal : f32x3
) void
{
worldPos = ViewMatrix * f32x4(position, 1.0f);
worldNormal = normalize((ViewMatrix * f32x4(normal, 0.0f)).xyz);
vertexExportCoordinates(worldPos);
}
Shader Attributes
Functions tagged with entry_point can be provided shader attributes. They will activate based on their program binding point, allowing for the same shader to change its execution mode.
// Compute shader attributes
threads(i32x3(8, 8, 1))
entry_point csMain() void {...}
// Pixel shader attributes
pixel_origin("center")
entry_point psMain() void {...}
Shader Type Switches
GPULang provides a set of built-in booleans to test what execution mode the shader is executing in:
var pixel : i32x2;
// GPULang will determine this branch at compile time
if (gplIsPixelShader)
{
// Pixel shader specific code
pixel = pixelGetCoordinates().xy;
}
else if (gplIsComputeShader)
{
// Compute shader specific code
pixel = computeGetGlobalThreadIndices().xy;
}
Generate
The generate
statement allows for conditional code generation
// Generate a set of functions
generate
<
if (!declared<BlurSize>)
<
const BlurSize = 5;
>
if (!declared<InputComponents>)
{
alias MemType as f32x4;
}
workgroup SharedMemory : MemType[BlurSize];
>
Control Flow
Branching
// If-else statements
if (alpha < 0.5f)
{
discard;
}
else if (alpha < 0.8f)
{
color.rgb *= 0.5f;
}
else
{
color.rgb *= 1.2f;
}
Loops
// For loop
var totalColor = f32x3(0.0f);
for (var i : i32 = 0; i < MAX_LIGHTS; i++)
{
totalColor += calculateLight(position, lights[i]);
}
// While loop
var samples : i32 = 0;
while (samples < MAX_SAMPLES && quality > threshold)
{
// Sampling logic
samples++;
}
Switch
C-like Switch-case is supported in GPULang:
switch (shaderType);
case ShaderTypes.PBR:
{
// PBR shader logic
}
case ShaderTypes.Diffuse:
{
// Diffuse shader logic
}
Uniform Value Loops Work in progress
Uniformely looping over threads sharing the same value is built-in to GPULang:
const cellIndex = ...;
for_uniform(cellIndex)
{
// Access cell value uniformly for all threads sharing cellIndex
const cellValue = uniformData[cellIndex];
// Perform operations with cellValue
}
Structures
Structure Definition
// Material structure
struct Material
{
Albedo : f32x3;
Roughness : f32;
Metallic : f32;
Normal : f32x3;
};
// Light structure
struct Light
{
Position : f32x3;
Tint : f32x3;
Intensity : f32;
Range : f32;
};
Using Structures
// Create and use structures
Material mat;
mat.Albedo = f32x3(0.8f, 0.6f, 0.4f);
mat.Roughness = 0.3f;
mat.Metallic = 0.0f;
// Structure as function parameter
calculatePBR(material : Material, light : Light, viewDir : f32x3) f32x3
{
// PBR calculation logic
return material.Albedo * light.Tint;
}
Shader Programs
Program Definition
Shader programs combine multiple shader stages:
// Render state definition
render_state MyRenderState
{
Cull = CullFace.Back;
DepthTest = true;
DepthWrite = true;
Blend = false;
};
// Program combining shaders
program StandardShading
{
VertexShader = VertexMain;
PixelShader = PixelMain;
RenderState = MyRenderState;
};
Compute Shaders
// Compute shader entry point
threads(i32x3(8, 8, 1))
entry_point
ComputeMain() void
{
const id = computeGetGlobalThreadIndices().xy;
// Compute logic here
outputTexture[id] = inputTexture[id] * 2.0f;
}
// Program combining shaders
program Compute
{
ComputeShader = ComputeMain;
};
Advanced Features
Annotations
GPULang supports annotations for additional metadata which can be retrieved at runtime:
// Annotations for program variants
@Features("Static")
program VariantShader
{
VertexShader = VertexMain;
PixelShader = PixelMain;
};
struct ShaderParams
{
@Edit("Slider") BaseColor : f32x3;
};
uniform Params : *ShaderParams;
Sampler States
// Sampler state definition
sampler_state LinearSampler
{
Filter = FilterMode.Linear;
AddressU = AddressMode.Clamp;
AddressV = AddressMode.Clamp;
Border = Color.Black;
};