Language2 min read

Resources

Accessing uniforms, textures, buffers, samplers, and storage images through the resources namespace.

Reading Time
2 min
Word Count
224
Sections
8
Try It Live

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 Edit

Shader-visible resources are declared in the pipeline with resources {} and accessed through resources.* from stages that opt into them.

bwsl
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:

bwsl
resources {
viewMatrix: mat4
projectionMatrix: mat4
time: float
albedoTexture: texture2D
albedoSampler: sampler
particles: buffer<Particle>
}

Each pass selects the resources it uses:

bwsl
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, and mat4
  • custom structs
  • textures such as texture2D, texture3D, textureCube, and texture2DArray
  • sampler
  • buffers such as buffer<Particle> and cbuffer<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>.

bwsl
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:

bwsl
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:

bwsl
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:

bwsl
float4 texel = sample(resources.albedoTexture, resources.albedoSampler, input.uv);

Storage Images

Storage images are used with load and store style intrinsics:

bwsl
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:

bwsl
vertex {
output.position = resources.mvp * float4(attributes.position, 1.0);
}
fragment {
float4 albedo = sample(resources.albedoTexture, resources.albedoSampler, input.uv);
output.color = albedo;
}

Compute:

bwsl
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);
}