bindTexture method
- ShaderHandle shader,
- String slot,
- TextureHandle texture, {
- SamplerOptions? sampler,
Binds texture to the sampler called slot in shader.
One name becomes two bindings, which is the shape of the whole
problem this package's GLSL is edited to solve: sampler2D is one object
in GLSL and two in WGSL, as it is in Vulkan and Metal, so the reflection
carries the pair and this splits the bind across them.
A slot the translator dropped is ignored rather than refused, which is what the WebGL2 backend does for the same reason: the engine gates its call sites on what a material's lighting model declares, and a stage that legitimately optimised a sampler away is not a caller mistake.
A null sampler is SamplerOptions.linearRepeat — the contract's
default, not the constructor's, which is nearest and clamp and which cost
a third backend two percent of every textured golden before the rule was
written down.
Implementation
@override
void bindTexture(
ShaderHandle shader,
String slot,
TextureHandle texture, {
SamplerOptions? sampler,
}) {
final stage = shader.backend as WebGpuShader;
final declared = stage.samplerNamed(slot);
if (declared == null) return;
final backend = texture.backend as WebGpuTexture;
assert(
backend.sampleable,
'the "$slot" slot was handed a texture that is multisampled or '
'deviceTransient, which on this backend is allocated without '
'TEXTURE_BINDING and can only ever be an attachment',
);
_views.putIfAbsent(
declared.group,
() => <int, GPUTextureView>{},
)[declared.textureBinding] = backend.sampledView;
_samplers.putIfAbsent(
declared.group,
() => <int, GPUSampler>{},
)[declared.samplerBinding] = _device.samplerFor(
sampler ?? SamplerOptions.linearRepeat,
);
}