-
Notifications
You must be signed in to change notification settings - Fork 877
Expand file tree
/
Copy pathRenderGraphTestsCore.cs
More file actions
195 lines (155 loc) · 8.16 KB
/
Copy pathRenderGraphTestsCore.cs
File metadata and controls
195 lines (155 loc) · 8.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
using NUnit.Framework;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
namespace UnityEditor.Rendering.Tests
{
// TODO: Move this class to the Tests/Editor folder once the "IsolatedPackagesVerified" CI test correctly resolves all dependencies.
// Currently, the URP package fails to locate the RenderGraphTestsCore class when it's placed under Tests/Editor,
// unless the Core package is explicitly added to the "testables" list in the project manifest — which is not a sustainable solution.
internal class RenderGraphTestsCore
{
// For RG Record/Hash/Compile testing, use m_RenderGraph
protected RenderGraph m_RenderGraph;
protected RenderPipelineAsset m_OldDefaultRenderPipeline;
protected RenderPipelineAsset m_OldQualityRenderPipeline;
// For RG Execute/Submit testing with rendering, use m_RenderGraphTestPipeline and m_RenderGraph in its recordRenderGraphBody
protected RenderGraphTestPipelineAsset m_RenderGraphTestPipeline;
protected RenderGraphTestGlobalSettings m_RenderGraphTestGlobalSettings;
protected GameObject m_GameObject;
// We need a camera to execute the render graph and a game object to attach a camera
protected Camera m_Camera;
// For the testing of the following RG steps: Execute and Submit (native) with camera rendering, use this custom RenderGraph render pipeline
// through a camera render call to test the RG with a real ScriptableRenderContext
internal class RenderGraphTestPipelineAsset : RenderPipelineAsset<RenderGraphTestPipelineInstance>
{
public Action<ScriptableRenderContext, Camera, CommandBuffer> recordRenderGraphBody;
public RenderGraph renderGraph { get; private set; }
public RenderTextureUVOriginStrategy renderTextureUVOriginStrategy;
public bool invalidContextForTesting;
protected override RenderPipeline CreatePipeline()
{
return new RenderGraphTestPipelineInstance(this);
}
// Called only once per UTR
void OnEnable()
{
renderGraph = new();
}
}
internal class RenderGraphTestPipelineInstance : RenderPipeline
{
RenderGraphTestPipelineAsset asset;
// Having the RG at this level allows us to handle RG framework within Render() for easier testing
RenderGraph m_RenderGraph;
public RenderGraphTestPipelineInstance(RenderGraphTestPipelineAsset asset)
{
this.asset = asset;
this.m_RenderGraph = asset.renderGraph;
}
protected override void Render(ScriptableRenderContext renderContext, List<Camera> cameras)
{
foreach (var camera in cameras)
{
if (!camera.enabled)
continue;
var cmd = CommandBufferPool.Get();
RenderGraphParameters rgParams = new()
{
commandBuffer = cmd,
scriptableRenderContext = renderContext,
currentFrameIndex = Time.frameCount,
invalidContextForTesting = asset.invalidContextForTesting,
renderTextureUVOriginStrategy = asset.renderTextureUVOriginStrategy
};
try
{
// Necessary to reinitialize the state, since we have many tests which do not use this system but directly adding
// passes to the graph (to test the compilation) and destroying them without executing them with camera.Render()
// (e.g GraphicsPassWriteWaitOnAsyncPipe). So the state becomes RecordGraph because of the Builder.Destroy logic.
m_RenderGraph.RenderGraphState = RenderGraphState.Idle;
m_RenderGraph.BeginRecording(rgParams);
asset.recordRenderGraphBody?.Invoke(renderContext, camera, cmd);
m_RenderGraph.EndRecordingAndExecute();
}
catch (Exception e)
{
if (m_RenderGraph.ResetGraphAndLogException(e))
throw;
return;
}
if (rgParams.invalidContextForTesting == false)
{
renderContext.ExecuteCommandBuffer(cmd);
}
CommandBufferPool.Release(cmd);
}
renderContext.Submit();
}
}
[SupportedOnRenderPipeline(typeof(RenderGraphTestPipelineAsset))]
[System.ComponentModel.DisplayName("RenderGraphTest")]
internal class RenderGraphTestGlobalSettings : RenderPipelineGlobalSettings<RenderGraphTestGlobalSettings, RenderGraphTestPipelineInstance>
{
[SerializeField] RenderPipelineGraphicsSettingsContainer m_Settings = new();
protected override List<IRenderPipelineGraphicsSettings> settingsList => m_Settings.settingsList;
}
[OneTimeSetUp]
public void Setup()
{
// Setting default global settings to the custom RG render pipeline type, no quality settings so we can rely on the default RP
m_RenderGraphTestGlobalSettings = ScriptableObject.CreateInstance<RenderGraphTestGlobalSettings>();
EditorGraphicsSettings.SetRenderPipelineGlobalSettingsAsset<RenderGraphTestPipelineInstance>(m_RenderGraphTestGlobalSettings);
// Saving old render pipelines to set them back after testing
m_OldDefaultRenderPipeline = GraphicsSettings.defaultRenderPipeline;
m_OldQualityRenderPipeline = QualitySettings.renderPipeline;
// Setting the custom RG render pipeline
m_RenderGraphTestPipeline = ScriptableObject.CreateInstance<RenderGraphTestPipelineAsset>();
GraphicsSettings.defaultRenderPipeline = m_RenderGraphTestPipeline;
QualitySettings.renderPipeline = m_RenderGraphTestPipeline;
// Getting the RG from the custom asset pipeline
m_RenderGraph = m_RenderGraphTestPipeline.renderGraph;
// Necessary to disable it for the Unit Tests, as the caller is not the same.
RenderGraph.RenderGraphExceptionMessages.enableCaller = false;
// We need a real ScriptableRenderContext and a camera to execute the Render Graph
m_GameObject = new GameObject("testGameObject")
{
hideFlags = HideFlags.HideAndDontSave
};
m_GameObject.tag = "MainCamera";
m_Camera = m_GameObject.AddComponent<Camera>();
}
[OneTimeTearDown]
public void Cleanup()
{
GraphicsSettings.defaultRenderPipeline = m_OldDefaultRenderPipeline;
m_OldDefaultRenderPipeline = null;
QualitySettings.renderPipeline = m_OldQualityRenderPipeline;
m_OldQualityRenderPipeline = null;
try
{
m_RenderGraph.Cleanup();
}
catch (Exception e)
{
Debug.Log($"Tried to clean RenderGraph but exception was thrown: {e.Message}");
}
UnityEngine.Object.DestroyImmediate(m_RenderGraphTestPipeline);
EditorGraphicsSettings.SetRenderPipelineGlobalSettingsAsset<RenderGraphTestPipelineInstance>(null);
UnityEngine.Object.DestroyImmediate(m_RenderGraphTestGlobalSettings);
GameObject.DestroyImmediate(m_GameObject);
m_GameObject = null;
m_Camera = null;
}
[TearDown]
public void CleanupRenderGraph()
{
m_RenderGraphTestPipeline.invalidContextForTesting = false;
// Cleaning all Render Graph resources and data structures
// Nothing remains, Render Graph in next test will start from scratch
m_RenderGraph.CleanupResourcesAndGraph();
}
}
}