# When is customShaderNameResolve called?

**URL:** <https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783>\
**Category:** Questions\
**Created:** [December 22, 2022, 3:08am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783 "2022-12-22T03:08:02Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 22, 2022, 3:08am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/1 "2022-12-22T03:08:02Z")

</div>

I’m making some custom shaders and replacing the source code of Babylon shaders. I’m using the `customShaderNameResolve` method. For some reason, sometimes this seems to get called every frame. Is this supposed to get called every frame?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 22, 2022, 9:29am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/2 "2022-12-22T09:29:22Z")

</div>

No, if it is called every frame it means the material effect is recreated each frame which should normally not happen. It means you are doing some changes on the material that triggers a recompilation each frame.

---

<div class="post-metadata">

**Author:** ![sebavan](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/sebavan/32/57_2.png) [@sebavan](https://forum.babylonjs.com/u/sebavan)\
**Post date:** [December 22, 2022, 8:44pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/3 "2022-12-22T20:44:30Z")

</div>

A repro would be great if it happens without changing materials properties on standard/pbr/nme as it could be a pretty annoying bug ?

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 26, 2022, 4:18pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/4 "2022-12-26T16:18:04Z")

</div>

I found at least one case I don’t understand, my material `defines._renderId` is for some reason always behind the scene’s renderID. I discovered this by debugging `PushMaterial.prototype._isReadyForSubMesh`. Every frame, the `defines._renderId` is two lower than the scene render ID.

 ![Screen Shot 2022-12-26 at 11.15.20 AM](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/0/b/0b10d677db7be0586a601afa07ea3594780b88e3.png)

Both render IDs increment every frame, but the mesh material is always lower.

I’m trying to track down how my material gets into this state.

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 26, 2022, 5:01pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/5 "2022-12-26T17:01:03Z")

</div>

I seem to get into this state when, on my material, I set `material.bumpSampler = someTexture`, where I have `someTexture` previously set as `new BABYLON.Texture('/somefile.jpg', scene)`. I’m not re-creating `someTexture` every frame. But the act of setting this property:

```auto
sceneData.mesh.material[input.property] = newValue

```

Where `input.property` is `bumpSampler`, then I get into the state where the renderID lags behind the scene.

I’m only setting this value once, I don’t set `bumpSampler` every loop.

I’m trying to re-create what my code is doing in a playground. I haven’t yet been able to reproduce my bug in a playground, but you can see generally what I’m doing at this link, if anything looks out of place:

> **[Babylon.js Playground](https://playground.babylonjs.com/#YPXI4C%2312)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 26, 2022, 5:29pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/6 "2022-12-26T17:29:52Z")

</div>

This is not a bug, it’s normal operation.

`scene.renderId` is incremented once if render targets are enabled (which is the default, even if there are no render targets to render) and once more before each camera is processed. Thus, at each frame, `scene.renderId` is incremented by at least 2 (more if there are render targets, more than one camera, or for other reasons).

The `PushMaterial._isReadyForSubMesh` function is an optimization to avoid checking a material more than once in a frame. So the first time this function is run (for a material/subMesh) for a frame, you will have a difference between `defines._renderId` and `scene.renderId` of at least 2.

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 26, 2022, 8:32pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/7 "2022-12-26T20:32:51Z")

</div>

I think I’m confused, because you said:

> if [customShaderNameResolve] called every frame it means the material effect is recreated each frame which should normally not happen

But now you are saying

> This is not a bug, it’s normal operation.

In my debugging image, you can see that `_isReadyForSubMesh` is `false`. The call stack looks like:

`Mesh.prototype.render` calls `material.isReadyForSubMesh(...)`.

That itself calls `this._isReadyForSubMesh(subMesh)` and inside of there it checks `defines._renderId === this.getScene().getRenderId()` which you’re saying will always be false.

So then back up in `isReadyForSubMesh` it continues on to call `var effect = this._prepareEffect(...)` which itself calls `customShaderNameResolve`.

So because the render IDs are different every frame, `customShaderNameResolve` is called every frame.

Is this expected behavior? Is something else in `isReadyForSubMesh` supposed to bail out before it gets to `_prepareEffect` to avoid `customShaderNameResolve` getting called every frame?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 26, 2022, 9:58pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/8 "2022-12-26T21:58:16Z")

</div>

> [@andyray](#):
>
> That itself calls `this._isReadyForSubMesh(subMesh)` and inside of there it checks `defines._renderId === this.getScene().getRenderId()` which you’re saying will always be false.

Not exactly, it will be `false` the first time it is called in a frame, but `true` in case it is called multiple times in the same frame.

> [@andyray](#):
>
> So then back up in `isReadyForSubMesh` it continues on to call `var effect = this._prepareEffect(...)` which itself calls `customShaderNameResolve`.

No, `this._prepareEffect(...)` won’t call `customShaderNameResolve` if `defines.isDirty === false`.

The fact that in your case `customShaderNameResolve` is called every time means that `defines.isDirty === true`, which means that you are modifying the material with every frame and dirtyfies it. You should find out why the material is dirty in each frame.

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 26, 2022, 10:52pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/9 "2022-12-26T22:52:22Z")

</div>

Hmm. You’re right, `defines._isdirty` is true. When I compare the `defines` object between two frames, only one key is different between the frames, which is `_renderId`. I’m not explicitly setting `_renderId`. All the other keys/values on the two defines objects are `===` identical.

Does Babylon’s internals setting `_renderId` mark the defines as dirty?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 26, 2022, 11:32pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/10 "2022-12-26T23:32:42Z")

