checkStageAgreement function
List<StageMismatch>
checkStageAgreement({
- required StageInterface vertex,
- required StageInterface fragment,
- List<
StageVariable> ? attributes,
Whether vertex and fragment, the stages of one pipeline, agree —
and with attributes, the vertex layout the pipeline is drawn with,
when it is known. Every mismatch, in the order found; empty when they
agree.
The check the bundle writer runs over every pipeline it writes (amendment 5): before this, a fragment stage reading a varying its vertex stage never wrote compiled on every backend and drew zeros on one, garbage on another, and failed to link on a third.
What it holds:
- every input of
fragmentis an output ofvertexwith the same type, and the same location where both state one (StageMismatchKind.varying); an output nobody reads is not a mismatch; - every input of
vertexis inattributeswith the same type, whereattributesis given (StageMismatchKind.attribute); - a uniform block both stages declare has the same members, in the same order, with the same types (StageMismatchKind.block).
Implementation
List<StageMismatch> checkStageAgreement({
required StageInterface vertex,
required StageInterface fragment,
List<StageVariable>? attributes,
}) {
final found = <StageMismatch>[];
final pair = '"${vertex.name}" and "${fragment.name}"';
for (final input in fragment.inputs) {
final output = vertex.outputs.where((o) => o.name == input.name);
if (output.isEmpty) {
found.add(
StageMismatch(
kind: StageMismatchKind.varying,
name: input.name,
says:
'"${fragment.name}" reads the varying ${input.name}, which '
'"${vertex.name}" does not write',
),
);
continue;
}
final written = output.first;
if (written.type != input.type ||
(written.location != null &&
input.location != null &&
written.location != input.location)) {
found.add(
StageMismatch(
kind: StageMismatchKind.varying,
name: input.name,
says:
'$pair disagree about the varying ${input.name}: '
'"${vertex.name}" writes $written, "${fragment.name}" reads $input',
),
);
}
}
if (attributes != null) {
for (final input in vertex.inputs) {
final given = attributes.where((a) => a.name == input.name);
if (given.isEmpty) {
found.add(
StageMismatch(
kind: StageMismatchKind.attribute,
name: input.name,
says:
'"${vertex.name}" reads the attribute ${input.name}, which the '
'vertex layout does not give it',
),
);
} else if (given.first.type != input.type) {
found.add(
StageMismatch(
kind: StageMismatchKind.attribute,
name: input.name,
says:
'"${vertex.name}" reads ${input.name} as ${input.type}, and the '
'vertex layout gives it as ${given.first.type}',
),
);
}
}
}
for (final MapEntry(key: block, value: members) in vertex.blocks.entries) {
final other = fragment.blocks[block];
if (other == null || _sameMembers(members, other)) continue;
found.add(
StageMismatch(
kind: StageMismatchKind.block,
name: block,
says:
'$pair declare the block $block differently: '
'{${members.join('; ')}} against {${other.join('; ')}}',
),
);
}
return found;
}