materialLanguageCompiler function
A CpuMaterialCompiler for the engine's material language — P8: the
source parsed and specialised at its declared defaults, as the build does
for the GPU sections beside it, and run by MaterialProgramStage.
Handed to CpuDevice(materialCompiler: ...), a bundle the build made from
a .f3dmat loads on the software backend with nothing registered by hand.
A source that does not parse is refused with its line and column.
Every stage a source becomes — version 2. A bundle carries the source
under each stage's name: the material's own, answered by
MaterialProgramStage or, for a full-screen stage,
MaterialFullscreenStage; and <name>Vertex and <name>VertexSkinned,
answered by MaterialVertexStage, which the library hands out as a
vertex stage.
Implementation
CpuStage materialLanguageCompiler(String stage, String source) {
final program = parseMaterial(source);
final specialised = specializeMaterial(
program,
MaterialVariant(program.name),
);
final vertex = program.vertexStageName;
if (vertex != null && stage == vertex) {
return CpuStage.vertex(MaterialVertexStage(specialised));
}
if (vertex != null && stage == '${vertex}Skinned') {
return CpuStage.vertex(MaterialVertexStage(specialised, skinned: true));
}
// Version 3: the instanced and lightmapped halves.
for (final MapEntry(key: variant, value: name) in materialVertexVariantStages(
program,
).entries) {
if (stage == name) {
return CpuStage.vertex(
MaterialVertexStage(
specialised,
instanced: variant == VertexStageVariant.instanced,
lightmapped: variant == VertexStageVariant.lightmapped,
),
);
}
}
if (program.name != stage) {
throw MaterialBundleException(
'the source is material "${program.name}" and the bundle calls it '
'"$stage"',
);
}
return switch (program.kind) {
MaterialStageKind.fullscreen => CpuStage.fragment(
MaterialFullscreenStage(specialised),
),
MaterialStageKind.compute => throw MaterialBundleException(
'"$stage" is a compute stage, which a bundle carries as its lowered '
'kernel in the kernel section, not as a material: build it again, or '
'load lowerMaterialCompute(program).kernel through kernelBundle',
),
_ => CpuStage.fragment(MaterialProgramStage(specialised)),
};
}