A game about forced loneliness, made by TACStudios
1using System;
2using System.Diagnostics;
3using UnityEngine.Scripting.APIUpdating;
4
5namespace UnityEngine.Rendering.RenderGraphModule
6{
7 /// <summary>
8 /// Use this struct to set up a new Render Pass.
9 /// </summary>
10 [MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
11 public struct RenderGraphBuilder : IDisposable
12 {
13 RenderGraphPass m_RenderPass;
14 RenderGraphResourceRegistry m_Resources;
15 RenderGraph m_RenderGraph;
16 bool m_Disposed;
17
18 #region Public Interface
19 /// <summary>
20 /// Specify that the pass will use a Texture resource as a color render target.
21 /// This has the same effect as WriteTexture and also automatically sets the Texture to use as a render target.
22 /// </summary>
23 /// <param name="input">The Texture resource to use as a color render target.</param>
24 /// <param name="index">Index for multiple render target usage.</param>
25 /// <returns>An updated resource handle to the input resource.</returns>
26 public TextureHandle UseColorBuffer(in TextureHandle input, int index)
27 {
28 CheckResource(input.handle, false);
29 m_Resources.IncrementWriteCount(input.handle);
30 m_RenderPass.SetColorBuffer(input, index);
31 return input;
32 }
33
34 /// <summary>
35 /// Specify that the pass will use a Texture resource as a depth buffer.
36 /// </summary>
37 /// <param name="input">The Texture resource to use as a depth buffer during the pass.</param>
38 /// <param name="flags">Specify the access level for the depth buffer. This allows you to say whether you will read from or write to the depth buffer, or do both.</param>
39 /// <returns>An updated resource handle to the input resource.</returns>
40 public TextureHandle UseDepthBuffer(in TextureHandle input, DepthAccess flags)
41 {
42 CheckResource(input.handle, false);
43
44 if ((flags & DepthAccess.Write) != 0)
45 m_Resources.IncrementWriteCount(input.handle);
46 if ((flags & DepthAccess.Read) != 0)
47 {
48 if (!m_Resources.IsRenderGraphResourceImported(input.handle) && m_Resources.TextureNeedsFallback(input))
49 WriteTexture(input);
50 }
51
52 m_RenderPass.SetDepthBuffer(input, flags);
53 return input;
54 }
55
56 /// <summary>
57 /// Specify a Texture resource to read from during the pass.
58 /// </summary>
59 /// <param name="input">The Texture resource to read from during the pass.</param>
60 /// <returns>An updated resource handle to the input resource.</returns>
61 public TextureHandle ReadTexture(in TextureHandle input)
62 {
63 CheckResource(input.handle);
64
65 if (!m_Resources.IsRenderGraphResourceImported(input.handle) && m_Resources.TextureNeedsFallback(input))
66 {
67 var textureResource = m_Resources.GetTextureResource(input.handle);
68
69 // Ensure we get a fallback to black
70 textureResource.desc.clearBuffer = true;
71 textureResource.desc.clearColor = Color.black;
72
73 // If texture is read from but never written to, return a fallback black texture to have valid reads
74 // Return one from the preallocated default textures if possible
75 if (m_RenderGraph.GetImportedFallback(textureResource.desc, out var fallback))
76 return fallback;
77
78 // If not, simulate a write to the texture so that it gets allocated
79 WriteTexture(input);
80 }
81
82 m_RenderPass.AddResourceRead(input.handle);
83 return input;
84 }
85
86 /// <summary>
87 /// Specify a Texture resource to write to during the pass.
88 /// </summary>
89 /// <param name="input">The Texture resource to write to during the pass.</param>
90 /// <returns>An updated resource handle to the input resource.</returns>
91 public TextureHandle WriteTexture(in TextureHandle input)
92 {
93 CheckResource(input.handle);
94 m_Resources.IncrementWriteCount(input.handle);
95 m_RenderPass.AddResourceWrite(input.handle);
96 return input;
97 }
98
99 /// <summary>
100 /// Specify a Texture resource to read and write to during the pass.
101 /// </summary>
102 /// <param name="input">The Texture resource to read and write to during the pass.</param>
103 /// <returns>An updated resource handle to the input resource.</returns>
104 public TextureHandle ReadWriteTexture(in TextureHandle input)
105 {
106 CheckResource(input.handle);
107 m_Resources.IncrementWriteCount(input.handle);
108 m_RenderPass.AddResourceWrite(input.handle);
109 m_RenderPass.AddResourceRead(input.handle);
110 return input;
111 }
112
113 /// <summary>
114 /// Create a new Render Graph Texture resource.
115 /// This texture will only be available for the current pass and will be assumed to be both written and read so users don't need to add explicit read/write declarations.
116 /// </summary>
117 /// <param name="desc">Texture descriptor.</param>
118 /// <returns>A new transient TextureHandle.</returns>
119 public TextureHandle CreateTransientTexture(in TextureDesc desc)
120 {
121 var result = m_Resources.CreateTexture(desc, m_RenderPass.index);
122 m_RenderPass.AddTransientResource(result.handle);
123 return result;
124 }
125
126 /// <summary>
127 /// Create a new Render Graph Texture resource using the descriptor from another texture.
128 /// This texture will only be available for the current pass and will be assumed to be both written and read so users don't need to add explicit read/write declarations.
129 /// </summary>
130 /// <param name="texture">Texture from which the descriptor should be used.</param>
131 /// <returns>A new transient TextureHandle.</returns>
132 public TextureHandle CreateTransientTexture(in TextureHandle texture)
133 {
134 var desc = m_Resources.GetTextureResourceDesc(texture.handle);
135 var result = m_Resources.CreateTexture(desc, m_RenderPass.index);
136 m_RenderPass.AddTransientResource(result.handle);
137 return result;
138 }
139
140 /// <summary>
141 /// Specify a RayTracingAccelerationStructure resource to build during the pass.
142 /// </summary>
143 /// <param name="input">The RayTracingAccelerationStructure resource to build during the pass.</param>
144 /// <returns>An updated resource handle to the input resource.</returns>
145 public RayTracingAccelerationStructureHandle WriteRayTracingAccelerationStructure(in RayTracingAccelerationStructureHandle input)
146 {
147 CheckResource(input.handle);
148 m_Resources.IncrementWriteCount(input.handle);
149 m_RenderPass.AddResourceWrite(input.handle);
150 return input;
151 }
152
153 /// <summary>
154 /// Specify a RayTracingAccelerationStructure resource to use during the pass.
155 /// </summary>
156 /// <param name="input">The RayTracingAccelerationStructure resource to use during the pass.</param>
157 /// <returns>An updated resource handle to the input resource.</returns>
158 public RayTracingAccelerationStructureHandle ReadRayTracingAccelerationStructure(in RayTracingAccelerationStructureHandle input)
159 {
160 CheckResource(input.handle);
161 m_RenderPass.AddResourceRead(input.handle);
162 return input;
163 }
164
165 /// <summary>
166 /// Specify a Renderer List resource to use during the pass.
167 /// </summary>
168 /// <param name="input">The Renderer List resource to use during the pass.</param>
169 /// <returns>An updated resource handle to the input resource.</returns>
170 public RendererListHandle UseRendererList(in RendererListHandle input)
171 {
172 if(input.IsValid())
173 m_RenderPass.UseRendererList(input);
174 return input;
175 }
176
177 /// <summary>
178 /// Specify a Graphics Buffer resource to read from during the pass.
179 /// </summary>
180 /// <param name="input">The Graphics Buffer resource to read from during the pass.</param>
181 /// <returns>An updated resource handle to the input resource.</returns>
182 public BufferHandle ReadBuffer(in BufferHandle input)
183 {
184 CheckResource(input.handle);
185 m_RenderPass.AddResourceRead(input.handle);
186 return input;
187 }
188
189 /// <summary>
190 /// Specify a Graphics Buffer resource to write to during the pass.
191 /// </summary>
192 /// <param name="input">The Graphics Buffer resource to write to during the pass.</param>
193 /// <returns>An updated resource handle to the input resource.</returns>
194 public BufferHandle WriteBuffer(in BufferHandle input)
195 {
196 CheckResource(input.handle);
197 m_RenderPass.AddResourceWrite(input.handle);
198 m_Resources.IncrementWriteCount(input.handle);
199 return input;
200 }
201
202 /// <summary>
203 /// Create a new Render Graph Graphics Buffer resource.
204 /// This Graphics Buffer will only be available for the current pass and will be assumed to be both written and read so users don't need to add explicit read/write declarations.
205 /// </summary>
206 /// <param name="desc">Graphics Buffer descriptor.</param>
207 /// <returns>A new transient GraphicsBufferHandle.</returns>
208 public BufferHandle CreateTransientBuffer(in BufferDesc desc)
209 {
210 var result = m_Resources.CreateBuffer(desc, m_RenderPass.index);
211 m_RenderPass.AddTransientResource(result.handle);
212 return result;
213 }
214
215 /// <summary>
216 /// Create a new Render Graph Graphics Buffer resource using the descriptor from another Graphics Buffer.
217 /// This Graphics Buffer will only be available for the current pass and will be assumed to be both written and read so users don't need to add explicit read/write declarations.
218 /// </summary>
219 /// <param name="graphicsbuffer">Graphics Buffer from which the descriptor should be used.</param>
220 /// <returns>A new transient GraphicsBufferHandle.</returns>
221 public BufferHandle CreateTransientBuffer(in BufferHandle graphicsbuffer)
222 {
223 var desc = m_Resources.GetBufferResourceDesc(graphicsbuffer.handle);
224 var result = m_Resources.CreateBuffer(desc, m_RenderPass.index);
225 m_RenderPass.AddTransientResource(result.handle);
226 return result;
227 }
228
229 /// <summary>
230 /// Specify the render function to use for this pass.
231 /// A call to this is mandatory for the pass to be valid.
232 /// </summary>
233 /// <typeparam name="PassData">The Type of the class that provides data to the Render Pass.</typeparam>
234 /// <param name="renderFunc">Render function for the pass.</param>
235 public void SetRenderFunc<PassData>(BaseRenderFunc<PassData, RenderGraphContext> renderFunc)
236 where PassData : class, new()
237 {
238 ((RenderGraphPass<PassData>)m_RenderPass).renderFunc = renderFunc;
239 }
240
241 /// <summary>
242 /// Enable asynchronous compute for this pass.
243 /// </summary>
244 /// <param name="value">Set to true to enable asynchronous compute.</param>
245 public void EnableAsyncCompute(bool value)
246 {
247 m_RenderPass.EnableAsyncCompute(value);
248 }
249
250 /// <summary>
251 /// Allow or not pass culling
252 /// By default all passes can be culled out if the render graph detects it's not actually used.
253 /// In some cases, a pass may not write or read any texture but rather do something with side effects (like setting a global texture parameter for example).
254 /// This function can be used to tell the system that it should not cull this pass.
255 /// </summary>
256 /// <param name="value">True to allow pass culling.</param>
257 public void AllowPassCulling(bool value)
258 {
259 m_RenderPass.AllowPassCulling(value);
260 }
261
262 /// <summary>
263 /// Enable foveated rendering for this pass.
264 /// </summary>
265 /// <param name="value">True to enable foveated rendering.</param>
266 public void EnableFoveatedRasterization(bool value)
267 {
268 m_RenderPass.EnableFoveatedRasterization(value);
269 }
270
271 /// <summary>
272 /// Dispose the RenderGraphBuilder instance.
273 /// </summary>
274 public void Dispose()
275 {
276 Dispose(true);
277 }
278
279 /// <summary>
280 /// Allow or not pass culling based on renderer list results
281 /// By default all passes can be culled out if the render graph detects they are using a renderer list that is empty (does not draw any geometry)
282 /// In some cases, a pass may not write or read any texture but rather do something with side effects (like setting a global texture parameter for example).
283 /// This function can be used to tell the system that it should not cull this pass.
284 /// </summary>
285 /// <param name="value">True to allow pass culling.</param>
286 public void AllowRendererListCulling(bool value)
287 {
288 m_RenderPass.AllowRendererListCulling(value);
289 }
290
291 /// <summary>
292 /// Used to indicate that a pass depends on an external renderer list (that is not directly used in this pass).
293 /// </summary>
294 /// <param name="input">The renderer list handle this pass depends on.</param>
295 /// <returns>A <see cref="RendererListHandle"/></returns>
296 public RendererListHandle DependsOn(in RendererListHandle input)
297 {
298 m_RenderPass.UseRendererList(input);
299 return input;
300 }
301
302 #endregion
303
304 #region Internal Interface
305 internal RenderGraphBuilder(RenderGraphPass renderPass, RenderGraphResourceRegistry resources, RenderGraph renderGraph)
306 {
307 m_RenderPass = renderPass;
308 m_Resources = resources;
309 m_RenderGraph = renderGraph;
310 m_Disposed = false;
311 }
312
313 void Dispose(bool disposing)
314 {
315 if (m_Disposed)
316 return;
317
318 m_RenderGraph.OnPassAdded(m_RenderPass);
319 m_Disposed = true;
320 }
321
322 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
323 void CheckResource(in ResourceHandle res, bool checkTransientReadWrite = true)
324 {
325 if(RenderGraph.enableValidityChecks)
326 {
327 if (res.IsValid())
328 {
329 int transientIndex = m_Resources.GetRenderGraphResourceTransientIndex(res);
330 // We have dontCheckTransientReadWrite here because users may want to use UseColorBuffer/UseDepthBuffer API to benefit from render target auto binding. In this case we don't want to raise the error.
331 if (transientIndex == m_RenderPass.index && checkTransientReadWrite)
332 {
333 Debug.LogError($"Trying to read or write a transient resource at pass {m_RenderPass.name}.Transient resource are always assumed to be both read and written.");
334 }
335
336 if (transientIndex != -1 && transientIndex != m_RenderPass.index)
337 {
338 throw new ArgumentException($"Trying to use a transient texture (pass index {transientIndex}) in a different pass (pass index {m_RenderPass.index}).");
339 }
340 }
341 else
342 {
343 throw new ArgumentException($"Trying to use an invalid resource (pass {m_RenderPass.name}).");
344 }
345 }
346 }
347
348 internal void GenerateDebugData(bool value)
349 {
350 m_RenderPass.GenerateDebugData(value);
351 }
352
353 #endregion
354 }
355}