Search Unity

Question Why does _StencilWriteMaskMV keep changing value (40 -> 42 -> 40, etc...) Starting in 2021.3.17/18?

Discussion in 'High Definition Render Pipeline' started by dgoyette, Feb 9, 2023.

  1. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Since updating to 2021.3.17 (or perhaps 2021.3.18), I've been seeing that a fair number of materials in my project keep getting modified such that their "_StencilWriteMaskMV" keeps flipping between 40 and 42. I'll notice in version control that the value has changed, and I'll commit the change. Then shortly thereafter the value will change back. It keeps flipping back and forth between 40 and 42.

    I'm not setting this value (to my knowledge) anywhere in my project, and I didn't see this happen prior to updating to either 2021.3.17 or 2021.3.18. What does this property represent? And any ideas of why it would keep switching value like this?

    For what it's worth, maybe this is only happening with materials that I'm making a copy of at runtime? For example, with code like this:

    Code (CSharp):
    1.  
    2.                 for (int rendererIndex = 0; rendererIndex < EmissiveRenderers.Length; rendererIndex++)
    3.                 {
    4.                     var mats = EmissiveRenderers[rendererIndex].materials;
    5.                     _emissiveMaterials[rendererIndex] = mats[EmissiveMaterialIndexes[rendererIndex]];
    6.                     EmissiveRenderers[rendererIndex].materials = mats;
    7.                 }
     
  2. David_GoRu

    David_GoRu

    Joined:
    Jul 18, 2014
    Posts:
    5
    +1 on this. Each time I press play, I get several dozens of changes on materials with the _StencilWriteMaskMV value changing between 40 and 42. This is making the version control unmanageable (specially when working with more people).

    All I've found is that _StencilWriteMaskMV: 42 is only used in DefaultHDParticleMaterial

    Hope someone finds a solution! We've had this bug for a week since updating to 2021.3.18f and is really annoying
     
    dgoyette likes this.
  3. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Just out of curiosity, as I'm tracking down what I think is a related bug: Have you had any issues with Skinned Mesh Renderers turning black? It's probably unrelated, but it's been something I've been seeing since updating to 2021.3.17/18, and it seems to be happening to SkinnedMeshRenderers where the _StencilWriteMaskMV is changing. Anyway, not trying to derail the _StencilWriteMaskMV thread, but just curious if there's a connection.
     
  4. David_GoRu

    David_GoRu

    Joined:
    Jul 18, 2014
    Posts:
    5
    We didn't have that error (luckily!). Might be something different
     
  5. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    This continues to be an issue in the latest HDRP (at least under 2021.3 LTS). I've been trying to figure out the issue from a commit standpoint, but the new structure of the Graphics git repo has me pretty confused.

    I thought I was on to something, as I thought I found a code change that explained the constant switching from 40 to 42.

    Git is telling me that @SebLagarde authored the change, but I can't tell if that's just a huge roll-up of a lot of other changes. Here's the commit:

    https://github.com/Unity-Technologies/Graphics/commit/155158be41a3e3c15653c7215a95d4a16e02a837

    What happened in this commit is

    The change is to file "BaseLitAPI.cs". The newly added code is:

    Code (CSharp):
    1. // ForwardOnly materials with motion vectors are rendered after GBuffer, so we need to clear the deferred bit in the stencil
    2.             if (forwardOnly)
    3.                 stencilWriteMaskMV |= (int)StencilUsage.RequiresDeferredLighting;

    What's very confusing is that the "forwardOnly" value there is being determined with this code:

    Code (CSharp):
    1. bool forwardOnly = !material.HasPass("GBuffer");
    And if I call similar code on the material that's getting changed (mat.GetShaderPassEnabled("GBuffer")), it tells me that GBuffer is enabled. So, I don't understand how "forwardOnly" would ever be false for this material.

    What I'm confident of is: If I set the _StencilWriteMaskMV of many materials to 42, then render completely black, unless they're not moving at all. If I change the _StencilWriteMaskMV back to 40, they render correctly.

    Anyway, this continues to be a confusing issue. The next test will be to confirm whether this is a problem on "legacy" materials only, such that if I create a brand new material this won't happen. We'll see.
     
    Last edited: Apr 5, 2023
    David_GoRu likes this.
  6. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Looking further into this, I think I have an explanation about why
    bool forwardOnly = !material.HasPass("GBuffer");
    is getting the wrong value.

    The reason is that fairly often, the material will only have one "pass" associated with it, named "Unnamed Pass 0". For example, here is some code I'm running against the offending materials to see which shader passes they have:

    Code (CSharp):
    1. foreach (var material in sharedMats)
    2. {
    3.     Debug.Log(material.name);
    4.     for (int i = 0, passCount = material.passCount; i < passCount; ++i)
    5.     {
    6.         Debug.Log($"{material.name}: {material.GetPassName(i)}");
    7.     }
    8. }
    Usually, this prints out 11 different passes, including GBuffer. But, in cases where thee material ends up rendering black, the passCount is 1 instead of 11, and GetPassName(i) produces a value of "Unnamed Pass 0".

    Because the material only has that single pass on it, the
    material.HasPass("GBuffer");
    isn't finding the GBuffer.

    So then the question becomes, what changed in HDRP 12.1.10 that caused my materials to start having "Unnamed Pass 0" in some cases? I don't yet have a highly reliable test case for this. It just ends up happening every few times I enter play mode. But I'll keep looking.
     
    David_GoRu likes this.
  7. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    From what I can tell, whenever I call "renderer.materials" upon entering Play Mode (such as in Start or Awake) there's a very good chance that this will cause the material to have only a single pass, called "Unnamed Pass 0". Because of this, the test to see if the material is forwardOnly gives a false positive, and the material is considered forwardOnly when it is not.

    New under to 12.1.10, in BaseLitGUI.ComputeStencilProperties, is that if forwardOnly is true, then stencilWriteMaskMV get
    StencilUsage.RequiresDeferredLighting
    OR'ed into it.

    This causes the material to render incorrectly with respect to motion vectors, appearing black in cases where the object has any motion. (It may still render if the renderer is perfectly still.)

    I testing going back to 12.1.8, which didn't have this issue, I can see that the material actually still has the Unnamed Pass 0 pass. So that appears to have been happening for some time. But it's not until 12.1.10 that this causes the stencilWriteMaskMV to get changed as a result of it.

    So, I guess the root cause of the issue wasn't introduced under 12.1.10 (why do materials have "Unnamed Pass 0" as their only shader pass when they're instantiated at runtime). 12.1.10 only introduced some behavior that is noticeably impacted by the issue.
     
    David_GoRu likes this.
  8. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    The issue of why I'm seeing "Unnamed Pass 0" on my materials seems pretty straightforward. I've reported bug IN-37607. Basically, any time you call "renderer.materials" in Start/Awake when entering play mode, the materials won't have their correct passes yet. Anything that's evaluating shader passes (such as HDRP checking for BGuffer) will get incorrect results in those cases.

    So I'm going to say the specific issue of _StencilWriteMaskMV is well-understood now. It happens when the material is validated if the material doesn't have a GBuffer pass. This isn't really an issue on its own, expect that the separate "Unnamed Pass 0" bug means that the _StencilWriteMaskMV code is getting incorrect information.

    I'll create a different thread for the "Unnamed Pass 0" bug so that it gets some visibility, since it's now buried in this thread.
     
    David_GoRu likes this.
  9. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Also, for anyone looking to avoid the _StencilWriteMaskMV value changing (@David_GoRu perhaps), a workaround is to make HDRP into a local package, and edit the line that checks if the material is forwardOnly, to keep it from mistaking "<Unnamed Pass 0>" for being forwardOnly. This is within BaseLitGUI.cs:

    Code (CSharp):
    1.         static public void SetupStencil(Material material, bool receivesSSR, bool useSplitLighting)
    2.         {
    3.             // DGG: Test for "<Unnamed Pass 0>" before deciding it's forwardOnly
    4.             bool forwardOnly = material.passCount > 0
    5.                 && material.GetPassName(0) != "<Unnamed Pass 0>"
    6.                 && !material.HasPass("GBuffer");    
     
    David_GoRu likes this.
  10. Marc-Ducret

    Marc-Ducret

    Joined:
    Apr 24, 2015
    Posts:
    12
    I am also experiencing this problem. It happens when I press play, but also when I build my project.
    Fortunately, I don't have that many materials and I don't usually update them, so I can safely revert any changes made to materials. Still, it is painful that it keeps coming back.
    I hope this will be fixed soon!
     
  11. adrien-de-tocqueville

    adrien-de-tocqueville

    Unity Technologies

    Joined:
    Mar 16, 2020
    Posts:
    270
    Hello, indeed there is an issue with GetPassName on the first frame, so the stencil value would not be consistent. This was fixed a while ago, but the 2021.3 backport was missing, it should be good now
     
    David_GoRu and dgoyette like this.
  12. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Just to be extra clear, I believe this bug will be indirectly resolved when UUM-33303 is resolved. (https://issuetracker.unity3d.com/is...in-only-a-single-pass-when-entering-play-mode) A fix for UM-33303 appears to be planned for Unity 2021.3.24 LTS, which is not yet released. So, people should expect to keep seeing this issue until the fix for UM-33303 is released.

    And, it's worth reminding that you may continue to see something similar to this occurring after the fix is released. That's because right now you may have some number of materials with the wrong _StencilWriteMaskMV. After receiving the fix for this issue, Unity will possibly correct some of your messed up materials, setting them to what they should have been all along. That will look like more _StencilWriteMaskMV toggling between 40 and 42, but after the fix it should (hopefully) stay the correct value from now on. Just don't be surprised if you still see some of these value changes after receiving the fix.
     
  13. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    I got a notification today that UUM-33303 has changed it status to "Under Consideration for 2021.3.X" Do you know if this bug is no longer likely to be resolved soon?
     
  14. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
  15. adrien-de-tocqueville

    adrien-de-tocqueville

    Unity Technologies

    Joined:
    Mar 16, 2020
    Posts:
    270
    Hum not sure what happened exactly but the backport on 21.3 was merged 20 days ago, so it should be good i think it's just the issue status that didn't update correctly
     
    dgoyette likes this.
  16. PeterJurkovsky

    PeterJurkovsky

    Joined:
    Jan 15, 2015
    Posts:
    12
    I had the same issue in 2021.3.19f1 in my HDRP project that some skinned mesh renderers were turning completely black (only in Game view, in Scene View it was rendering always correctly) and after upgrading to 2021.3.25f1 this issue disappeared.
     
  17. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Yup, that was a side-effect of this _StencilWriteMaskMV bug, which I was seeing too. It seemed to occur if an SMR was moving. (The bug messed up the motion vectors for the material, or something.) But as of 2021.3.24, it's no longer happening, so does appear to be generally resolved at this point.
     
    adrien-de-tocqueville likes this.
  18. NickJVaccaro

    NickJVaccaro

    Joined:
    Apr 29, 2013
    Posts:
    7
    I just upgraded my project to 2021.3.31, specifically to fix the _StencilWriteMaskMV bug, and it is still occurring. Is that the bug that is supposed to be fixed now, or only the other bug mentioned in this thread? Do I still have to do the workaround that @dgoyette pointed out, i.e. making HDRP into a local package and editing it directly?
     
  19. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    I'm still on 2021.3.30, and this issue isn't occurring anymore on 2021.3.30. I haven't updated to 2021.3.31 yet, so there's some small possibility that it's regressed again in 2021.3.31. If I see that happening when I update to 2021.3.31, I'll mention it here and reopen the issue.

    However, one thing to keep in mind: Even after you update to a version where this issue is fixed, you'll potentially still see changes to _StencilWriteMaskMV in your materials, as Unity "corrects" the values to what they should have been all along. So, assuming that several of your materials have the wrong _StencilWriteMaskMV values on them, you'll see those get corrected when you're on a fixed version. I'd only be concerned if you continue to see this field's value flip-flop on the same material.

    And also note that a similar issue occurs with "DecalProjectorForwardEmissive" property, though that apparently hasn't been fixed yet.
     
  20. NickJVaccaro

    NickJVaccaro

    Joined:
    Apr 29, 2013
    Posts:
    7
    Ahh, thank you for the note! The "correction" could indeed be what's happening, I will keep an eye out for that. If I can confirm whether that is indeed the case, or it's still broken, I'll report back. Thanks so much for your post!