Skip to content

Commit 6a64c72

Browse files
arttu-peltonenEvergreen
authored andcommitted
Fix RTHandles.Alloc() failing when called inside ScriptableRendererFeature.Create()
This PR addresses https://jira.unity3d.com/browse/UUM-44048 Slack discussion: https://unity.slack.com/archives/C89KFUUCT/p1706102897599419 **The issue:** Currently, `ScriptableRendererFeature.Create()` is called from `OnEnable()` and `OnValidate()` event functions, both of which regularly occur when `UniversalRenderPipeline` has not yet been constructed, for example any time a script change triggers domain reload, or user enters playmode. This is a problem because ScriptableRendererFeature is logically a subsystem of the render pipeline, so it is expected that you are able initialize rendering resources in `ScriptableRendererFeature.Create()`. Since `RTHandleSystem` is only initialized by URP constructor, calling `RTHandle.Alloc()` here will result in errors. **The fix:** Turns out `ScriptableRendererFeature.Create()` is called from 3 places: 1. `ScriptableRendererFeature.OnEnable()` (event function) 2. `ScriptableRendererFeature.OnValidate()` (event function) 3. `ScriptableRenderer.ctor()` The callsite 3) is the one that actually takes the feature from `ScriptableRendererData`, calls `Create()` and adds it to another list inside the runtime `ScriptableRenderer` instance, where it can be accessed during rendering. All of this means that `ScriptableRendererFeature.Create()` gets called **at least 3 times** for example whenever you enter play mode. This seems kind of wasteful but maybe there's a reason for it that I'm not seeing. The fix I'm making is just adding a check to callsites 1) and 2) so that they don't call `Create()` if URP has not yet been constructed. `ScriptableRenderer` constructor still guarantees that the feature gets created before rendering.
1 parent c171091 commit 6a64c72

9 files changed

+220
-14
lines changed

Packages/com.unity.render-pipelines.universal/Runtime/ScriptableRendererFeature.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,18 @@ public virtual void SetupRenderPasses(ScriptableRenderer renderer, in RenderingD
4545

4646
void OnEnable()
4747
{
48-
Create();
48+
// UUM-44048: If the pipeline is not created, don't call Create() as it may allocate RTHandles or do other
49+
// things that require the pipeline to be constructed. This is safe because once the pipeline is constructed,
50+
// ScriptableRendererFeature.Create() will be called by ScriptableRenderer constructor.
51+
if (RenderPipelineManager.currentPipeline is UniversalRenderPipeline)
52+
Create();
4953
}
5054

5155
void OnValidate()
5256
{
53-
Create();
57+
// See comment in OnEnable.
58+
if (RenderPipelineManager.currentPipeline is UniversalRenderPipeline)
59+
Create();
5460
}
5561

5662
/// <summary>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using UnityEngine;
2+
using UnityEngine.Rendering;
3+
using UnityEngine.Rendering.Universal;
4+
5+
public class AllocRTHandleInCreate_ScriptableRendererFeature : ScriptableRendererFeature
6+
{
7+
class AllocRTHandleInCreate_ScriptableRenderPass : ScriptableRenderPass
8+
{
9+
RTHandle m_RTHandle;
10+
11+
public AllocRTHandleInCreate_ScriptableRenderPass()
12+
{
13+
m_RTHandle = RTHandles.Alloc(Vector2.one, name: "DummyScriptableRendererPass RTHandle");
14+
}
15+
16+
public void Dispose()
17+
{
18+
m_RTHandle.Release();
19+
}
20+
}
21+
22+
AllocRTHandleInCreate_ScriptableRenderPass m_Pass;
23+
24+
public override void Create()
25+
{
26+
m_Pass = new AllocRTHandleInCreate_ScriptableRenderPass();
27+
}
28+
29+
protected override void Dispose(bool disposing)
30+
{
31+
m_Pass?.Dispose();
32+
m_Pass = null;
33+
}
34+
35+
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
36+
{
37+
}
38+
}

Tests/SRPTests/Projects/UniversalGraphicsTest_Foundation/Assets/CommonAssets/AllocRTHandleInCreate_ScriptableRendererFeature.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
%YAML 1.1
2+
%TAG !u! tag:unity3d.com,2011:
3+
--- !u!114 &-8472969894007707715
4+
MonoBehaviour:
5+
m_ObjectHideFlags: 0
6+
m_CorrespondingSourceObject: {fileID: 0}
7+
m_PrefabInstance: {fileID: 0}
8+
m_PrefabAsset: {fileID: 0}
9+
m_GameObject: {fileID: 0}
10+
m_Enabled: 1
11+
m_EditorHideFlags: 0
12+
m_Script: {fileID: 11500000, guid: 513627f990bf4d32b40ed586608b5d61, type: 3}
13+
m_Name: AllocRTHandleInCreate_ScriptableRendererFeature
14+
m_EditorClassIdentifier:
15+
m_Active: 1
16+
--- !u!114 &11400000
17+
MonoBehaviour:
18+
m_ObjectHideFlags: 0
19+
m_CorrespondingSourceObject: {fileID: 0}
20+
m_PrefabInstance: {fileID: 0}
21+
m_PrefabAsset: {fileID: 0}
22+
m_GameObject: {fileID: 0}
23+
m_Enabled: 1
24+
m_EditorHideFlags: 0
25+
m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3}
26+
m_Name: AllocRTHandleInCreate_UniversalRendererData
27+
m_EditorClassIdentifier:
28+
debugShaders:
29+
debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7,
30+
type: 3}
31+
hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3}
32+
probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959,
33+
type: 3}
34+
probeVolumeResources:
35+
probeVolumeDebugShader: {fileID: 0}
36+
probeVolumeFragmentationDebugShader: {fileID: 0}
37+
probeVolumeOffsetDebugShader: {fileID: 0}
38+
probeVolumeSamplingDebugShader: {fileID: 0}
39+
probeSamplingDebugMesh: {fileID: 0}
40+
probeSamplingDebugTexture: {fileID: 0}
41+
probeVolumeBlendStatesCS: {fileID: 0}
42+
m_RendererFeatures:
43+
- {fileID: -8472969894007707715}
44+
m_RendererFeatureMap: bd6717ebc5f6698a
45+
m_UseNativeRenderPass: 0
46+
xrSystemData: {fileID: 0}
47+
postProcessData: {fileID: 0}
48+
m_AssetVersion: 2
49+
m_OpaqueLayerMask:
50+
serializedVersion: 2
51+
m_Bits: 4294967295
52+
m_TransparentLayerMask:
53+
serializedVersion: 2
54+
m_Bits: 4294967295
55+
m_DefaultStencilState:
56+
overrideStencilState: 0
57+
stencilReference: 0
58+
stencilCompareFunction: 8
59+
passOperation: 2
60+
failOperation: 0
61+
zFailOperation: 0
62+
m_ShadowTransparentReceive: 1
63+
m_RenderingMode: 0
64+
m_DepthPrimingMode: 0
65+
m_CopyDepthMode: 1
66+
m_AccurateGbufferNormals: 0
67+
m_IntermediateTextureMode: 1

