Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to transpile webgl vertex shader [Shader Id 3 LitShader-ShadowPass_1_0-proc] to WebGPU: [GLSL compilation failed] while rendering undefined #6673

Open
erikdubbelboer opened this issue Jun 8, 2024 · 9 comments
Assignees
Labels
area: graphics Graphics related issue bug

Comments

@erikdubbelboer
Copy link
Contributor

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.

@mvaligursky
Copy link
Contributor

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.

@mvaligursky mvaligursky self-assigned this Jun 10, 2024
@mvaligursky mvaligursky added bug area: graphics Graphics related issue labels Jun 10, 2024
@mvaligursky
Copy link
Contributor

mvaligursky commented Jun 10, 2024

So when the compilation fails, we get now this (with PR #6681)

Screenshot 2024-06-10 at 11 17 49

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:

import(`${buildUrl(glslangUrl)}`).then(module => module.default())

and use it here:

const spirv = this.shader.device.glslang.compileGLSL(src, shaderType);

repro using engine examples:

  • make some typo in shader-toon.shader.frag and run the Shader Toon example.

@kungfooman
Copy link
Collaborator

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

@mvaligursky
Copy link
Contributor

Happy to do some small changes to glslang.js - what would you suggest?

@kungfooman
Copy link
Collaborator

kungfooman commented Jun 10, 2024

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:

image

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:

@mvaligursky
Copy link
Contributor

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?

@kungfooman
Copy link
Collaborator

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.)

@mvaligursky
Copy link
Contributor

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

@mvaligursky
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: graphics Graphics related issue bug
Projects
None yet
Development

No branches or pull requests

3 participants