</div>

No, `renderId` is set to `scene.renderId` at the end of `isReadyForSubMesh` and does not dirtyfy the material.

You should look at these properties of the `defines` object:

```auto
    public _areLightsDirty;
    public _areLightsDisposed;
    public _areAttributesDirty;
    public _areTexturesDirty;
    public _areFresnelDirty;
    public _areMiscDirty;
    public _arePrePassDirty;
    public _areImageProcessingDirty;

```

You should have at least one being `true` when `defines.isDirty == true`. That should help you find which changes to the material dirtyfies it.

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 27, 2022, 12:53am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/11 "2022-12-27T00:53:53Z")

</div>

Interesting. All of my \_are\* keys appear to be false, but \_isDirty is still true. Here’s a copy-paste from all of those keys:

```auto
_areAttributesDirty: false
_areFresnelDirty: false
_areImageProcessingDirty: false
_areLightsDirty: false
_areLightsDisposed: false
_areMiscDirty: false
_arePrePassDirty: false
_areTexturesDirty: false
_isDirty: true
_keys: (218) [...]
_needNormals: true
_needUVs: true
_normals: true
_renderId: 9976
_uvs: true

```

The only key suffixed with “Dirty” that’s true is the `_isDirty`. Do either any of the other keys like \_needsNormals affect dirty?

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 27, 2022, 12:58am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/12 "2022-12-27T00:58:30Z")

</div>

Still tracing, looks like `markAsUnprocessed()` is getting called because `_isReadyInternal` returns false, because there is no `_pipelineContext` on the effect? Each frame it gets to the last line of this method

```auto
    Effect.prototype._isReadyInternal = function () {
        if (this._isReady) {
            return true;
        }
        if (this._pipelineContext) {
            return this._pipelineContext.isReady;
        }
        return false;
    };

```

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 27, 2022, 1:22am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/13 "2022-12-27T01:22:30Z")

</div>

I’m starting to suspect this is happening because my shader is failing to compile, causing no pipeline context to be created, but I’m still investigating.

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 27, 2022, 4:20am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/14 "2022-12-27T04:20:01Z")

</div>

I might need to open a separate thread for this.

I found an issue, which has been confusing me for a while. I have been getting a compile error after setting valid GLSL inside of `processFinalCode`. After some debugging it seems like `processFinalCode` is a poor API name, because it’s not “final.”

In the GLSL I put in `proessFinalCode`, I create my own out variable, as in `out vec4 myCustomOut;`. Babylon also apparently hijacks the code after `processFinalCode` and adds its own out variable: [https://github.com/BabylonJS/Babylon.js/blob/6fa632432ec5e7940933922c5018ccfd25aa2c47/packages/dev/core/src/Engines/WebGL/webGL2ShaderProcessors.ts#L32](https://github.com/BabylonJS/Babylon.js/blob/6fa632432ec5e7940933922c5018ccfd25aa2c47/packages/dev/core/src/Engines/WebGL/webGL2ShaderProcessors.ts#L32)

```auto
code = code.replace(/void\s+?main\s*\(/g, (hasDrawBuffersExtension ? "" : "out vec4 glFragColor;\n") + "void main(");

```

The end result of this is my shader ends up containing two output variables:

```auto
out vec4 myCustomOut;
...
out vec4 glFragColor;
void main() {

```

This causes the GLSL error:

> Error: FRAGMENT SHADER ERROR: 0:114: ‘myCustomOut’ : must explicitly specify all locations when using multiple fragment outputs  
> ERROR: 0:658: ‘glFragColor’ : must explicitly specify all locations when using multiple fragment outputs

My suspicion is that the invalid GLSL in the shader causes a compilation failure which prevents creation of a pipeineContext, which I first noticed as customShaderNameResolve getting called on each frame. At least, I think, I’m not sure. I can’t reproduce this bug in the playground I linked above. If I enter invalid GLSL in the textarea then I don’t see `customShaderNameResolve` called in a loop. Is there some edge case bug in Babylon where invalid GLSL causes `customShaderNameResolve` to get called every frame?

My goal is to take the raw GLSL created by a Babylon PBRMaterial, manipulate it with a compiler, and then put the compiled GLSL back into the source code of a new PBRMaterial. Is there a way to prevent Babylon from manipulating the code after the process **Final** Code method? I’m trying to set my own `out` variable, which is conflicting with the one that Babylon hijacks the GLSL with.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 27, 2022, 12:29pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/15 "2022-12-27T12:29:51Z")

</div>

Yes, you need to fix the compilation errors you have first, because once you fix them, your other errors might disappear.

