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

TypeError: Failed to execute 'shaderSource' on 'WebGLRenderingContext': parameter 1 is not of type 'WebGLShader'. #392

Closed
humphd opened this issue Mar 3, 2022 · 5 comments

Comments

@humphd
Copy link

humphd commented Mar 3, 2022

I'm using jsmpeg in React, and sometimes I get this Failed to execute 'shaderSource' error (usually on tear-down or some re-render), I suspect due to React destroying the canvas context when jsmpeg doesn't expect it.

I notice that mapbox-gl-js had a similar issue, and added checks on the context being lost. Not a deal breaker, but probably something that someone with more knowledge of WebGL could fix.

Regardless, this thing is absolutely amazing. Thanks for sharing, it works so well!

@phoboslab
Copy link
Owner

Can you please check if the above commit fixes your problem?

I'm a bit baffled that you saw this particular error message, since shaderSource() is only executed when the player and renderer are instantiated. So it seems like there's an immediate re-layout from React, right after the JSMpeg Player is created!? Maybe you have to postpone the player creation until after React is definitely done, to avoid an unnecessary contextLost and contextRestored cycle?

@humphd
Copy link
Author

humphd commented Mar 11, 2022

I'll test this over the coming days, but my initial tests have been positive--it looks to be OK. Thanks a lot.

@humphd
Copy link
Author

humphd commented Mar 12, 2022

I'm still hitting this. It's triggered by a re-render in React, so it's probably my bug vs. yours, but in case you're interested, this is what I see:

Screen Shot 2022-03-12 at 10 51 45 AM

Screen Shot 2022-03-12 at 10 56 21 AM

gl.createShader(type) with type=35633 and source=attribute vec2 vertex;\nvarying vec2 texCoord;\nvoid main() { texCoord = vertex;\ngl_Position = vec4((vertex * 2.0 - 1.0) * vec2(1, -1), 0.0, 1.0);\n} returns null.

@humphd
Copy link
Author

humphd commented Mar 14, 2022

I removed my effect's cleanup logic, and this goes away:

useEffect(() => {
   let player;

    function destroy() {
      if (player) {
        player.destroy();
        player = null;
      }
    }

    const canvasElem = canvasElemRef.current;
    if (!(canvasElem && canvasElem instanceof HTMLCanvasElement)) {
      return destroy();
    }

    if (!isVisible) {
      return destroy();
    }

    try {
      player = new window.JSMpeg.Player(src, {
        canvas: canvasElem,
        audio: false,
      });
    } catch (err) {
      console.warn(err);
      destroy();
    }

  // This is causing the crash for me, removing makes things work
  // return () => {
  //   destroy();
  // };
}, [src, canvasElemRef, isVisible])

@phoboslab
Copy link
Owner

player.destroy() tries to free up all resources associated with the WebGL context by explicitly calling .loseContext(). So the WebGL context is not usable after this anymore.

Considering that this happens on re-render, only when you previously call player.destroy() (and I don't know much about React): Is the <canvas> element re-created by React on a re-render, or does it try to "re-use" the previous <canvas> element?

If the element is indeed re-used, then canvas.getContext('webgl') would return the old (destroyed) context and trigger this error. I guess checking for gl.isContextLost() directly after canvas.getContext() (and then restoring it) would fix this issue.

Can you try to explicitly re-create the <canvas> element on a re-render to confirm that this is indeed what's causing the problem?

scarletsky pushed a commit to scarletsky/jsmpeg that referenced this issue Apr 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants