Resources
Accessing uniforms, textures, buffers, samplers, and storage images through the resources namespace.
Pressure-test the syntax
Take the concept from this page into the playground and deliberately break a pass, binding, or type signature to see how the compiler responds.
Try a Live EditShader-visible resources are declared in the pipeline with resources {} and accessed through resources.* from stages that opt into them.
float4 albedo = sample(resources.albedoTexture, resources.albedoSampler, input.uv);
mat4 viewProj = resources.projectionMatrix * resources.viewMatrix;
Particle p = resources.particles[input.instance_id];
Where Resources Come From
Resources are declared in a pipeline-level resources {} block:
resources {
viewMatrix: mat4
projectionMatrix: mat4
time: float
albedoTexture: texture2D
albedoSampler: sampler
particles: buffer<Particle>
}
Each pass selects the resources it uses:
pass "Main" {
use resources { viewMatrix, projectionMatrix, time, albedoTexture, albedoSampler }
fragment {
float4 albedo = sample(resources.albedoTexture, resources.albedoSampler, input.uv);
output.color = albedo;
}
}
The compiler resolves usage from source, assigns bindings automatically, and emits reflection for the host. The resource block is the public declaration surface for shader-visible host data.
Common resource types include:
- scalar, vector, and matrix values such as
float,float3, andmat4 - custom structs
- textures such as
texture2D,texture3D,textureCube, andtexture2DArray sampler- buffers such as
buffer<Particle>andcbuffer<CameraData> - storage images where supported
The exact resource type controls how it can be used from BWSL.
Selecting Resources Per Pass
use resources is pass-scoped. A resource must be selected before that pass can access resources.<name>.
pass "Shadow" {
use resources { lightViewProj }
vertex {
output.position = resources.lightViewProj * float4(attributes.position, 1.0);
}
fragment = null
}
Resources can also be optional. Optional resources create implicit variant facts that can be used for specialization:
pass "Main" {
use resources { albedoTexture?, albedoSampler? }
fragment {
if (variants.has_resource_albedoTexture && variants.has_resource_albedoSampler) {
output.color = sample(resources.albedoTexture, resources.albedoSampler, input.uv);
} else {
output.color = float4(1.0);
}
}
}
Uniforms and Buffers
Uniforms and buffers are read with normal member or index access:
float time = resources.time;
mat4 vp = resources.projectionMatrix * resources.viewMatrix;
Particle particle = resources.particles[input.instance_id];
Sampled Textures
Sampled textures can be accessed through reflected texture bindings:
float4 texel = sample(resources.albedoTexture, resources.albedoSampler, input.uv);
Storage Images
Storage images are used with load and store style intrinsics:
float4 texel = load(resources.inputImage, int2(4, 8), 0);
store(resources.outputImage, int2(4, 8), texel);
Stage Validation
Resource access is validated against how the resource is actually used in the pipeline.
That means:
- invalid stage/resource access is rejected during compilation
- unsupported backend bindings can be surfaced through reflection before runtime
Typical Patterns
Graphics:
vertex {
output.position = resources.mvp * float4(attributes.position, 1.0);
}
fragment {
float4 albedo = sample(resources.albedoTexture, resources.albedoSampler, input.uv);
output.color = albedo;
}
Compute:
compute "Main" [16, 16, 1] {
uint2 gid = input.global_id.xy;
float4 value = load(resources.inputImage, int2(gid), 0);
store(resources.outputImage, int2(gid), value);
}