createPipelineAsync method

  1. @override
Future<PipelineHandle> createPipelineAsync(
  1. ShaderHandle vertex,
  2. ShaderHandle fragment, {
  3. VertexLayoutDescriptor? layout,
})

createPipeline, and the real pipelines it will need built off the calling turn, through createRenderPipelineAsync.

What can be realised up front, and what cannot. A pipeline here is a stage pair until a draw says the rest: the targets it draws into, the blend, the depth test, the cull, the stencil. Those are baked into a GPURenderPipeline, one per distinct state, and none of them is in this call. So the pair is recorded as createPipeline records it, and then warmed: built asynchronously in every draw state this device has already built a pipeline in (the most recent warmStateLimit of them), and kept in the same cache a draw looks in. A draw in one of those states then finds its pipeline ready; a draw in a state nobody drew before builds it synchronously, as always.

The future completes when the warming has settled. A pipeline the browser refuses in one of those states is skipped — the state was a guess, and a draw that really asks for it builds it and reports a refusal on pipelineRefusals — while a pair that cannot be recorded at all (two fragment stages, a stage from another backend, a layout that misses an input) completes the future with the error.

Implementation

@override
Future<PipelineHandle> createPipelineAsync(
  ShaderHandle vertex,
  ShaderHandle fragment, {
  VertexLayoutDescriptor? layout,
}) async {
  final handle = _held(
    createWebGpuPipeline(vertex, fragment, layout: layout, owner: this),
  );
  final pipeline = handle.backend as WebGpuPipeline;
  // A pair whose layouts are refused has nothing to warm: its draws are
  // skipped, and the first of them reports why.
  final layouts = _bindingsFor(pipeline);
  if (layouts == null) return handle;
  await Future.wait(<Future<void>>[
    for (final state in _drawStates.values.toList())
      _warm(pipeline, layouts, state.forPipeline(pipeline)),
  ]);
  return handle;
}