Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Bug ArgumentException when rendering lots of runtime lights w/o shadows

Discussion in 'High Definition Render Pipeline' started by xVergilx, Jul 19, 2023.

  1. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Unity 2021.3.23f1 + HDRP 12.1.7 (tried 12.1.10 as well);
    I'm getting weird exception that pops up randomly when looking through different portions of the scene.

    Nothing gets rendered at all, since it stalls the entire pipeline.
    This happens in both editor and build. If I pause in playmode and switch to the scene view, look from the same place - scene view stops rendering as well.

    Previously I thought it was tied to VRAM usage, but its actually unrelated.

    Here's a full stack:
    Code (CSharp):
    1. ArgumentException: SetData(): Accessing 36848 bytes at offset 0 for Buffer of size 36736 bytes is not possible.
    2. UnityEngine.ComputeBuffer.SetData[T] (Unity.Collections.NativeArray`1[T] data, System.Int32 nativeBufferStartIndex, System.Int32 computeBufferStartIndex, System.Int32 count) (at <f712b1dc50b4468388b9c5f95d0d0eaf>:0)
    3. UnityEngine.Rendering.HighDefinition.HDRenderPipeline.PushLightDataGlobalParams (UnityEngine.Rendering.CommandBuffer cmd) (at Library/PackageCache/com.unity.render-pipelines.high-definition@12.1.11/Runtime/Lighting/LightLoop/LightLoop.cs:2130)
    4. UnityEngine.Rendering.HighDefinition.HDRenderPipeline.PrepareLightsForGPU (UnityEngine.Rendering.CommandBuffer cmd, UnityEngine.Rendering.HighDefinition.HDCamera hdCamera, UnityEngine.Rendering.CullingResults cullResults, UnityEngine.Rendering.HighDefinition.HDProbeCullingResults hdProbeCullingResults, UnityEngine.Rendering.HighDefinition.LocalVolumetricFogList localVolumetricFogList, UnityEngine.Rendering.HighDefinition.DebugDisplaySettings debugDisplaySettings, UnityEngine.Rendering.HighDefinition.AOVRequestData aovRequest) (at Library/PackageCache/com.unity.render-pipelines.high-definition@12.1.11/Runtime/Lighting/LightLoop/LightLoop.cs:1939)
    5. UnityEngine.Rendering.HighDefinition.HDRenderPipeline.ExecuteRenderRequest (UnityEngine.Rendering.HighDefinition.HDRenderPipeline+RenderRequest renderRequest, UnityEngine.Rendering.ScriptableRenderContext renderContext, UnityEngine.Rendering.CommandBuffer cmd, UnityEngine.Rendering.HighDefinition.AOVRequestData aovRequest) (at Library/PackageCache/com.unity.render-pipelines.high-definition@12.1.11/Runtime/RenderPipeline/HDRenderPipeline.cs:2139)
    6. UnityEngine.Rendering.HighDefinition.HDRenderPipeline.Render (UnityEngine.Rendering.ScriptableRenderContext renderContext, System.Collections.Generic.List`1[T] cameras) (at Library/PackageCache/com.unity.render-pipelines.high-definition@12.1.11/Runtime/RenderPipeline/HDRenderPipeline.cs:1915)
    7. UnityEngine.Rendering.RenderPipeline.InternalRender (UnityEngine.Rendering.ScriptableRenderContext context, System.Collections.Generic.List`1[T] cameras) (at <f712b1dc50b4468388b9c5f95d0d0eaf>:0)
    8. UnityEngine.Rendering.RenderPipelineManager.DoRenderLoop_Internal (UnityEngine.Rendering.RenderPipelineAsset pipe, System.IntPtr loopPtr, System.Collections.Generic.List`1[T] renderRequests, Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle safety) (at <f712b1dc50b4468388b9c5f95d0d0eaf>:0)
    9. UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)
    Here's where it fails:
    Code (CSharp):
    1.         void PushLightDataGlobalParams(CommandBuffer cmd)
    2.         {
    3.             m_LightLoopLightData.directionalLightData.SetData(m_GpuLightsBuilder.directionalLights, 0, 0, m_GpuLightsBuilder.directionalLightCount);
    4.             m_LightLoopLightData.lightData.SetData(m_GpuLightsBuilder.lights, 0, 0, m_GpuLightsBuilder.lightsCount);
    5.             m_LightLoopLightData.envLightData.SetData(m_lightList.envLights);
    6.             m_LightLoopLightData.decalData.SetData(DecalSystem.m_DecalDatas, 0, 0, Math.Min(DecalSystem.m_DecalDatasCount, m_MaxDecalsOnScreen)); // don't add more than the size of the buffer
    7.  
    8.             for (int viewId = 0; viewId < m_GpuLightsBuilder.lightsPerViewCount; ++viewId)
    9.             {
    10.                 HDGpuLightsBuilder.LightsPerView lightsPerView = m_GpuLightsBuilder.lightsPerView[viewId];
    11.                 Debug.Assert(lightsPerView.boundsCount <= m_TotalLightCount, "Encountered bounds counts that are greater than the total light count.");
    12.  
    13.                 /// In the CPU we have stored the left and right eye in one single array, offset by the LightsPerView.boundsOffset. This is before trivial rejection.
    14.                 /// In the GPU we compact them, and access each eye by the actual m_TotalLightCount, which contains the post trivial rejection offset.
    15.                 int inputStartIndex = lightsPerView.boundsOffset;
    16.                 int outputStartIndex = viewId * m_TotalLightCount;
    17.  
    18.                 // <------------------------------------------- Here   ------------------ >
    19.                 // These two buffers have been set in Rebuild(). At this point, view 0 contains combined data from all views
    20.                 m_TileAndClusterData.convexBoundsBuffer.SetData(m_GpuLightsBuilder.lightBounds, inputStartIndex, outputStartIndex, lightsPerView.boundsCount);
    21.                 m_TileAndClusterData.lightVolumeDataBuffer.SetData(m_GpuLightsBuilder.lightVolumes, inputStartIndex, outputStartIndex, lightsPerView.boundsCount);
    22.             }
    23.  
    24.  
    25.             cmd.SetGlobalTexture(HDShaderIDs._CookieAtlas, m_TextureCaches.lightCookieManager.atlasTexture);
    26.             cmd.SetGlobalTexture(HDShaderIDs._EnvCubemapTextures, m_TextureCaches.reflectionProbeCache.GetTexCache());
    27.             cmd.SetGlobalTexture(HDShaderIDs._Env2DTextures, m_TextureCaches.reflectionPlanarProbeCache.GetTexCache());
    28.  
    29.             cmd.SetGlobalBuffer(HDShaderIDs._LightDatas, m_LightLoopLightData.lightData);
    30.             cmd.SetGlobalBuffer(HDShaderIDs._EnvLightDatas, m_LightLoopLightData.envLightData);
    31.             cmd.SetGlobalBuffer(HDShaderIDs._DecalDatas, m_LightLoopLightData.decalData);
    32.             cmd.SetGlobalBuffer(HDShaderIDs._DirectionalLightDatas, m_LightLoopLightData.directionalLightData);
    33.         }
    34.  
    Does anyone know what could be causing this and if there is a workaround?

    Edit: From investigation it seems like HDRP does not like when there are lots of lights stacked in the same frustum volume. Lights are small radius, no shadow maps, no volumetrics. Disabling some lights prevents pipeline from exploding. But any light count should be supported for the deferred, right?
     
    Last edited: Jul 19, 2023
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Ended up writing custom light culling for runtime lights based on distance as a workaround. No issues so far.
    Fortunately content is generated randomly, so no lights are present in the editor. But I guess it would be same black screen in scene view [outside of playmode] if that happens.

    No idea why nobody's run into this issue before.
    ~150 small lights in a camera view isn't that big of a count for the large map.

    In any case, proper error message would be great if its intentional. A fix would be great too.
    Also, I haven't tested if this is the case for the particle system lights as well.
     
  3. Julien_Unity

    Julien_Unity

    Unity Technologies

    Joined:
    Nov 17, 2015
    Posts:
    73
    Looking at the callstack it definitely seems unexpected. It seems like one of our data buffer is undersized (or number of objects is not capped properly).
    If you can make a small repro project, please file a bug report so that we can look at the issue.
     
  4. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Case #IN-48534

    Took a while, but I've managed to isolate it.
    Issue itself seems to be related to the decal projectors as well. Because without them it doesn't seems to happen.
    Objects in the repro scene are pretty much runtime scene dump, sorry for the mess in advance.

    Tried to pack via Repro Wizard and it failed to pack the project (due to some textures).
    Fortunatelly, packed scene still triggers the issue.
     
  5. mgeorgedeveloper

    mgeorgedeveloper

    Joined:
    Jul 10, 2012
    Posts:
    338
    @xVergilx @Julien_Unity sorry for the ping but I'm getting an error message spammed randomly, which has been happening since v2022.3.19 but also is happening in v2022.3.22. I can see the message embedded in the above code "here's where it fails". The message is: "Encountered bounds counts that are greater than the total light count.
    UnityEngine.GUIUtility ProcessEvent (int,intptr,bool&)"

    Not sure if this is an Editor-only issue - because it comes from GUIUtility.ProcessEvent - but it sure does spam thousands of errors into the log which is causing the frame rate to suffer.

    Is there a public link for the above bug report yet?
     
    Last edited: Mar 29, 2024
  6. mgeorgedeveloper

    mgeorgedeveloper

    Joined:
    Jul 10, 2012
    Posts:
    338
    I couldn't set a breakpoint, so I added this error log when light count is invalid.
    Now you can see the error being spammed with the number - the bounds count goes slightly above light count by up to +6 in my quick test.

    BTW this will happen when I'm standing in one scene and just look around long enough. After a while, these numbers get bad. Takes about a minute before the error starts.

    boundscount.png
     
  7. mgeorgedeveloper

    mgeorgedeveloper

    Joined:
    Jul 10, 2012
    Posts:
    338
    I've investigated a little deeper. The "max lights count" value comes roughly from the total of the four different max light count settings in the HDRP asset (see below in pink). This number seems stable and correct.

    In our scene, we have roughly 50 total lights, some of which are disabled (but I don't think that's relevant here).

    Bounds count seems to be the culprit. It starts low. In my screenshot here it is sitting at 77 already, which is higher than all our lights in the scene. If I walk around this area a bit more and rotate the camera, it will eventually go past 107 and then the error spamming begins. So it appears that bounds count is "leaking".

    EDIT: after staying in the same area a little longer, I had bounds count as high as 160+. It is 100% growing over time, so this is a pretty serious bug I guess.

    bounds-count-bug.png
     
    Last edited: Mar 29, 2024
  8. mgeorgedeveloper

    mgeorgedeveloper

    Joined:
    Jul 10, 2012
    Posts:
    338
    UPDATE (NOW I SEE WHAT'S GOING ON)

    Our character prints decals with each footstep (sand indentations). I finally realised that "bounds count" is going up to match total decal instances in the scene. This means if I move around quite a bit printing over 107 decals, the Debug.Assert will fail and cause the error spamming.

    The comparison between bounds count and max light count, is therefore completely meaningless and it's no wonder this causes error spamming.

    bounds-count-logic.png
     
  9. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    267
    This comparison is correct because we also store decals in the cluster. The problem is that the max light count doesn't take into account the cluster count.

    A fix for your issue has been pushed and will be available in future releases, you can track the progress here: https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-68633
     
    mgeorgedeveloper likes this.