question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Stack overflow with plugin material

See original GitHub issue

I’m getting a RangeError: Maximum call stack size exceeded with material plugins. This happens when this.markAllAsDirty() is called in set isEnabled(), using pretty much the same code from https://playground.babylonjs.com/#P8B91Z#32. This seems to happen only in larger scenes and it’s heavily influenced by loading multiple models and the order they are loaded, so it is difficult to reproduce.

However the problem seems pretty clear: calling the dirty callbacks on set isEnabled() seems to generate a big stack trace, apparently from an infinite loop. From what I’m seeing it calls the plugin constructor again and again, perhaps because of repeated observers? This is a compiled code dump, but one can easily see the loop with the dirty calls.

CausticPluginMaterial | @ | Underwaterb.vue:95
-- | -- | --
  | (anonymous) | @ | Underwaterb.vue:696
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | get | @ | babylon.js:16
  | e.getMaterial | @ | babylon.js:16
  | e._markAllSubMeshesAsDirty | @ | babylon.js:16
  | e._markAllSubMeshesAsAllDirty | @ | babylon.js:16
  | set | @ | Underwaterb.vue:111
  | (anonymous) | @ | Underwaterb.vue:697
  | (anonymous) | @ | babylon.js:16
  | e.notifyObservers | @ | babylon.js:16
  | e | @ | babylon.js:16
  | t | @ | babylon.js:16
  | t | @ | babylon.js:16
  | a.a.DefaultMaterialFactory | @ | babylon.js:16
  | Promise.then (async) |   |  
  | e._loadAsync | @ | babylonjs.loaders.min.js:1
  | (anonymous) | @ | babylonjs.loaders.min.js:1
  | Promise.then (async) |   |  
  | e.importMeshAsync | @ | babylonjs.loaders.min.js:1
  | (anonymous) | @ | babylonjs.loaders.min.js:1
  | Promise.then (async) |   |  
  | e.importMeshAsync | @ | babylonjs.loaders.min.js:1
  | (anonymous) | @ | babylon.js:16
  | p | @ | babylon.js:16
  | (anonymous) | @ | babylonjs.loaders.min.js:1
  | Promise.then (async) |   |  
  | (anonymous) | @ | babylonjs.loaders.min.js:1
  | (anonymous) | @ | babylon.js:16
  | m | @ | babylon.js:16
  | XMLHttpRequest.send (async) |   |  
  | e.send | @ | babylon.js:16
  | p | @ | babylon.js:16
  | p | @ | babylon.js:16
  | P | @ | babylon.js:16
  | R | @ | babylon.js:16
  | t._loadFile | @ | babylon.js:16
  | e._loadFile | @ | babylonjs.loaders.min.js:1
  | e.loadFile | @ | babylonjs.loaders.min.js:1
  | g | @ | babylon.js:16
  | e | @ | babylon.js:16
  | xe.a.OfflineProviderFactory | @ | babylon.js:16
  | e._LoadData | @ | babylon.js:16
  | e.ImportMesh | @ | babylon.js:16
  | t.runTask | @ | babylon.js:16
  | e.run | @ | babylon.js:16
  | e._runTask | @ | babylon.js:16
  | e.load | @ | babylon.js:16
  | Underwater | @ | Underwaterb.vue:224
  | mounted | @ | Underwaterb.vue:1866
  | invokeWithErrorHandling | @ | vue.runtime.esm.js:1863
  | callHook | @ | vue.runtime.esm.js:4235
  | insert | @ | vue.runtime.esm.js:3158
  | invokeInsertHook | @ | vue.runtime.esm.js:6390
  | patch | @ | vue.runtime.esm.js:6609
  | Vue._update | @ | vue.runtime.esm.js:3963
  | updateComponent | @ | vue.runtime.esm.js:4075
  | get | @ | vue.runtime.esm.js:4495
  | run | @ | vue.runtime.esm.js:4570
  | flushSchedulerQueue | @ | vue.runtime.esm.js:4326
  | (anonymous) | @ | vue.runtime.esm.js:1989
  | flushCallbacks | @ | vue.runtime.esm.js:1915
  | Promise.then (async) |   |  
  | timerFunc | @ | vue.runtime.esm.js:1942
  | nextTick | @ | vue.runtime.esm.js:1999
  | queueWatcher | @ | vue.runtime.esm.js:4418
  | update | @ | vue.runtime.esm.js:4560
  | Vue.$forceUpdate | @ | vue.runtime.esm.js:3984
  | (anonymous) | @ | index.js:244
  | (anonymous) | @ | index.js:242
  | (anonymous) | @ | index.js:119
  | ./components/Underwaterb.vue | @ | Underwaterb.vue?869a:29
  | __webpack_require__ | @ | bootstrap:853
  | hotApplyInternal | @ | bootstrap:749
  | hotApply | @ | bootstrap:411
  | cb | @ | process-update.js:76
  | (anonymous) | @ | process-update.js:91
  | Promise.then (async) |   |  
  | check | @ | process-update.js:90
  | push../node_modules/webpack-hot-middleware/process-update.js.module.exports | @ | process-update.js:52
  | processMessage | @ | client.js:279
  | handleMessage | @ | client.js:139
  | handleMessage | @ | client.js:102

My apologies, but I couldn’t get a faithful way to repro this on a PG. Even in my application it doesn’t happen 100% of the time, but it’s often enough (over half of the time). If I would guess (and perhaps be completely wrong), this seems to be caused when the plugin is instantiated as other models are still being loaded in other parallel promises with ImportMeshAsync(). But calling isEnabled in the factory makes the problem happen more often:

    BABYLON.RegisterMaterialPlugin('Caustic', (material) => {
      material.caustic = new CausticPluginMaterial(material);
      material.caustic.isEnabled = true;
      return material.caustic;
    });

Temporary fix: not calling this.markAllAsDirty() on set isEnabled fixes the issue with no apparent side effects (I’m guessing something else calls dirty() in my case). This is perfectly fine to me, but since this is the reference implementation on the documentation I’m reporting the issue to see what to do. Do we just change the doc examples to not call markAllAsDirty()? The examples seem to work just the same without that call.

I’m happy to debug or get more information on request.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
deltakoshcommented, Feb 2, 2022

No worries! you’re part of the family so you have a special treatment 😉

0reactions
brunobgcommented, Feb 2, 2022

My apologies for not posting on the forum first, since this was a straight bug I thought it’d just pollute things there. It won’t happen again.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sharing Material UI to plugins - Stack Overflow
This works really well, but was wondering if there is a better or more correct solution to share the entire framework with the...
Read more >
Integrating Discourse and Stackoverflow? - feature
I'm wondering. Has Stack Overflow ever considered merging Discourse and Stack Overflow together? For https://github.com/mui/material-ui:.
Read more >
Support Stack Overflow - Actions · mui/material-ui - GitHub
MUI Core: Ready-to-use foundational React components, free forever. It includes Material UI, which implements Google's Material Design.
Read more >
Stack Overflow icon in Material Filled Style - Icons8
Download Stack Overflow vector icon in Material Filled style. Available in png, svg, pdf, html code. Modify, resize, recolor Stack Overflow icon.
Read more >
Nissan app developer busted for copying code from Stack ...
That's because there are question-and-answer sites like StackOverflow.com, where any developer can post a programming-related question and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found