createPipelineFrom method
The pipeline descriptor describes: the entry point every pipeline
input after 1.0 arrives through.
createPipeline cannot gain a parameter within a major (an override has to accept every parameter of what it overrides, so a new one would break every backend written before it), and a new pipeline input as a second member pair (synchronous and asynchronous) per input would leave 1.x with a family of them. A field on PipelineDescriptor breaks nobody, so specialisation constants, a cache blob or a hint of the pass state come as fields here, each with a default that means what a pipeline did before it.
By default it links through createPipeline and gives the pipeline PipelineDescriptor.label through setLabel, so a backend that overrides only createPipeline builds the same pipeline through either form. A backend overrides this one to read a field createPipeline has no room for. The refusal rules are createPipeline's: a pair the driver will not build is reported on pipelineRefusals, not thrown.
Implementation
PipelineHandle createPipelineFrom(PipelineDescriptor descriptor) {
final pipeline = createPipeline(
descriptor.vertex,
descriptor.fragment,
layout: descriptor.layout,
);
if (descriptor.label case final label?) setLabel(pipeline, label);
return pipeline;
}