Open erikdubbelboer opened 3 months ago
It seems the glslang here fails to transpile the shader. It usually logs some warning messages to console just before it fails and we log this error. Maybe we could try and see if we can obtain those messages and print them out as part of this error.
So when the compilation fails, we get now this (with PR https://github.com/playcanvas/engine/pull/6681)
We have additional callstack. But ideally we'd capture the (yellow) text the glslang wasm logs and print it ourselves as part of this error. I've tried to override console.log/warn/err, but also glslang.print/printErr but no luck to capture it yet.
@Maksims @kungfooman - any idea how this can be captured?
We call initialize glslang here: https://github.com/playcanvas/engine/blob/f88018583563299d35b300e1e6f2818a0fa54eb1/src/platform/graphics/webgpu/webgpu-graphics-device.js#L186
and use it here: https://github.com/playcanvas/engine/blob/f88018583563299d35b300e1e6f2818a0fa54eb1/src/platform/graphics/webgpu/webgpu-shader.js#L152
repro using engine examples:
shader-toon.shader.frag
and run the Shader Toon
example.It's a bound function:
var x = c.print || console.log.bind(console),
y = c.printErr || console.warn.bind(console);
And c.printErr
isn't accessible through its init system, so it would require some updates to glslang.js
Happy to do some small changes to glslang.js
- what would you suggest?
Happy to do some small changes to
glslang.js
- what would you suggest?
I just realized we can also temporarily overwrite console.warn
until glslang.js
loaded:
Both files belong next to glslang.js for testing:
glslangCaptureSingleError.js
const {warn} = console;
const lastErrors = [];
console.warn = msg => {
lastErrors.push(msg);
warn('Captured', msg);
}
const glslang_ = await import('./glslang.js');
const glslang = await glslang_.default();
// Restore warn method once glslang created a bound warn function out of it.
console.warn = warn;
function compileGLSL(...args) {
lastErrors.length = 0;
try {
glslang.compileGLSL(...args);
} catch (e) {
const tmp = lastErrors.join('\n');
// Rethrow with captured errors.
throw new Error(tmp + e);
}
}
/** @todo Same error capturing for compileGLSLZeroCopy */
const {compileGLSLZeroCopy} = glslang;
export {compileGLSL, compileGLSLZeroCopy};
console.warn("NORMAL WARN");
test.html
<script type="module">
// Now the API even looks readable:
import {compileGLSL} from './glslangCaptureSingleError.js';
try {
const ret = compileGLSL('#version 150\nout herp\nderp\nerrp;', 'fragment');
console.log("ret", ret);
} catch (e) {
console.error("Full error:", e);
}
</script>
Output:
Of course the extraneous console.log
's need to be removed, I just left them for making the captured messages mentally reconstructable in the image.
(I still can't run WebGPU examples on Linux, so I just made up this mini html for testing)
The only objection I can think of is the top level await, but that seems better supported than WebGPU:
Hey that's pretty cool, thanks for looking into this. Considering the import of glslang is async, we disable the console warnings till this is imported .. we might miss printing some other useful warning for the user during that time? I guess we could print them out after the await, but those could be out of order with other messages, or even not print at all if some exception is thrown during that time?
Hey that's pretty cool, thanks for looking into this. Considering the import of glslang is async, we disable the console warnings till this is imported .. we might miss printing some other useful warning for the user during that time?
Right, overwriting console.warn
is definitely wonky, seems like refactoring glslang.js
itself would make most sense, probably should open an issue there?
https://github.com/search?q=repo%3AKhronosGroup%2Fglslang+compileGLSLZeroCopy&type=code
(Otherwise the next version updates will have to jump through the same hoops again or it will be forgotten etc.)
Yeah I look at this, I think the repo is here, but it's not very active https://github.com/kainino0x/glslang.js?tab=readme-ov-file
I'll probably go ahead with your initial suggestion. Override console.warn by a wrapper, that still writes things out, but capture those internally to an array while calling compileGLSL
- that seems like it should have no side-effects.
This error is affecting only a couple of the users of https://poki.com/en/preview/94176748-9ef8-42c9-a44e-a95b70ec5680/da472bf8-04fa-4660-a885-2c2b6b783dda But it seems like an interesting error so I thought I'd create an issue just to be sure.
Affects both mobile and desktop Chrome 125.
I'm afraid I have no stack trace or further information for this error.