Template Linkage
A template module is generic: it cannot be
analyzed for wgpu linkage until it is instantiated with concrete type
arguments. This chapter covers how to go from a generic shader to a usable
WgpuLinkage.
Templates cannot be analyzed directly
Calling analyze_wgsl_module on the Source of a template fails:
#![allow(unused)]
fn main() {
let linkage = analyze_wgsl_module(&template::SOURCE);
// Err(Error::TemplateResolution)
}
The analyzer needs concrete types to compute binding sizes and entry-point
signatures. A template’s Source still has unsubstituted generic type
parameters, so there is nothing concrete to link.
Instantiate, then analyze
The correct flow is:
- Get the template’s IR (or
Source). - Call
instantiate::<T1, T2, ...>()to produce a concreteir::Module. - Pass the concrete IR to
analyze_ir_module.
#![allow(unused)]
fn main() {
use wgsl_rs_linkage_wgpu::analyze_ir_module;
use wgsl_rs::*;
let template: &Source = &renderer::SOURCE;
let concrete_ir: ir::Module = template.instantiate::<f32, Vec4f>()?;
let linkage = analyze_ir_module(concrete_ir);
}
ir::Module::generate_linkage() (the IrModuleExt re-export) does the
second step in one call:
#![allow(unused)]
fn main() {
let linkage = concrete_ir.generate_linkage()?;
}
WgpuLinkage owns the concrete IR
WgpuLinkage holds the ir::Module it was given. This matters: the WGSL
source it returns via wgsl_source() is rendered from that exact concrete
IR, so the source always matches what was analyzed. There is no risk of
re-rendering a different template instantiation.
For a non-template Source, analyze_wgsl_module builds the IR internally and
owns it the same way.
Example: instantiate a generic shader
#![allow(unused)]
fn main() {
#[wgsl]
pub mod generic_blit {
use wgsl_rs::std::*;
pub struct Params<T> { pub scale: T, pub bias: T }
uniform!(PARAMS, Params<Vec4f>); // concrete after instantiation
texture!(SRC, Texture2d);
sampler!(SMP, Sampler);
#[vertex]
pub fn vs(...) -> VertexOutput { /* ... */ }
#[fragment]
pub fn fs(in: VertexOutput) -> Vec4f {
let c = textureSample(SRC, SMP, in.uv);
c * PARAMS.scale + PARAMS.bias
}
}
// In application code:
use wgsl_rs::*;
let concrete = generic_blit::SOURCE.instantiate::<Vec4f>()?;
let mut linkage = concrete.generate_linkage()?;
let shader = linkage.shader_module(&device);
let layout = linkage.pipeline_layout(&mut linkage, &device, Some("blit"));
// ... build pipeline as usual
}
Summary
| Step | API |
|---|---|
| Instantiate template IR | source.instantiate::<T...>() -> ir::Module |
| Analyze concrete IR | analyze_ir_module(ir) -> WgpuLinkage |
| Or, combined | ir.generate_linkage() -> WgpuLinkage |
| Analyze concrete source | analyze_wgsl_module(&source) -> WgpuLinkage |