bindTexture method

  1. @override
bool bindTexture(
  1. ShaderHandle shader,
  2. String slot,
  3. TextureHandle texture, {
  4. SamplerOptions? sampler,
})
override

Binds texture to the sampler called slot in shader. False when that stage declares no such sampler.

False, never a throw and never a silent success, on every backend. Until 0.8.0 this returned nothing and each backend answered a slot the stage does not have in its own way: Impeller threw "Failed to bind texture", WebGL and WebGPU did nothing, and the software rasteriser bound it anyway. So a renderer that handed PolylineVertex a morph texture it never declared drew every golden on three backends and failed on Metal at the first frame, for three releases. bindUniformBlock has always answered the same question with a bool, and now both do. A backend with no reflection of its stages answers true, for the reason bindUniformBlock gives.

Asked of the stage, not of the program. A sampler the fragment stage declares is false through the vertex stage's handle, on every backend that can tell the two apart.

A shader that declares a sampler must still have something bound to it, so "no texture" is a neutral texture rather than an absent binding.

A null sampler means SamplerOptions.linearRepeat, not the SamplerOptions constructor's own defaults.

Stated because it was not. Both hardware backends had chosen linearRepeat independently, so they agreed and nobody wrote the rule down; the third backend read this interface, took the constructor defaults — nearest and clamp — and every textured picture it drew had hard seams where the others had soft ones. Two percent of every textured golden, and it looked like a filtering bug in the new backend rather than a question the contract had never answered.

Implementation

@override
bool bindTexture(
  ShaderHandle shader,
  String slot,
  TextureHandle texture, {
  SamplerOptions? sampler,
}) {
  if (!shader.mayBindSampler(slot)) return false;
  commands.add(RecordedTexture(slot, texture, sampler, shader: shader));
  if (!_declares(shader, slot, sampler: true)) return false;
  _boundSamplers.putIfAbsent(shader.name, () => <String>{}).add(slot);
  return true;
}