> [@andyray](#):
>
> Is there a way to prevent Babylon from manipulating the code after the process **Final** Code method?

In fact, **processFinalCode** is really called as a last step: the injection of `out vec4 glFragColor` is done before, so you can remove it by string manipulation if you want (replacing it with an empty string - there’s no way to avoid Babylon doing this injection).

See this PG:

> **[Babylon.js Playground](https://www.babylonjs-playground.com/#KWVY94%2312)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

It dumps the fragment code from the `processFinalCode` callback: you will see that `out vec4 glFragColor` is there.

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 27, 2022, 7:56pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/16 "2022-12-27T19:56:25Z")

</div>

Making progress! I think what I’m seeing happening is that my material `customShaderNameResolve`/`processFinalCode` is getting called multiple times as part of my compilation process. I intentionally bail out of `customShaderNameResolve` if my internal compiled source code hasn’t changed. I’m trying to determine if that’s the issue - that on subsequent calls of `customShaderNameResolve` for (what should be) the same custom material, since I bail out, it doesn’t set `processFinalCode`, so it doesn’t remove the `glFragColor` line on subsequent calls.

In my compiler, what I’m trying to do is:

- I kick off my compile process, something like `myEngine.compile()`

- I create a `new PBRMaterial` and create a `processFinalCode` so that I can scrape its source code.

- Right after creation, I call `newPbrShaderMaterial.forceCompilation(mesh)` to force the scrape to occur. My expectation is that `forceCompilation` is a synchronous operation, all within the same frame.

- I (synchronously) pass the returned source code back to the scene component, which itself creates a `new PBRMaterial` with `processFinalCode` that injects the compiled source code (the first paragraph of this post).

I have a few questions now, because I think my assumptions are wrong:

1. Can I count on `forceCompilation` to be synchronous like I am to scrape the source code? Or must I wait until the callback happens? The code path I described works, I get the initial PBR source code synchronously (I think).

2. When I call `newPbrShaderMaterial.forceCompilation(mesh)` - I think it also causes the mesh’s current material to recompile. Does cause both `newPbrShaderMaterial` and `mesh.material` to recompile? Does it cause any other materials in the scene to recompile? Can I force the compilation of a single material only?

3. I notice you call the original \_saveCustomShaderNameResolve on the shader - should I be doing that in my case? What is the risk of not doing that?

Thanks for your help by the way, you’ve moved me very far along.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 27, 2022, 8:32pm UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/17 "2022-12-27T20:32:26Z")

</div>

> [@andyray](#):
>
> Can I count on `forceCompilation` to be synchronous like I am to scrape the source code?

No, it is not synchronous, except if you set `engine.getCaps().parallelShaderCompile = null`. It can be synchronous even when `parallelShaderCompile` is enabled, depending on the fact that the effect already exists or not. If it does not exist and a new one must be created, then it is not synchronous because it “waits” (using `setTimeout` regularly) for the effect to be ready before calling the `onCompiled` callback.

> [@andyray](#):
>
> Does cause both `newPbrShaderMaterial` and `mesh.material` to recompile?

No, only the material for which you call `forceCompilation` will be recompiled, for the mesh you pass in parameter.

> [@andyray](#):
>
> I notice you call the original \_saveCustomShaderNameResolve on the shader - should I be doing that in my case? What is the risk of not doing that?

If you know that nobody else will have registered a `customShaderNameResolve` then you are safe not calling the existing one (if it exists). In any case, it’s not used by the system, so you can’t generate internal errors if you don’t call an existing `customShaderNameResolve`.

---

<div class="post-metadata">

**Author:** ![andyray](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/andyray/32/21767_2.png) [@andyray](https://forum.babylonjs.com/u/andyray)\
**Post date:** [December 29, 2022, 12:43am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/18 "2022-12-29T00:43:47Z")

</div>

Ah, ok, I think I have been able to reproduce the specific bug that’s confusing me.

Click “change texture” and observe the console. [https://playground.babylonjs.com/#YPXI4C#19](https://playground.babylonjs.com/#YPXI4C#19)

How can this infinite dirty/re-check be prevented when modifying a material such as this? And why does it only happen when a material is added?

From debugging the code, it’s because the `renderId` is different in `_isReadyForSubMesh`.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 29, 2022, 10:26am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/19 "2022-12-29T10:26:54Z")

</div>

You are doing `defines.AMBIENTDIRECTUV = 0.00001 * id();` in the callback, so in effect you are dirtyfying the material each time the callback is called. [EDIT] Hum, not so sure, even if removing the line makes it work… Disabling parallel shading compilation makes it also work, so I will have to debug it when I come back to work next week. [/EDIT]

You probably don’t need this line, as `customShaderNameResolve` being called means the effect is being recreated.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [December 29, 2022, 10:53am UTC](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783/20 "2022-12-29T10:53:35Z")

</div>

Assigned @Evgeni\_Popov on December 29, 2022, 10:53am UTC



[Next page](https://forum.babylonjs.com/t/when-is-customshadernameresolve-called/36783.md?page=2)