Tests/SRPTests/Projects/UniversalGraphicsTest_Foundation/Assets/CommonAssets/AllocRTHandleInCreate_UniversalRendererData.asset.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tests/SRPTests/Projects/UniversalGraphicsTest_Foundation/Assets/CommonAssets/URPAssets/DefaultURPAsset.asset

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ MonoBehaviour:
4040
- {fileID: 11400000, guid: 7155e055dd29f9944927bdffff6eb366, type: 2}
4141
- {fileID: 11400000, guid: 74a701ce533b14adb8f98f35425f3aeb, type: 2}
4242
- {fileID: 11400000, guid: 846bf2a7afe0943388665d187143c7f6, type: 2}
43+
- {fileID: 11400000, guid: 708aca6b4b64e8f41946dabb10fe1586, type: 2}
4344
m_DefaultRendererIndex: 0
4445
m_RequireDepthTexture: 1
4546
m_RequireOpaqueTexture: 1
@@ -58,7 +59,8 @@ MonoBehaviour:
5859
m_LightProbeSystem: 0
5960
m_ProbeVolumeMemoryBudget: 1024
6061
m_ProbeVolumeBlendingMemoryBudget: 128
61-
m_SupportProbeVolumeStreaming: 0
62+
m_SupportProbeVolumeGPUStreaming: 0
63+
m_SupportProbeVolumeDiskStreaming: 0
6264
m_SupportProbeVolumeScenarios: 0
6365
m_SupportProbeVolumeScenarioBlending: 0
6466
m_ProbeVolumeSHBands: 1
@@ -103,26 +105,21 @@ MonoBehaviour:
103105
m_SupportDataDrivenLensFlare: 0
104106
m_SupportScreenSpaceLensFlare: 0
105107
m_GPUResidentDrawerMode: 0
108+
m_UseLegacyLightmaps: 0
109+
m_SmallMeshScreenPercentage: 0
110+
m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0
106111
m_ShadowType: 0
107112
m_LocalShadowsSupported: 1
108113
m_LocalShadowsAtlasResolution: 512
109114
m_MaxPixelLights: 4
110115
m_ShadowAtlasResolution: 2048
111116
m_VolumeFrameworkUpdateMode: 0
112117
m_VolumeProfile: {fileID: 0}
113-
m_Textures:
114-
blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3}
115-
bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3}
116118
apvScenesData:
117-
m_ObsoleteSerializedBakingSets: []
118-
sceneToBakingSet:
119-
m_Keys: []
120-
m_Values: []
121-
bakingSets: []
122-
sceneBounds:
119+
obsoleteSceneBounds:
123120
m_Keys: []
124121
m_Values: []
125-
hasProbeVolumes:
122+
obsoleteHasProbeVolumes:
126123
m_Keys: []
127124
m_Values:
128125
m_PrefilteringModeMainLightShadows: 3
@@ -153,5 +150,9 @@ MonoBehaviour:
153150
m_PrefilterSoftShadows: 0
154151
m_PrefilterScreenCoord: 1
155152
m_PrefilterNativeRenderPass: 0
153+
m_PrefilterUseLegacyLightmaps: 0
156154
m_ShaderVariantLogLevel: 0
157155
m_ShadowCascades: 3
156+
m_Textures:
157+
blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3}
158+
bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using System.Collections;
3+
using NUnit.Framework;
4+
using UnityEngine;
5+
using UnityEngine.Rendering;
6+
using UnityEngine.Rendering.Universal;
7+
using UnityEngine.TestTools;
8+
9+
public class ScriptableRendererFeatureTests
10+
{
11+
// Custom log handler is needed because the default one misses LogErrors that happen during RP constructor due to
12+
// how domain reload works with the test framework. This handler will notice the errors and fail the test inside
13+
// the test body if any were logged (for example if RTHandles.Initialize logs an error).
14+
class ErrorLogHandler : ILogHandler, IDisposable
15+
{
16+
ILogHandler m_OriginalHandler;
17+
public string errorMessage { get; private set; }
18+
public bool hasError => !string.IsNullOrEmpty(errorMessage);
19+
20+
public ErrorLogHandler()
21+
{
22+
m_OriginalHandler = Debug.unityLogger.logHandler;
23+
Debug.unityLogger.logHandler = this;
24+
}
25+
26+
public void LogFormat(LogType logType, UnityEngine.Object context, string format, params object[] args)
27+
{
28+
if (logType == LogType.Error)
29+
{
30+
// Defer assertion to ensure we are not in the middle of RP constructor or something
31+
errorMessage = string.Format(format, args);
32+
}
33+
else
34+
{
35+
m_OriginalHandler.LogFormat(logType, context, format, args);
36+
}
37+
}
38+
39+
public void LogException(Exception exception, UnityEngine.Object context)
40+
{
41+
m_OriginalHandler.LogException(exception, context);
42+
}
43+
44+
public void Dispose()
45+
{
46+
Debug.unityLogger.logHandler = m_OriginalHandler;
47+
m_OriginalHandler = null;
48+
49+
errorMessage = null;
50+
}
51+
}
52+
53+
ErrorLogHandler m_ErrorLogHandler;
54+
55+
[SetUp]
56+
public void Setup()
57+
{
58+
m_ErrorLogHandler = new ErrorLogHandler();
59+
}
60+
61+
[TearDown]
62+
public void TearDown()
63+
{
64+
m_ErrorLogHandler.Dispose();
65+
}
66+
67+
[UnityTest]
68+
public IEnumerator AllocRTHandleInCreate_EnterExitPlayModeWithoutErrors()
69+
{
70+
yield return new EnterPlayMode();
71+
yield return null;
72+
73+
yield return new ExitPlayMode();
74+
yield return null;
75+
76+
if (m_ErrorLogHandler.hasError)
77+
Assert.Fail(m_ErrorLogHandler.errorMessage);
78+
}
79+
}

Tests/SRPTests/Projects/UniversalGraphicsTest_Foundation/Assets/Test/Editor/ScriptableRendererFeatureTests.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tests/SRPTests/Projects/UniversalGraphicsTest_Foundation/Assets/Test/Editor/Unity.Testing.SRP.Universal.Foundation.Editor.asmdef

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"GUID:15fc0a57446b3144c949da3e2b9737a9",
1313
"GUID:36d514892e55d4340b470c29fcab8b44",
1414
"GUID:55aba1c6f9cf8e949aa77aaeccd46083",
15-
"GUID:adf6f42bac617413dbcd97c993ab7077"
15+
"GUID:adf6f42bac617413dbcd97c993ab7077",
16+
"GUID:df380645f10b7bc4b97d4f5eb6303d95"
1617
],
1718
"includePlatforms": [
1819
"Editor"

0 commit comments

Comments
 (0)