TECHARTNOMAD | TECHARTFLOWIO.COM

TECH.ART.FLOW.IO

[번역] URP 17, RenderGraph Invalid version: 20

jplee 2024. 10. 6. 22:30

역자의 말: Zenn 블로그에 렌더그래프 기사가 많은 편이네요. 렌더타깃에 대한 쓰기 회수 제한에 관한 고민의 흔적이 있어서 소개 해 봅니다.

저자

환경

  • Unity 6000.0.15f1
  • Universal RP 17.0.3
  • 2D Rendererカスタム

Invalid version: 20

기존 프로젝트의 Unity 버전업에 따라 URP를 14에서 17로 업그레이드하고 다양한 커스텀 렌더링 경로를 RenderGraph에 대응시켰는데, 매 프레임마다 Render Graph Execution Error라는 에러가 발생했습니다.프레임마다 Render Graph Execution Error라는 오류가 발생하게 되었습니다.

Render Graph Execution error
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

Render Graph 마이그레이션에 따른 오류는 이전에도 여러 번 보아왔지만, 오류가 발생하기 시작하는 첫 번째 프레임에 예외 등이 발생하는 경향이 있는 것 같습니다.

이번에도 대량의 로그를 거슬러 올라가면 가장 먼저 다음과 같은 오류를 발견할 수 있습니다.

Exception: Invalid version: 20
UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler.ResourcesData.Index (UnityEngine.Rendering.RenderGraphModule.ResourceHandle h) (at ./Library/PackageCache/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/ResourcesData.cs:304)
UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler.ResourcesData.get_Item (UnityEngine.Rendering.RenderGraphModule.ResourceHandle h) (at ./Library/PackageCache/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/ResourcesData.cs:325)
UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler.NativePassCompiler.BuildGraph () (at ./Library/PackageCache/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.cs:261)
UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler.NativePassCompiler.Compile (UnityEngine.Rendering.RenderGraphModule.RenderGraphResourceRegistry resources) (at ./Library/PackageCache/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/NativePassCompiler.cs:84)
UnityEngine.Rendering.RenderGraphModule.RenderGraph.CompileNativeRenderGraph (System.Int32 graphHash) (at ./Library/PackageCache/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.Compiler.cs:20)
UnityEngine.Rendering.RenderGraphModule.RenderGraph.Execute () (at ./Library/PackageCache/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs:1221)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

조사

소스를 보러 가자.

https://github.com/Unity-Technologies/Graphics/blob/fc267ad41df7e0cf39300c4c4d57dd1dc890c054/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/ResourcesData.cs#L298-L307

// Flatten array index
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int Index(ResourceHandle h)
        {
#if UNITY_EDITOR // Hot path
            if (h.version < 0 || h.version >= MaxVersions)
                throw new Exception("Invalid version: " + h.version);
#endif
            return h.index * MaxVersions + h.version;
        }
 

아직 잘 모르겠지만, ResourceHandle의 버전이 MaxVersions를 초과하면 오류가 발생하는 것 같습니다.

이 ResourceHandle은 RenderGraph에서 텍스처 등에 대한 핸들이며, 특정 프레임 내 리소스의 상태 변화를 버전 값으로 저장하고 있습니다.

예를 들어, RenderGraph에서 경로를 실행할 때 다음과 같은 코드로 쓰기 대상 리소스를 선언한다.

UniversalResourceData resourcesData = frameData.Get<UniversalResourceData>();
using (var builder = renderGraph.AddRasterRenderPass<CopyPassData>("Copy Pass",
           out var passData, profilingSampler))
{
    // cameraColorを書き込み対象として宣言
    builder.SetRenderAttachment(resourcesData.cameraColor, 0, AccessFlags.Write);

    /* パスの発行 */
}

사실 이 때 SetRenderAttachment() 호출을 통해 cameraColor의 버전이 증가되고 있습니다.

https://github.com/Unity-Technologies/Graphics/blob/fc267ad41df7e0cf39300c4c4d57dd1dc890c054/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilders.cs#L238-L243

if ((flags & AccessFlags.Write) != 0)
            {
                ValidateWriteTo(handle);
                m_RenderPass.AddResourceWrite(m_Resources.GetNewVersionedHandle(handle));
                m_Resources.IncrementWriteCount(handle);
            }

 

이 버전 값에 상한이 있다는 것이 진짜인 것 같습니다.

원래 예외를 던지는 부분에서 참조하고 있는 MaxVersions의 정의를 살펴봤습니다.

https://github.com/Unity-Technologies/Graphics/blob/fc267ad41df7e0cf39300c4c4d57dd1dc890c054/Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/Compiler/ResourcesData.cs#L196

public const int MaxVersions = 20; 
// A quite arbitrary limit should be enough for most graphs. Increasing it shouldn't be a problem but will use more memory as these lists use a fixed size upfront allocation.

 

MaxVersions는 20으로 상수로 정의되어 있습니다.그리고 이어지는 주석에는 '대부분의 그래프에서는 이 제한으로 충분하다'는 내용이 적혀 있습니다.

즉, RenderGraph는 한 프레임에서 특정 렌더 타깃에 대한 쓰기 횟수는 20회 정도면 충분하다는 것이 RenderGraph의 설계인 것 같습니다.

대책

현재로서는 쓰기 경로의 수를 줄이거나 패키지를 개조하여 MaxVersions를 늘리는 것이 효과적인 대책이 될 수 있을 것 같습니다.둘 다 꽤 번거롭지만 .......

커스텀 풀스크린 패스를 깔면 쉽게 도달할 수 있는 한계인 것 같기도 해서 뭔가 쉬운 해결방법이 있으면 좋겠네요.


원문.

https://zenn.dev/ruccho/articles/41337c11ee3615

 

【URP 17, RenderGraph】Invalid version: 20

バッジを贈って著者を応援しよう バッジを受け取った著者にはZennから現金やAmazonギフトカードが還元されます。 バッジを贈る

zenn.dev