A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Runtime.CompilerServices;
5using UnityEngine.Experimental.Rendering;
6using UnityEngine.Scripting.APIUpdating;
7// Typedefs for the in-engine RendererList API (to avoid conflicts with the experimental version)
8using CoreRendererList = UnityEngine.Rendering.RendererList;
9using CoreRendererListDesc = UnityEngine.Rendering.RendererUtils.RendererListDesc;
10
11namespace UnityEngine.Rendering.RenderGraphModule
12{
13 /// <summary>
14 /// Basic properties of a RTHandle needed by the render graph compiler. It is not always possible to derive these
15 /// given an RTHandle so the user needs to pass these in.
16 ///
17 /// We don't use a full RenderTargetDescriptor here as filling out a full descriptor may not be trivial for users and not all
18 /// members of the descriptor are actually used by the render graph. This struct is the minimum set of info needed by the render graph.
19 /// If you want to develop some utility framework to work with render textures, etc. it's probably better to use RenderTargetDescriptor.
20 /// </summary>
21 [MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
22 public struct RenderTargetInfo
23 {
24 /// <summary>
25 /// The width in pixels of the render texture.
26 /// </summary>
27 public int width;
28 /// <summary>
29 /// The height in pixels of the render texture.
30 /// </summary>
31 public int height;
32 /// <summary>
33 /// The number of volume/array slices of the render texture.
34 /// </summary>
35 public int volumeDepth;
36 /// <summary>
37 /// The number of msaa samples in the render texture.
38 /// </summary>
39 public int msaaSamples;
40 /// <summary>
41 /// The Graphics format of the render texture.
42 /// </summary>
43 public GraphicsFormat format;
44 /// <summary>
45 /// Set to true if the render texture needs to be bound as a multisampled texture in a shader.
46 /// </summary>
47 public bool bindMS;
48 }
49
50 /// <summary>
51 /// A helper struct describing the clear behavior of imported textures.
52 /// </summary>
53 public struct ImportResourceParams
54 {
55 /// <summary>
56 /// Clear the imported texture the first time it is used by the graph.
57 /// </summary>
58 public bool clearOnFirstUse;
59 /// <summary>
60 /// The color to clear with on first use. Ignored if clearOnFirstUse==false;
61 /// </summary>
62 public Color clearColor;
63 /// <summary>
64 /// Discard the imported texture the last time it is used by the graph.
65 /// If MSAA enabled, only the multisampled version is discarded while the MSAA surface is always resolved.
66 /// Fully discarding both multisampled and resolved data is not currently possible.
67 /// </summary>
68 public bool discardOnLastUse;
69 }
70
71 class RenderGraphResourceRegistry
72 {
73 const int kSharedResourceLifetime = 30;
74
75 static RenderGraphResourceRegistry m_CurrentRegistry;
76 internal static RenderGraphResourceRegistry current
77 {
78 get
79 {
80 // We assume that it's enough to only check in editor because we don't want to pay the cost at runtime.
81#if UNITY_EDITOR
82 if (m_CurrentRegistry == null)
83 {
84 throw new InvalidOperationException("Current Render Graph Resource Registry is not set. You are probably trying to cast a Render Graph handle to a resource outside of a Render Graph Pass.");
85 }
86#endif
87 return m_CurrentRegistry;
88 }
89 set
90 {
91 m_CurrentRegistry = value;
92 }
93 }
94
95 delegate bool ResourceCreateCallback(InternalRenderGraphContext rgContext, IRenderGraphResource res);
96 delegate void ResourceCallback(InternalRenderGraphContext rgContext, IRenderGraphResource res);
97
98 class RenderGraphResourcesData
99 {
100 public DynamicArray<IRenderGraphResource> resourceArray = new DynamicArray<IRenderGraphResource>();
101 public int sharedResourcesCount;
102 public IRenderGraphResourcePool pool;
103 public ResourceCreateCallback createResourceCallback;
104 public ResourceCallback releaseResourceCallback;
105
106 public RenderGraphResourcesData()
107 {
108 resourceArray.Resize(1); // Element 0 is the null element
109 }
110
111 public void Clear(bool onException, int frameIndex)
112 {
113 resourceArray.Resize(sharedResourcesCount+1); // First N elements are reserved for shared persistent resources and are kept as is. Element 0 is null
114
115 if (pool != null)
116 pool.CheckFrameAllocation(onException, frameIndex);
117 }
118
119 public void Cleanup()
120 {
121 // Cleanup all shared resources.
122 for (int i = 1; i < sharedResourcesCount+1; ++i)
123 {
124 var resource = resourceArray[i];
125 if (resource != null)
126 {
127 resource.ReleaseGraphicsResource();
128 }
129 }
130 // Then cleanup the pool
131 if (pool != null)
132 pool.Cleanup();
133 }
134
135 public void PurgeUnusedGraphicsResources(int frameIndex)
136 {
137 if (pool != null)
138 pool.PurgeUnusedResources(frameIndex);
139 }
140
141 public int AddNewRenderGraphResource<ResType>(out ResType outRes, bool pooledResource = true)
142 where ResType : IRenderGraphResource, new()
143 {
144 // In order to not create garbage, instead of using Add, we keep the content of the array while resizing and we just reset the existing ref (or create it if it's null).
145 int result = resourceArray.size;
146 resourceArray.Resize(resourceArray.size + 1, true);
147 if (resourceArray[result] == null)
148 resourceArray[result] = new ResType();
149
150 outRes = resourceArray[result] as ResType;
151 outRes.Reset(pooledResource ? pool : null);
152 return result;
153 }
154 }
155
156 RenderGraphResourcesData[] m_RenderGraphResources = new RenderGraphResourcesData[(int)RenderGraphResourceType.Count];
157 DynamicArray<RendererListResource> m_RendererListResources = new DynamicArray<RendererListResource>();
158 DynamicArray<RendererListLegacyResource> m_RendererListLegacyResources = new DynamicArray<RendererListLegacyResource>();
159
160 RenderGraphDebugParams m_RenderGraphDebug;
161 RenderGraphLogger m_ResourceLogger = new RenderGraphLogger();
162 RenderGraphLogger m_FrameInformationLogger; // Comes from the RenderGraph instance.
163 int m_CurrentFrameIndex;
164 int m_ExecutionCount;
165
166 RTHandle m_CurrentBackbuffer;
167
168 const int kInitialRendererListCount = 256;
169 List<CoreRendererList> m_ActiveRendererLists = new List<CoreRendererList>(kInitialRendererListCount);
170
171 #region Internal Interface
172 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
173 void CheckTextureResource(TextureResource texResource)
174 {
175 if (texResource.graphicsResource == null && !texResource.imported)
176 throw new InvalidOperationException($"Trying to use a texture ({texResource.GetName()}) that was already released or not yet created. Make sure you declare it for reading in your pass or you don't read it before it's been written to at least once.");
177 }
178
179 internal RTHandle GetTexture(in TextureHandle handle)
180 {
181 if (!handle.IsValid())
182 return null;
183
184 var texResource = GetTextureResource(handle.handle);
185 CheckTextureResource(texResource);
186 return texResource.graphicsResource;
187 }
188
189 // This index overload will not check frame validity.
190 // Its only purpose is because the NRP compiled graph stores resource handles that would not be frame valid when reused.
191 internal RTHandle GetTexture(int index)
192 {
193 var texResource = GetTextureResource(index);
194 CheckTextureResource(texResource);
195 return texResource.graphicsResource;
196 }
197
198 internal bool TextureNeedsFallback(in TextureHandle handle)
199 {
200 if (!handle.IsValid())
201 return false;
202
203 return GetTextureResource(handle.handle).NeedsFallBack();
204 }
205
206 internal CoreRendererList GetRendererList(in RendererListHandle handle)
207 {
208 if (!handle.IsValid())
209 return CoreRendererList.nullRendererList;
210
211 switch (handle.type)
212 {
213 case RendererListHandleType.Renderers:
214 {
215 if (handle >= m_RendererListResources.size)
216 return CoreRendererList.nullRendererList;
217 return m_RendererListResources[handle].rendererList;
218 }
219 case RendererListHandleType.Legacy:
220 {
221 if (handle >= m_RendererListLegacyResources.size)
222 return CoreRendererList.nullRendererList;
223 if (!m_RendererListLegacyResources[handle].isActive)
224 return CoreRendererList.nullRendererList;
225 return m_RendererListLegacyResources[handle].rendererList;
226 }
227 }
228
229 return CoreRendererList.nullRendererList;
230 }
231
232 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
233 void CheckBufferResource(BufferResource bufferResource)
234 {
235 if (bufferResource.graphicsResource == null)
236 throw new InvalidOperationException($"Trying to use a graphics buffer ({bufferResource.GetName()}) that was already released or not yet created. Make sure you declare it for reading in your pass or you don't read it before it's been written to at least once.");
237 }
238
239 internal GraphicsBuffer GetBuffer(in BufferHandle handle)
240 {
241 if (!handle.IsValid())
242 return null;
243
244 var bufferResource = GetBufferResource(handle.handle);
245 CheckBufferResource(bufferResource);
246
247 return bufferResource.graphicsResource;
248 }
249
250 // This index overload will not check frame validity.
251 // Its only purpose is because the NRP compiled graph stores resource handles that would not be frame valid when reused.
252 internal GraphicsBuffer GetBuffer(int index)
253 {
254 var bufferResource = GetBufferResource(index);
255 CheckBufferResource(bufferResource);
256
257 return bufferResource.graphicsResource;
258 }
259
260 internal RayTracingAccelerationStructure GetRayTracingAccelerationStructure(in RayTracingAccelerationStructureHandle handle)
261 {
262 if (!handle.IsValid())
263 return null;
264
265 var accelStructureResource = GetRayTracingAccelerationStructureResource(handle.handle);
266 var resource = accelStructureResource.graphicsResource;
267#if DEVELOPMENT_BUILD || UNITY_EDITOR
268 if (resource == null)
269 throw new InvalidOperationException($"Trying to use a acceleration structure ({accelStructureResource.GetName()}) that was already released or not yet created. Make sure you declare it for reading in your pass or you don't read it before it's been written to at least once.");
270#endif
271
272 return resource;
273 }
274
275 internal int GetSharedResourceCount(RenderGraphResourceType type)
276 {
277 return m_RenderGraphResources[(int)type].sharedResourcesCount;
278 }
279
280 private RenderGraphResourceRegistry()
281 {
282 }
283
284 internal RenderGraphResourceRegistry(RenderGraphDebugParams renderGraphDebug, RenderGraphLogger frameInformationLogger)
285 {
286 m_RenderGraphDebug = renderGraphDebug;
287 m_FrameInformationLogger = frameInformationLogger;
288
289 for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
290 {
291 m_RenderGraphResources[i] = new RenderGraphResourcesData();
292 }
293
294 m_RenderGraphResources[(int)RenderGraphResourceType.Texture].createResourceCallback = CreateTextureCallback;
295 m_RenderGraphResources[(int)RenderGraphResourceType.Texture].releaseResourceCallback = ReleaseTextureCallback;
296 m_RenderGraphResources[(int)RenderGraphResourceType.Texture].pool = new TexturePool();
297
298 m_RenderGraphResources[(int)RenderGraphResourceType.Buffer].pool = new BufferPool();
299
300 // RayTracingAccelerationStructures can be imported only.
301 m_RenderGraphResources[(int)RenderGraphResourceType.AccelerationStructure].pool = null;
302 }
303
304 internal void BeginRenderGraph(int executionCount)
305 {
306 m_ExecutionCount = executionCount;
307 ResourceHandle.NewFrame(executionCount);
308
309 // We can log independently of current execution name since resources are shared across all executions of render graph.
310 if (m_RenderGraphDebug.enableLogging)
311 m_ResourceLogger.Initialize("RenderGraph Resources");
312 }
313
314 internal void BeginExecute(int currentFrameIndex)
315 {
316 m_CurrentFrameIndex = currentFrameIndex;
317 ManageSharedRenderGraphResources();
318 current = this;
319 }
320
321 internal void EndExecute()
322 {
323 current = null;
324 }
325
326 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
327 [MethodImpl(MethodImplOptions.AggressiveInlining)]
328 void CheckHandleValidity(in ResourceHandle res)
329 {
330 CheckHandleValidity(res.type, res.index);
331 }
332
333 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
334 void CheckHandleValidity(RenderGraphResourceType type, int index)
335 {
336 if(RenderGraph.enableValidityChecks)
337 {
338 var resources = m_RenderGraphResources[(int)type].resourceArray;
339 if (index == 0)
340 throw new ArgumentException($"Trying to access resource of type {type} with an null resource index.");
341 if (index >= resources.size)
342 throw new ArgumentException($"Trying to access resource of type {type} with an invalid resource index {index}");
343 }
344 }
345
346 internal void IncrementWriteCount(in ResourceHandle res)
347 {
348 CheckHandleValidity(res);
349 m_RenderGraphResources[res.iType].resourceArray[res.index].IncrementWriteCount();
350 }
351
352 internal void NewVersion(in ResourceHandle res)
353 {
354 CheckHandleValidity(res);
355 m_RenderGraphResources[res.iType].resourceArray[res.index].NewVersion();
356 }
357
358 internal ResourceHandle GetLatestVersionHandle(in ResourceHandle res)
359 {
360 CheckHandleValidity(res);
361 var ver = m_RenderGraphResources[res.iType].resourceArray[res.index].version;
362 if (IsRenderGraphResourceShared(res))
363 {
364 ver -= m_ExecutionCount; //TODO(ddebaets) is this a good solution ?
365 }
366 return new ResourceHandle(res, ver);
367 }
368
369 internal int GetLatestVersionNumber(in ResourceHandle res)
370 {
371 CheckHandleValidity(res);
372 var ver = m_RenderGraphResources[res.iType].resourceArray[res.index].version;
373 if (IsRenderGraphResourceShared(res))
374 {
375 ver -= m_ExecutionCount;//TODO(ddebaets) is this a good solution ?
376 }
377 return ver;
378 }
379
380 internal ResourceHandle GetZeroVersionedHandle(in ResourceHandle res)
381 {
382 CheckHandleValidity(res);
383 return new ResourceHandle(res, 0);
384 }
385
386 internal ResourceHandle GetNewVersionedHandle(in ResourceHandle res)
387 {
388 CheckHandleValidity(res);
389 var ver = m_RenderGraphResources[res.iType].resourceArray[res.index].NewVersion();
390 if (IsRenderGraphResourceShared(res))
391 {
392 ver -= m_ExecutionCount;//TODO(ddebaets) is this a good solution ?
393 }
394 return new ResourceHandle(res, ver);
395 }
396
397 internal IRenderGraphResource GetResourceLowLevel(in ResourceHandle res)
398 {
399 CheckHandleValidity(res);
400 return m_RenderGraphResources[res.iType].resourceArray[res.index];
401 }
402
403 internal string GetRenderGraphResourceName(in ResourceHandle res)
404 {
405 CheckHandleValidity(res);
406 return m_RenderGraphResources[res.iType].resourceArray[res.index].GetName();
407 }
408
409 internal string GetRenderGraphResourceName(RenderGraphResourceType type, int index)
410 {
411 CheckHandleValidity(type, index);
412 return m_RenderGraphResources[(int)type].resourceArray[index].GetName();
413 }
414
415 internal bool IsRenderGraphResourceImported(in ResourceHandle res)
416 {
417 CheckHandleValidity(res);
418 return m_RenderGraphResources[res.iType].resourceArray[res.index].imported;
419 }
420
421 internal bool IsRenderGraphResourceForceReleased(RenderGraphResourceType type, int index)
422 {
423 CheckHandleValidity(type, index);
424 return m_RenderGraphResources[(int)type].resourceArray[index].forceRelease;
425 }
426
427 internal bool IsRenderGraphResourceShared(RenderGraphResourceType type, int index)
428 {
429 CheckHandleValidity(type, index);
430 return index <= m_RenderGraphResources[(int)type].sharedResourcesCount;
431 }
432
433 internal bool IsRenderGraphResourceShared(in ResourceHandle res) => IsRenderGraphResourceShared(res.type, res.index);
434
435 internal bool IsGraphicsResourceCreated(in ResourceHandle res)
436 {
437 CheckHandleValidity(res);
438 return m_RenderGraphResources[res.iType].resourceArray[res.index].IsCreated();
439 }
440
441 internal bool IsRendererListCreated(in RendererListHandle res)
442 {
443 switch (res.type)
444 {
445 case RendererListHandleType.Renderers:
446 return m_RendererListResources[res].rendererList.isValid;
447 case RendererListHandleType.Legacy:
448 return m_RendererListLegacyResources[res].isActive && m_RendererListLegacyResources[res].rendererList.isValid;
449 }
450 return false;
451 }
452
453 internal bool IsRenderGraphResourceImported(RenderGraphResourceType type, int index)
454 {
455 CheckHandleValidity(type, index);
456 return m_RenderGraphResources[(int)type].resourceArray[index].imported;
457 }
458
459 internal int GetRenderGraphResourceTransientIndex(in ResourceHandle res)
460 {
461 CheckHandleValidity(res);
462 return m_RenderGraphResources[res.iType].resourceArray[res.index].transientPassIndex;
463 }
464
465 // Texture Creation/Import APIs are internal because creation should only go through RenderGraph
466 internal TextureHandle ImportTexture(in RTHandle rt, bool isBuiltin = false)
467 {
468 ImportResourceParams importParams = new ImportResourceParams();
469 importParams.clearOnFirstUse = false;
470 importParams.discardOnLastUse = false;
471
472 return ImportTexture(rt, importParams, isBuiltin);
473 }
474
475 // Texture Creation/Import APIs are internal because creation should only go through RenderGraph
476 internal TextureHandle ImportTexture(in RTHandle rt, in ImportResourceParams importParams, bool isBuiltin = false)
477 {
478 // Apparently existing code tries to import null textures !?? So we sort of allow them then :(
479 // Not sure what this actually "means" it allocates a RG handle but nothing is behind it
480 if (rt != null)
481 {
482 // Imported, try to get back to the original handle we imported and get the properties from there
483 if (rt.m_RT != null)
484 {
485 // RTHandle wrapping a RenderTexture, ok we can get properties from that
486 }
487 else if (rt.m_ExternalTexture != null)
488 {
489 // RTHandle wrapping a regular 2D texture we can't render to that
490 }
491#if DEVELOPMENT_BUILD || UNITY_EDITOR
492 else if (rt.m_NameID != emptyId)
493 {
494
495 // RTHandle wrapping a RenderTargetIdentifier
496 throw new Exception("Invalid import, you are importing a texture handle that wraps a RenderTargetIdentifier. The render graph can't know the properties of these textures so please use the ImportTexture overload that takes a RenderTargetInfo argument instead.");
497 }
498 else
499 {
500 throw new Exception("Invalid render target handle: RT, External texture and NameID are all null or zero.");
501 }
502#endif
503 }
504
505 int newHandle = m_RenderGraphResources[(int)RenderGraphResourceType.Texture].AddNewRenderGraphResource(out TextureResource texResource);
506 texResource.graphicsResource = rt;
507 texResource.imported = true;
508
509 RenderTexture renderTexture = (rt != null) ? ((rt.m_RT != null) ? rt.m_RT : (rt.m_ExternalTexture as RenderTexture)) : null;
510 if (renderTexture)
511 {
512 texResource.desc = new TextureDesc(renderTexture);
513 texResource.validDesc = true;
514 }
515 texResource.desc.clearBuffer = importParams.clearOnFirstUse;
516 texResource.desc.clearColor = importParams.clearColor;
517 texResource.desc.discardBuffer = importParams.discardOnLastUse;
518
519 var texHandle = new TextureHandle(newHandle, false, isBuiltin);
520
521 // Try getting the info straight away so if something is wrong we throw at import time.
522 // It is invalid to import a texture if we can't get its info somehow.
523 // (The alternative is for the code calling ImportTexture to use the overload that takes a RenderTargetInfo).
524 if(rt != null)
525 ValidateRenderTarget(texHandle.handle);
526
527 return texHandle;
528 }
529
530 // Texture Creation/Import APIs are internal because creation should only go through RenderGraph
531 internal TextureHandle ImportTexture(in RTHandle rt, RenderTargetInfo info, in ImportResourceParams importParams)
532 {
533 int newHandle = m_RenderGraphResources[(int)RenderGraphResourceType.Texture].AddNewRenderGraphResource(out TextureResource texResource);
534 texResource.graphicsResource = rt;
535 texResource.imported = true;
536 // Be sure to clear the desc to the default state
537 texResource.desc = new TextureDesc();
538
539 // Apparently existing code tries to import null textures !?? So we sort of allow them then :(
540 if (rt != null)
541 {
542 if (rt.m_NameID != emptyId)
543 {
544 // Store the info in the descriptor structure to avoid having a separate info structure being saved per resource
545 // This descriptor will then be used to reconstruct the info (see GetRenderTargetInfo) but is not a full featured descriptor.
546 // This is ok as this descriptor will never be used to create textures (as they are imported into the graph and thus externally created).
547
548 texResource.desc.format = info.format;
549 texResource.desc.width = info.width;
550 texResource.desc.height = info.height;
551 texResource.desc.slices = info.volumeDepth;
552 texResource.desc.msaaSamples = (MSAASamples)info.msaaSamples;
553 texResource.desc.bindTextureMS = info.bindMS;
554 texResource.desc.clearBuffer = importParams.clearOnFirstUse;
555 texResource.desc.clearColor = importParams.clearColor;
556 texResource.desc.discardBuffer = importParams.discardOnLastUse;
557 texResource.validDesc = false; // The desc above just contains enough info to make RenderTargetInfo not a full descriptor.
558 // This means GetRenderTargetInfo will work for the handle but GetTextureResourceDesc will throw
559 }
560 // Anything else is an error and should take the overload not taking a RenderTargetInfo
561 else
562 {
563#if DEVELOPMENT_BUILD || UNITY_EDITOR
564 throw new Exception("Invalid import, you are importing a texture handle that isn't wrapping a RenderTargetIdentifier. You cannot use the overload taking RenderTargetInfo as the graph will automatically determine the texture properties based on the passed in handle.");
565#endif
566 }
567 }
568 else
569 {
570#if DEVELOPMENT_BUILD || UNITY_EDITOR
571 throw new Exception("Invalid import, null handle.");
572#endif
573 }
574
575 var texHandle = new TextureHandle(newHandle);
576
577 // Try getting the info straight away so if something is wrong we throw at import time.
578 ValidateRenderTarget(texHandle.handle);
579
580 return texHandle;
581 }
582
583 internal TextureHandle CreateSharedTexture(in TextureDesc desc, bool explicitRelease)
584 {
585 var textureResources = m_RenderGraphResources[(int)RenderGraphResourceType.Texture];
586 int sharedTextureCount = textureResources.sharedResourcesCount;
587
588 Debug.Assert(textureResources.resourceArray.size <= sharedTextureCount+1);
589
590 // try to find an available slot.
591 TextureResource texResource = null;
592 int textureIndex = -1;
593
594 for (int i = 1; i < sharedTextureCount+1; ++i)
595 {
596 var resource = textureResources.resourceArray[i];
597 if (resource.shared == false) // unused
598 {
599 texResource = (TextureResource)textureResources.resourceArray[i];
600 textureIndex = i;
601 break;
602 }
603 }
604
605 // if none is available, add a new resource.
606 if (texResource == null)
607 {
608 textureIndex = m_RenderGraphResources[(int)RenderGraphResourceType.Texture].AddNewRenderGraphResource(out texResource, pooledResource: false);
609 textureResources.sharedResourcesCount++;
610 }
611
612 texResource.imported = true;
613 texResource.shared = true;
614 texResource.sharedExplicitRelease = explicitRelease;
615 texResource.desc = desc;
616 texResource.validDesc = true;
617
618 return new TextureHandle(textureIndex, shared: true);
619 }
620
621 internal void RefreshSharedTextureDesc(in TextureHandle texture, in TextureDesc desc)
622 {
623#if DEVELOPMENT_BUILD || UNITY_EDITOR
624 if (!IsRenderGraphResourceShared(RenderGraphResourceType.Texture, texture.handle.index))
625 {
626 throw new InvalidOperationException($"Trying to refresh texture {texture} that is not a shared resource.");
627 }
628#endif
629 var texResource = GetTextureResource(texture.handle);
630 texResource.ReleaseGraphicsResource();
631 texResource.desc = desc;
632 }
633
634 internal void ReleaseSharedTexture(in TextureHandle texture)
635 {
636 var texResources = m_RenderGraphResources[(int)RenderGraphResourceType.Texture];
637
638#if DEVELOPMENT_BUILD || UNITY_EDITOR
639 if (texture.handle.index == 0 || texture.handle.index >= texResources.sharedResourcesCount+1)
640 throw new InvalidOperationException("Tried to release a non shared texture.");
641#endif
642
643 // Decrement if we release the last one.
644 if (texture.handle.index == (texResources.sharedResourcesCount))
645 texResources.sharedResourcesCount--;
646
647 var texResource = GetTextureResource(texture.handle);
648 texResource.ReleaseGraphicsResource();
649 texResource.Reset();
650 }
651
652 internal TextureHandle ImportBackbuffer(RenderTargetIdentifier rt, in RenderTargetInfo info, in ImportResourceParams importParams)
653 {
654 if (m_CurrentBackbuffer != null)
655 m_CurrentBackbuffer.SetTexture(rt);
656 else
657 m_CurrentBackbuffer = RTHandles.Alloc(rt, "Backbuffer");
658
659 int newHandle = m_RenderGraphResources[(int)RenderGraphResourceType.Texture].AddNewRenderGraphResource(out TextureResource texResource);
660 texResource.graphicsResource = m_CurrentBackbuffer;
661 texResource.imported = true;
662 texResource.desc = new TextureDesc();
663 texResource.desc.width = info.width;
664 texResource.desc.height = info.height;
665 texResource.desc.slices = info.volumeDepth;
666 texResource.desc.msaaSamples = (MSAASamples)info.msaaSamples;
667 texResource.desc.bindTextureMS = info.bindMS;
668 texResource.desc.format = info.format;
669 texResource.desc.clearBuffer = importParams.clearOnFirstUse;
670 texResource.desc.clearColor = importParams.clearColor;
671 texResource.desc.discardBuffer = importParams.discardOnLastUse;
672 texResource.validDesc = false;// The desc above just contains enough info to make RenderTargetInfo not a full descriptor.
673 // This means GetRenderTargetInfo will work for the handle but GetTextureResourceDesc will throw
674
675 var texHandle = new TextureHandle(newHandle);
676
677 // Try getting the info straight away so if something wrong we get the exceptions directly at import time.
678 ValidateRenderTarget(texHandle.handle);
679
680 return texHandle;
681 }
682
683 static RenderTargetIdentifier emptyId = new RenderTargetIdentifier();
684 static RenderTargetIdentifier builtinCameraRenderTarget = new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
685
686 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
687 private void ValidateRenderTarget(in ResourceHandle res)
688 {
689 if(RenderGraph.enableValidityChecks)
690 {
691 RenderTargetInfo outInfo;
692 GetRenderTargetInfo(res, out outInfo);
693 }
694 }
695
696 internal void GetRenderTargetInfo(in ResourceHandle res, out RenderTargetInfo outInfo)
697 {
698#if DEVELOPMENT_BUILD || UNITY_EDITOR
699 if (res.iType != (int)RenderGraphResourceType.Texture)
700 {
701 outInfo = new RenderTargetInfo();
702 throw new ArgumentException("Invalid Resource Handle passed to GetRenderTargetInfo");
703 }
704#endif
705 // You can never have enough ways to reference a render target...
706 // Lots of legacy if's and but's
707 TextureResource tex = GetTextureResource(res);
708 if (tex.imported)
709 {
710 // Imported, try to get back to the original handle we imported and get the properties from there
711 RTHandle handle = tex.graphicsResource;
712 if (handle == null)
713 {
714 // Apparently existing code tries to import null textures !?? So we sort of allow them then :(
715 // throw new Exception("Invalid imported texture. The RTHandle provided was null.");
716 outInfo = new RenderTargetInfo();
717 }
718 else if (handle.m_RT != null)
719 {
720 outInfo = new RenderTargetInfo();
721 outInfo.width = handle.m_RT.width;
722 outInfo.height = handle.m_RT.height;
723 outInfo.volumeDepth = handle.m_RT.volumeDepth;
724 outInfo.format = GetFormat(handle.m_RT.graphicsFormat, handle.m_RT.depthStencilFormat);
725 outInfo.msaaSamples = handle.m_RT.antiAliasing;
726 outInfo.bindMS = handle.m_RT.bindTextureMS;
727 }
728 else if (handle.m_ExternalTexture != null)
729 {
730 outInfo = new RenderTargetInfo();
731 outInfo.width = handle.m_ExternalTexture.width;
732 outInfo.height = handle.m_ExternalTexture.height;
733 outInfo.volumeDepth = 1; // XRTODO: Check dimension instead?
734 if (handle.m_ExternalTexture is RenderTexture)
735 {
736 RenderTexture rt = (RenderTexture)handle.m_ExternalTexture;
737 outInfo.format = GetFormat(rt.graphicsFormat, rt.depthStencilFormat);
738 outInfo.msaaSamples = rt.antiAliasing;
739 }
740 else
741 {
742 //Note: This case will likely not work when used as an actual rendertarget. This is a regular 2D, Cube,...
743 //texture an not a rendertarget texture so it will fail when bound as a rendertarget later.
744 outInfo.format = handle.m_ExternalTexture.graphicsFormat;
745 outInfo.msaaSamples = 1;
746 }
747 outInfo.bindMS = false;
748 }
749 else if (handle.m_NameID != emptyId)
750 {
751 // WE can't really get info about RenderTargetIdentifier back. It simply doesn't expose this info.
752 // But in some cases like the camera built-in target it also cant. If it's a BuiltinRenderTextureType
753 // we can't know from the size/format/... from the enum. It's implicitly defined by the current camera,
754 // screen resolution,.... we can't even hope to know or replicate the size calculation here
755 // so we just say we don't know what this rt is and rely on the user passing in the info to us.
756 var desc = GetTextureResourceDesc(res, true);
757 outInfo = new RenderTargetInfo();
758#if DEVELOPMENT_BUILD || UNITY_EDITOR
759 if (desc.width == 0 || desc.height == 0 || desc.slices == 0 || desc.msaaSamples == 0 || desc.format == GraphicsFormat.None)
760 {
761 throw new Exception("Invalid imported texture. A RTHandle wrapping an RenderTargetIdentifier was imported without providing valid RenderTargetInfo.");
762 }
763#endif
764 outInfo.width = desc.width;
765 outInfo.height = desc.height;
766 outInfo.volumeDepth = desc.slices;
767
768 outInfo.msaaSamples = (int)desc.msaaSamples;
769 outInfo.format = desc.format;
770 outInfo.bindMS = desc.bindTextureMS;
771 }
772 else
773 {
774 throw new Exception("Invalid imported texture. The RTHandle provided is invalid.");
775 }
776 }
777 else
778 {
779 // Managed by rendergraph, it might not be created yet so we look at the desc to find out
780 var desc = GetTextureResourceDesc(res);
781 var dim = desc.CalculateFinalDimensions();
782 outInfo = new RenderTargetInfo();
783 outInfo.width = dim.x;
784 outInfo.height = dim.y;
785 outInfo.volumeDepth = desc.slices;
786
787 outInfo.msaaSamples = (int)desc.msaaSamples;
788 outInfo.bindMS = desc.bindTextureMS;
789 outInfo.format = desc.format;
790 }
791 }
792
793 internal GraphicsFormat GetFormat(GraphicsFormat color, GraphicsFormat depthStencil)
794 {
795 ValidateFormat(color, depthStencil);
796 return (depthStencil != GraphicsFormat.None) ? depthStencil : color;
797 }
798
799 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
800 internal void ValidateFormat(GraphicsFormat color, GraphicsFormat depthStencil)
801 {
802 if (RenderGraph.enableValidityChecks)
803 {
804 if (color != GraphicsFormat.None && depthStencil != GraphicsFormat.None)
805 {
806 throw new Exception("Invalid imported texture. Both a color and a depthStencil format are provided. The texture needs to either have a color format or a depth stencil format.");
807 }
808 }
809 }
810
811 internal TextureHandle CreateTexture(in TextureDesc desc, int transientPassIndex = -1)
812 {
813 ValidateTextureDesc(desc);
814
815 int newHandle = m_RenderGraphResources[(int)RenderGraphResourceType.Texture].AddNewRenderGraphResource(out TextureResource texResource);
816 texResource.desc = desc;
817 texResource.validDesc = true;
818 texResource.transientPassIndex = transientPassIndex;
819 texResource.requestFallBack = desc.fallBackToBlackTexture;
820 return new TextureHandle(newHandle);
821 }
822
823 internal int GetResourceCount(RenderGraphResourceType type)
824 {
825 return m_RenderGraphResources[(int)type].resourceArray.size;
826 }
827
828 internal int GetTextureResourceCount()
829 {
830 return GetResourceCount(RenderGraphResourceType.Texture);
831 }
832
833 internal TextureResource GetTextureResource(in ResourceHandle handle)
834 {
835 Debug.Assert(handle.type == RenderGraphResourceType.Texture);
836 return m_RenderGraphResources[(int)RenderGraphResourceType.Texture].resourceArray[handle.index] as TextureResource;
837 }
838
839 internal TextureResource GetTextureResource(int index)
840 {
841 return m_RenderGraphResources[(int)RenderGraphResourceType.Texture].resourceArray[index] as TextureResource;
842 }
843
844 internal TextureDesc GetTextureResourceDesc(in ResourceHandle handle, bool noThrowOnInvalidDesc = false)
845 {
846 Debug.Assert(handle.type == RenderGraphResourceType.Texture);
847 var texture = (m_RenderGraphResources[(int)RenderGraphResourceType.Texture].resourceArray[handle.index] as TextureResource);
848 if (!texture.validDesc && !noThrowOnInvalidDesc)
849 throw new ArgumentException("The passed in texture handle does not have a valid descriptor. (This is most commonly cause by the handle referencing a built-in texture such as the system back buffer.)", "handle");
850 return texture.desc;
851 }
852
853 internal RendererListHandle CreateRendererList(in CoreRendererListDesc desc)
854 {
855 ValidateRendererListDesc(desc);
856
857 int newHandle = m_RendererListResources.Add(new RendererListResource(CoreRendererListDesc.ConvertToParameters(desc)));
858 return new RendererListHandle(newHandle);
859 }
860
861 internal RendererListHandle CreateRendererList(in RendererListParams desc)
862 {
863 int newHandle = m_RendererListResources.Add(new RendererListResource(desc));
864 return new RendererListHandle(newHandle);
865 }
866
867 internal RendererListHandle CreateShadowRendererList(ScriptableRenderContext context, ref ShadowDrawingSettings shadowDrawinSettings)
868 {
869 RendererListLegacyResource resource = new RendererListLegacyResource();
870 resource.rendererList = context.CreateShadowRendererList(ref shadowDrawinSettings);
871 int newHandle = m_RendererListLegacyResources.Add(resource);
872 return new RendererListHandle(newHandle, RendererListHandleType.Legacy);
873 }
874
875 internal RendererListHandle CreateGizmoRendererList(ScriptableRenderContext context, in Camera camera, in GizmoSubset gizmoSubset)
876 {
877 RendererListLegacyResource resource = new RendererListLegacyResource();
878 resource.rendererList = context.CreateGizmoRendererList(camera, gizmoSubset);
879 int newHandle = m_RendererListLegacyResources.Add(resource);
880 return new RendererListHandle(newHandle, RendererListHandleType.Legacy);
881 }
882
883 internal RendererListHandle CreateUIOverlayRendererList(ScriptableRenderContext context, in Camera camera, in UISubset uiSubset)
884 {
885 RendererListLegacyResource resource = new RendererListLegacyResource();
886 resource.rendererList = context.CreateUIOverlayRendererList(camera, uiSubset);
887 int newHandle = m_RendererListLegacyResources.Add(resource);
888 return new RendererListHandle(newHandle, RendererListHandleType.Legacy);
889 }
890
891 internal RendererListHandle CreateWireOverlayRendererList(ScriptableRenderContext context, in Camera camera)
892 {
893 RendererListLegacyResource resource = new RendererListLegacyResource();
894 resource.rendererList = context.CreateWireOverlayRendererList(camera);
895 int newHandle = m_RendererListLegacyResources.Add(resource);
896 return new RendererListHandle(newHandle, RendererListHandleType.Legacy);
897 }
898
899 internal RendererListHandle CreateSkyboxRendererList(ScriptableRenderContext context, in Camera camera)
900 {
901 RendererListLegacyResource resource = new RendererListLegacyResource();
902 resource.rendererList = context.CreateSkyboxRendererList(camera);
903 int newHandle = m_RendererListLegacyResources.Add(resource);
904 return new RendererListHandle(newHandle, RendererListHandleType.Legacy);
905 }
906
907 internal RendererListHandle CreateSkyboxRendererList(ScriptableRenderContext context, in Camera camera, Matrix4x4 projectionMatrix, Matrix4x4 viewMatrix)
908 {
909 RendererListLegacyResource resource = new RendererListLegacyResource();
910 resource.rendererList = context.CreateSkyboxRendererList(camera, projectionMatrix, viewMatrix);
911 int newHandle = m_RendererListLegacyResources.Add(resource);
912 return new RendererListHandle(newHandle, RendererListHandleType.Legacy);
913 }
914
915 internal RendererListHandle CreateSkyboxRendererList(ScriptableRenderContext context, in Camera camera, Matrix4x4 projectionMatrixL, Matrix4x4 viewMatrixL, Matrix4x4 projectionMatrixR, Matrix4x4 viewMatrixR)
916 {
917 RendererListLegacyResource resource = new RendererListLegacyResource();
918 resource.rendererList = context.CreateSkyboxRendererList(camera, projectionMatrixL, viewMatrixL, projectionMatrixR, viewMatrixR);
919 int newHandle = m_RendererListLegacyResources.Add(resource);
920 return new RendererListHandle(newHandle, RendererListHandleType.Legacy);
921 }
922
923 internal BufferHandle ImportBuffer(GraphicsBuffer graphicsBuffer, bool forceRelease = false)
924 {
925 int newHandle = m_RenderGraphResources[(int)RenderGraphResourceType.Buffer].AddNewRenderGraphResource(out BufferResource bufferResource);
926 bufferResource.graphicsResource = graphicsBuffer;
927 bufferResource.imported = true;
928 bufferResource.forceRelease = forceRelease;
929 bufferResource.validDesc = false;
930
931 return new BufferHandle(newHandle);
932 }
933
934 internal BufferHandle CreateBuffer(in BufferDesc desc, int transientPassIndex = -1)
935 {
936 ValidateBufferDesc(desc);
937
938 int newHandle = m_RenderGraphResources[(int)RenderGraphResourceType.Buffer].AddNewRenderGraphResource(out BufferResource bufferResource);
939 bufferResource.desc = desc;
940 bufferResource.validDesc = true;
941 bufferResource.transientPassIndex = transientPassIndex;
942
943 return new BufferHandle(newHandle);
944 }
945
946 internal BufferDesc GetBufferResourceDesc(in ResourceHandle handle, bool noThrowOnInvalidDesc = false)
947 {
948 Debug.Assert(handle.type == RenderGraphResourceType.Buffer);
949 var buffer = (m_RenderGraphResources[(int)RenderGraphResourceType.Buffer].resourceArray[handle.index] as BufferResource);
950 if (!buffer.validDesc && !noThrowOnInvalidDesc)
951 throw new ArgumentException("The passed in buffer handle does not have a valid descriptor. (This is most commonly cause by importing the buffer.)", "handle");
952 return buffer.desc;
953 }
954
955 internal int GetBufferResourceCount()
956 {
957 return GetResourceCount(RenderGraphResourceType.Buffer);
958 }
959
960 BufferResource GetBufferResource(in ResourceHandle handle)
961 {
962 Debug.Assert(handle.type == RenderGraphResourceType.Buffer);
963 return m_RenderGraphResources[(int)RenderGraphResourceType.Buffer].resourceArray[handle.index] as BufferResource;
964 }
965
966 BufferResource GetBufferResource(int index)
967 {
968 return m_RenderGraphResources[(int)RenderGraphResourceType.Buffer].resourceArray[index] as BufferResource;
969 }
970
971 RayTracingAccelerationStructureResource GetRayTracingAccelerationStructureResource(in ResourceHandle handle)
972 {
973 return m_RenderGraphResources[(int)RenderGraphResourceType.AccelerationStructure].resourceArray[handle.index] as RayTracingAccelerationStructureResource;
974 }
975
976 internal int GetRayTracingAccelerationStructureResourceCount()
977 {
978 return GetResourceCount(RenderGraphResourceType.AccelerationStructure);
979 }
980
981 internal RayTracingAccelerationStructureHandle ImportRayTracingAccelerationStructure(in RayTracingAccelerationStructure accelStruct, string name)
982 {
983 int newHandle = m_RenderGraphResources[(int)RenderGraphResourceType.AccelerationStructure].AddNewRenderGraphResource(out RayTracingAccelerationStructureResource accelStructureResource, false);
984 accelStructureResource.graphicsResource = accelStruct;
985 accelStructureResource.imported = true;
986 accelStructureResource.forceRelease = false;
987 accelStructureResource.desc.name = name;
988
989 return new RayTracingAccelerationStructureHandle(newHandle);
990 }
991
992 internal void UpdateSharedResourceLastFrameIndex(int type, int index)
993 {
994 m_RenderGraphResources[type].resourceArray[index].sharedResourceLastFrameUsed = m_ExecutionCount;
995 }
996 internal void UpdateSharedResourceLastFrameIndex(in ResourceHandle handle) => UpdateSharedResourceLastFrameIndex((int)handle.type, handle.index);
997
998
999 void ManageSharedRenderGraphResources()
1000 {
1001 for (int type = 0; type < (int)RenderGraphResourceType.Count; ++type)
1002 {
1003 var resources = m_RenderGraphResources[type];
1004 for (int i = 1; i < resources.sharedResourcesCount+1; ++i)
1005 {
1006 var resource = m_RenderGraphResources[type].resourceArray[i];
1007 bool isCreated = resource.IsCreated();
1008 // Alloc if needed
1009 if (resource.sharedResourceLastFrameUsed == m_ExecutionCount && !isCreated)
1010 {
1011 // User name provided through the resource desc will be used
1012 resource.CreateGraphicsResource();
1013 }
1014 // Release if not used anymore
1015 else if (isCreated && !resource.sharedExplicitRelease && ((resource.sharedResourceLastFrameUsed + kSharedResourceLifetime) < m_ExecutionCount))
1016 {
1017 resource.ReleaseGraphicsResource();
1018 }
1019 }
1020 }
1021 }
1022
1023 internal bool CreatePooledResource(InternalRenderGraphContext rgContext, int type, int index)
1024 {
1025 Debug.Assert(index != 0, "Index 0 indicates the null object it can't be used here");
1026
1027 bool? executedWork = false;
1028 var resource = m_RenderGraphResources[type].resourceArray[index];
1029 if (!resource.imported)
1030 {
1031 resource.CreatePooledGraphicsResource();
1032
1033 if (m_RenderGraphDebug.enableLogging)
1034 resource.LogCreation(m_FrameInformationLogger);
1035
1036 executedWork = m_RenderGraphResources[type].createResourceCallback?.Invoke(rgContext, resource);
1037 }
1038
1039 return executedWork ?? false;
1040 }
1041
1042 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1043 internal bool CreatePooledResource(InternalRenderGraphContext rgContext, in ResourceHandle handle)
1044 {
1045 return CreatePooledResource(rgContext, handle.iType, handle.index);
1046 }
1047
1048 // Only modified by native compiler when using native render pass
1049 internal bool forceManualClearOfResource = true;
1050
1051 bool CreateTextureCallback(InternalRenderGraphContext rgContext, IRenderGraphResource res)
1052 {
1053 var resource = res as TextureResource;
1054
1055#if UNITY_2020_2_OR_NEWER
1056 var fastMemDesc = resource.desc.fastMemoryDesc;
1057 if (fastMemDesc.inFastMemory)
1058 {
1059 resource.graphicsResource.SwitchToFastMemory(rgContext.cmd, fastMemDesc.residencyFraction, fastMemDesc.flags);
1060 }
1061#endif
1062
1063 bool executedWork = false;
1064 if ((forceManualClearOfResource && resource.desc.clearBuffer) || m_RenderGraphDebug.clearRenderTargetsAtCreation)
1065 {
1066 bool debugClear = m_RenderGraphDebug.clearRenderTargetsAtCreation && !resource.desc.clearBuffer;
1067 var clearFlag = GraphicsFormatUtility.IsDepthStencilFormat(resource.desc.format) ? ClearFlag.DepthStencil : ClearFlag.Color;
1068 var clearColor = debugClear ? Color.magenta : resource.desc.clearColor;
1069 CoreUtils.SetRenderTarget(rgContext.cmd, resource.graphicsResource, clearFlag, clearColor);
1070 executedWork = true;
1071 }
1072 return executedWork;
1073 }
1074
1075 internal void ReleasePooledResource(InternalRenderGraphContext rgContext, int type, int index)
1076 {
1077 var resource = m_RenderGraphResources[type].resourceArray[index];
1078
1079 if (!resource.imported || resource.forceRelease)
1080 {
1081 m_RenderGraphResources[type].releaseResourceCallback?.Invoke(rgContext, resource);
1082
1083 if (m_RenderGraphDebug.enableLogging)
1084 {
1085 resource.LogRelease(m_FrameInformationLogger);
1086 }
1087
1088 resource.ReleasePooledGraphicsResource(m_CurrentFrameIndex);
1089 }
1090 }
1091
1092 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1093 internal void ReleasePooledResource(InternalRenderGraphContext rgContext, in ResourceHandle handle)
1094 {
1095 ReleasePooledResource(rgContext, handle.iType, handle.index);
1096 }
1097
1098 void ReleaseTextureCallback(InternalRenderGraphContext rgContext, IRenderGraphResource res)
1099 {
1100 var resource = res as TextureResource;
1101
1102 if (m_RenderGraphDebug.clearRenderTargetsAtRelease)
1103 {
1104 var clearFlag = GraphicsFormatUtility.IsDepthStencilFormat(resource.desc.format)? ClearFlag.DepthStencil : ClearFlag.Color;
1105 CoreUtils.SetRenderTarget(rgContext.cmd, resource.graphicsResource, clearFlag, Color.magenta);
1106 }
1107 }
1108
1109 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
1110 void ValidateTextureDesc(in TextureDesc desc)
1111 {
1112 if(RenderGraph.enableValidityChecks)
1113 {
1114 if (desc.format == GraphicsFormat.None )
1115 {
1116 throw new ArgumentException("Texture was created with with no format. The texture needs to either have a color format or a depth stencil format.");
1117 }
1118
1119 if (desc.dimension == TextureDimension.None)
1120 {
1121 throw new ArgumentException("Texture was created with an invalid texture dimension.");
1122 }
1123
1124 if (desc.slices == 0)
1125 {
1126 throw new ArgumentException("Texture was created with a slices parameter value of zero.");
1127 }
1128
1129 if (desc.sizeMode == TextureSizeMode.Explicit)
1130 {
1131 if (desc.width == 0 || desc.height == 0)
1132 throw new ArgumentException("Texture using Explicit size mode was create with either width or height at zero.");
1133 }
1134 }
1135 }
1136
1137 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
1138 void ValidateRendererListDesc(in CoreRendererListDesc desc)
1139 {
1140 if(RenderGraph.enableValidityChecks)
1141 {
1142 if (!desc.IsValid())
1143 {
1144 throw new ArgumentException("Renderer List descriptor is not valid.");
1145 }
1146
1147 if (desc.renderQueueRange.lowerBound == 0 && desc.renderQueueRange.upperBound == 0)
1148 {
1149 throw new ArgumentException("Renderer List creation descriptor must have a valid RenderQueueRange.");
1150 }
1151 }
1152 }
1153
1154 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
1155 void ValidateBufferDesc(in BufferDesc desc)
1156 {
1157 if(RenderGraph.enableValidityChecks)
1158 {
1159 if (desc.stride % 4 != 0)
1160 {
1161 throw new ArgumentException("Invalid Graphics Buffer creation descriptor: Graphics Buffer stride must be at least 4.");
1162 }
1163 if (desc.count == 0)
1164 {
1165 throw new ArgumentException("Invalid Graphics Buffer creation descriptor: Graphics Buffer count must be non zero.");
1166 }
1167 }
1168 }
1169
1170 internal void CreateRendererLists(List<RendererListHandle> rendererLists, ScriptableRenderContext context, bool manualDispatch = false)
1171 {
1172 // We gather the active renderer lists of a frame in a list/array before we pass it in the core API for batch processing
1173 m_ActiveRendererLists.Clear();
1174
1175 foreach (var rendererList in rendererLists)
1176 {
1177 switch(rendererList.type)
1178 {
1179 case RendererListHandleType.Renderers:
1180 {
1181 ref var rendererListResource = ref m_RendererListResources[rendererList];
1182 ref var desc = ref rendererListResource.desc;
1183 rendererListResource.rendererList = context.CreateRendererList(ref desc);
1184 m_ActiveRendererLists.Add(rendererListResource.rendererList);
1185 break;
1186 }
1187 case RendererListHandleType.Legacy:
1188 {
1189 // Legacy rendererLists are created upfront in recording phase. Simply activate them.
1190 ref var rendererListResource = ref m_RendererListLegacyResources[rendererList];
1191 rendererListResource.isActive = true;
1192 break;
1193 }
1194#if DEVELOPMENT_BUILD || UNITY_EDITOR
1195 default:
1196 {
1197 throw new ArgumentException("Invalid RendererListHandle: RendererListHandleType is not recognized.");
1198 }
1199#endif
1200 }
1201
1202 }
1203
1204 if (manualDispatch)
1205 context.PrepareRendererListsAsync(m_ActiveRendererLists);
1206 }
1207
1208 internal void Clear(bool onException)
1209 {
1210 LogResources();
1211
1212 for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
1213 m_RenderGraphResources[i].Clear(onException, m_CurrentFrameIndex);
1214 m_RendererListResources.Clear();
1215 m_RendererListLegacyResources.Clear();
1216 m_ActiveRendererLists.Clear();
1217 }
1218
1219 internal void PurgeUnusedGraphicsResources()
1220 {
1221 for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
1222 m_RenderGraphResources[i].PurgeUnusedGraphicsResources(m_CurrentFrameIndex);
1223 }
1224
1225 internal void Cleanup()
1226 {
1227 for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
1228 m_RenderGraphResources[i].Cleanup();
1229
1230 RTHandles.Release(m_CurrentBackbuffer);
1231 }
1232
1233 internal void FlushLogs()
1234 {
1235 Debug.Log(m_ResourceLogger.GetAllLogs());
1236 }
1237
1238 void LogResources()
1239 {
1240 if (m_RenderGraphDebug.enableLogging)
1241 {
1242 m_ResourceLogger.LogLine("==== Allocated Resources ====\n");
1243
1244 for (int type = 0; type < (int)RenderGraphResourceType.Count; ++type)
1245 {
1246 if (m_RenderGraphResources[type].pool != null)
1247 {
1248 m_RenderGraphResources[type].pool.LogResources(m_ResourceLogger);
1249 m_ResourceLogger.LogLine("");
1250 }
1251 }
1252 }
1253 }
1254
1255 #endregion
1256 }
1257}