compileModule method
Turns wgsl into a GPUShaderModule, and asks the browser what it
thought of it.
Nothing is thrown for text that does not compile, and nothing can be.
A module is created whether or not the code was valid, the same way a
pipeline is created whether or not the descriptor was — and a bad shader
is not an error scope's business at all: createShaderModule succeeds,
and the complaint arrives at the first pipeline built from it as
[Invalid ShaderModule "X"] is invalid due to a previous error, naming
neither the line nor what was wrong with it. getCompilationInfo has the
line and the column and is a promise, so the verdict cannot reach a caller
standing here. It is thrown at the next beginFrame as a
ShaderCompileException instead (see webgpu_error_ledger.dart), and a
test — open_test.dart is the one that asks a browser what it makes of
the generated WGSL — reads it sooner from debugDrainErrors. The WGSL a
translator produced is WGSL nobody typed.
Every module this backend ever compiles goes through here, the engine's stages and a loaded bundle's alike, so a stage that arrives broken at half past a reload is reported in the same words as one that shipped broken.
Implementation
@override
Object compileModule(String name, String wgsl) {
final module = _gpuDevice.createShaderModule(
GPUShaderModuleDescriptor(code: wgsl, label: name),
);
_ledger.track(
module.getCompilationInfo().toDart.then((GPUCompilationInfo info) {
for (final message in info.messages.toDart) {
if (message.type != 'error') continue;
final line = message.lineNum;
final lines = wgsl.split('\n');
_ledger.complainOfShader(
name,
'line $line, column ${message.linePos}: ${message.message}',
// WebGPU counts both from one, and zero when it names no place.
diagnostic: ShaderDiagnostic(
message.message,
line: line > 0 ? line : null,
column: message.linePos > 0 ? message.linePos : null,
excerpt: line > 0 && line <= lines.length
? lines[line - 1]
: null,
),
);
}
}),
);
return module;
}