Language3 min read

Language Overview

An introduction to BWSL syntax and core concepts.

Reading Time
3 min
Word Count
480
Sections
12
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

BWSL (Brawl Shading Language) is designed to be familiar to developers who know C-style languages while providing modern features for shader development.

Core Concepts

Pipelines

Every BWSL program starts with a pipeline definition. A pipeline represents a complete rendering setup that can contain multiple passes.

bwsl
pipeline MyPipeline {
// Pipeline contents
}

Passes

Passes represent individual render passes within a pipeline. Each pass contains vertex and fragment shader code.

bwsl
pass "MainPass" {
vertex { /* ... */ }
fragment { /* ... */ }
}

Attributes

Attributes define the vertex input data for your shader:

bwsl
attributes {
position: float3
normal: float3
texcoord: float2
color: float4
}

Resources

Resources are shader-visible values declared directly in the pipeline and provided by the host at runtime:

bwsl
resources {
modelViewMatrix: mat4
projectionMatrix: mat4
normalMatrix: mat3
time: float
sceneColor: texture2D
sceneSampler: sampler
}

Modules

Modules organize reusable shader functions, constants, structs, and enums. They are file-scope declarations, so they can live in separate .bwsl files or next to pipelines in the same source file. Import them with import, optionally give them a local alias with as, and access members through Module::member:

bwsl
import PBR as BRDF
using Material = BRDF::PBRMaterial
shade :: (Material mat, float3 normal) -> float3 {
return BRDF::lambertianDiffuse(mat.albedo) * saturate(normal.y);
}

Use using ModuleName when an already imported module should also contribute functions and constants to unqualified lookup in the current scope.

Use submodule Name extends ParentModule when a separate file or declaration should contribute more members to an existing module namespace; import the parent module to use those members.

Type System

BWSL provides a strong type system with the following primitive types:

TypeDescription
float32-bit floating point
float22-component float vector
float33-component float vector
float44-component float vector
int32-bit signed integer
uint32-bit unsigned integer
boolBoolean value
mat22x2 float matrix
mat33x3 float matrix
mat44x4 float matrix

BWSL matrix source spelling is mat2, mat3, and mat4. Backend names like float2x2, float3x3, and float4x4 are not supported aliases.

Resource types are declared in resources {} blocks:

TypeDescription
texture2D2D texture resource
texture3D3D texture resource
textureCubeCube texture resource
texture2DArray2D texture array resource
samplerSampler state used with texture resources
buffer<T>Structured buffer resource
cbuffer<T>Constant-buffer-style resource

Custom struct resource payloads can be local structs or module-defined structs. In a resources {} block, module-defined structs use Module.Type spelling after importing the module.

Specification Draft

The BWSL source repo includes a canonical spec draft in docs/spec/ and a BNF grammar in docs/spec/bwsl.bnf. Use the public docs for authoring guidance, and use the source-tree spec when you need exact grammar or conformance details for compiler and editor tooling.

Variables and Constants

bwsl
// Local variables
float x = 1.0;
float3 color = float3(1.0, 0.5, 0.0);
// Constants
const float PI = 3.14159265359;
const float3 UP = float3(0.0, 1.0, 0.0);

Control Flow

BWSL supports standard control flow statements:

bwsl
// Conditionals
if (condition) {
// ...
} else {
// ...
}
// Loops
for (int i = 0; i < 10; i++) {
// ...
}
// Early returns
if (alpha < 0.01) {
discard; // Fragment shader only
}

Swizzling

Vector components can be accessed and rearranged using swizzle notation:

bwsl
float4 color = float4(1.0, 0.5, 0.3, 1.0);
float3 rgb = color.rgb; // (1.0, 0.5, 0.3)
float2 rg = color.rg; // (1.0, 0.5)
float r = color.r; // 1.0
// Rearranging
float3 bgr = color.bgr; // (0.3, 0.5, 1.0)
float4 rrra = color.rrra; // (1.0, 1.0, 1.0, 1.0)

You can use either rgba or xyzw notation for swizzling. They're interchangeable.

Next Steps