-
Notifications
You must be signed in to change notification settings - Fork 822
/
Copy pathRenderGraph.cs
2668 lines (2303 loc) · 127 KB
/
RenderGraph.cs
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Scripting.APIUpdating;
// Typedef for the in-engine RendererList API (to avoid conflicts with the experimental version)
using CoreRendererListDesc = UnityEngine.Rendering.RendererUtils.RendererListDesc;
namespace UnityEngine.Rendering.RenderGraphModule
{
/// <summary>
/// Sets the read and write access for the depth buffer.
/// </summary>
[Flags][MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public enum DepthAccess
{
///<summary>Read Access.</summary>
Read = 1 << 0,
///<summary>Write Access.</summary>
Write = 1 << 1,
///<summary>Read and Write Access.</summary>
ReadWrite = Read | Write,
}
/// <summary>
/// Express the operations the rendergraph pass will do on a resource.
/// </summary>
[Flags][MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public enum AccessFlags
{
///<summary>The pass does not access the resource at all. Calling Use* functions with none has no effect.</summary>
None = 0,
///<summary>This pass will read data the resource. Data in the resource should never be written unless one of the write flags is also present. Writing to a read-only resource may lead to undefined results, significant performance penaties, and GPU crashes.</summary>
Read = 1 << 0,
///<summary>This pass will at least write some data to the resource. Data in the resource should never be read unless one of the read flags is also present. Reading from a write-only resource may lead to undefined results, significant performance penaties, and GPU crashes.</summary>
Write = 1 << 1,
///<summary>Previous data in the resource is not preserved. The resource will contain undefined data at the beginning of the pass.</summary>
Discard = 1 << 2,
///<summary>All data in the resource will be written by this pass. Data in the resource should never be read.</summary>
WriteAll = Write | Discard,
///<summary> Shortcut for Read | Write</summary>
ReadWrite = Read | Write
}
/// <summary>
/// An object representing the internal context of a rendergraph pass execution.
/// This object is public for technical reasons only and should not be used.
/// </summary>
[MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public class InternalRenderGraphContext
{
internal ScriptableRenderContext renderContext;
internal CommandBuffer cmd;
internal RenderGraphObjectPool renderGraphPool;
internal RenderGraphDefaultResources defaultResources;
internal RenderGraphPass executingPass;
internal bool contextlessTesting;
}
// This whole thing is a bit of a mess InternalRenderGraphContext is public (but all members are internal)
// just because the C# standard says that all interface member function implementations should be public.
// So below in for example the RasterGraphContext we can't implement the (internal) interface as
// internal void FromInternalContext(InternalRenderGraphContext context) { ... }
// So we have to make FromInternalContext public so InternalRenderGraphContext also becomes public.
// This seems an oversight in c# where Interfaces used as Generic constraints could very well be useful
// with internal only functions.
internal interface IDerivedRendergraphContext
{
/// <summary>
/// This function is only public for techical resons of the c# language and should not be called outside the package.
/// </summary>
/// <param name="context">The context to convert</param>
public void FromInternalContext(InternalRenderGraphContext context);
}
/// <summary>
/// This class specifies the context given to every render pass. This context type passes a generic
/// command buffer that can be used to schedule all commands. This will eventually be deprecated
/// in favor of more specific contexts that have more specific command buffer types.
/// </summary>
[MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public struct RenderGraphContext : IDerivedRendergraphContext
{
private InternalRenderGraphContext wrappedContext;
/// <inheritdoc />
public void FromInternalContext(InternalRenderGraphContext context)
{
wrappedContext = context;
}
///<summary>Scriptable Render Context used for rendering.</summary>
public ScriptableRenderContext renderContext { get => wrappedContext.renderContext; }
///<summary>Command Buffer used for rendering.</summary>
public CommandBuffer cmd { get => wrappedContext.cmd; }
///<summary>Render Graph pool used for temporary data.</summary>
public RenderGraphObjectPool renderGraphPool { get => wrappedContext.renderGraphPool; }
///<summary>Render Graph default resources.</summary>
public RenderGraphDefaultResources defaultResources { get => wrappedContext.defaultResources; }
}
/// <summary>
/// This class declares the context object passed to the execute function of a raster render pass.
/// <see cref="RenderGraph.AddRasterRenderPass"/>
/// </summary>
[MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public struct RasterGraphContext : IDerivedRendergraphContext
{
private InternalRenderGraphContext wrappedContext;
///<summary>Command Buffer used for rendering.</summary>
public RasterCommandBuffer cmd;
///<summary>Render Graph default resources.</summary>
public RenderGraphDefaultResources defaultResources { get => wrappedContext.defaultResources; }
///<summary>Render Graph pool used for temporary data.</summary>
public RenderGraphObjectPool renderGraphPool { get => wrappedContext.renderGraphPool; }
static internal RasterCommandBuffer rastercmd = new RasterCommandBuffer(null, null, false);
/// <inheritdoc />
public void FromInternalContext(InternalRenderGraphContext context)
{
wrappedContext = context;
rastercmd.m_WrappedCommandBuffer = wrappedContext.cmd;
rastercmd.m_ExecutingPass = context.executingPass;
cmd = rastercmd;
}
}
/// <summary>
/// This class declares the context object passed to the execute function of a compute render pass.
/// <see cref="RenderGraph.AddComputePass"/>
/// </summary>
[MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public class ComputeGraphContext : IDerivedRendergraphContext
{
private InternalRenderGraphContext wrappedContext;
///<summary>Command Buffer used for rendering.</summary>
public ComputeCommandBuffer cmd;
///<summary>Render Graph default resources.</summary>
public RenderGraphDefaultResources defaultResources { get => wrappedContext.defaultResources; }
///<summary>Render Graph pool used for temporary data.</summary>
public RenderGraphObjectPool renderGraphPool { get => wrappedContext.renderGraphPool; }
static internal ComputeCommandBuffer computecmd = new ComputeCommandBuffer(null, null, false);
/// <inheritdoc />
public void FromInternalContext(InternalRenderGraphContext context)
{
wrappedContext = context;
computecmd.m_WrappedCommandBuffer = wrappedContext.cmd;
computecmd.m_ExecutingPass = context.executingPass;
cmd = computecmd;
}
}
/// <summary>
/// This class declares the context object passed to the execute function of an unsafe render pass.
/// <see cref="RenderGraph.AddUnsafePass"/>
/// </summary>
[MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public class UnsafeGraphContext : IDerivedRendergraphContext
{
private InternalRenderGraphContext wrappedContext;
///<summary>Unsafe Command Buffer used for rendering.</summary>
public UnsafeCommandBuffer cmd;
///<summary>Render Graph default resources.</summary>
public RenderGraphDefaultResources defaultResources { get => wrappedContext.defaultResources; }
///<summary>Render Graph pool used for temporary data.</summary>
public RenderGraphObjectPool renderGraphPool { get => wrappedContext.renderGraphPool; }
internal static UnsafeCommandBuffer unsCmd = new UnsafeCommandBuffer(null, null, false);
/// <inheritdoc />
public void FromInternalContext(InternalRenderGraphContext context)
{
wrappedContext = context;
unsCmd.m_WrappedCommandBuffer = wrappedContext.cmd;
unsCmd.m_ExecutingPass = context.executingPass;
cmd = unsCmd;
}
}
/// <summary>
/// This struct contains properties which control the execution of the Render Graph.
/// </summary>
[MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public struct RenderGraphParameters
{
///<summary>Identifier for this render graph execution.</summary>
public string executionName;
///<summary>Index of the current frame being rendered.</summary>
public int currentFrameIndex;
///<summary> Controls whether to enable Renderer List culling or not.</summary>
public bool rendererListCulling;
///<summary>Scriptable Render Context used by the render pipeline.</summary>
public ScriptableRenderContext scriptableRenderContext;
///<summary>Command Buffer used to execute graphic commands.</summary>
public CommandBuffer commandBuffer;
///<summary>When running tests indicate the context is intentionally invalid and all calls on it should just do nothing.
///This allows you to run tests that rely on code execution the way to the pass render functions
///This also changes some behaviours with exception handling and error logging so the test framework can act on exceptions to validate behaviour better.</summary>
internal bool invalidContextForTesting;
}
/// <summary>
/// The Render Pass rendering delegate to use with typed contexts.
/// </summary>
/// <typeparam name="PassData">The type of the class used to provide data to the Render Pass.</typeparam>
/// <typeparam name="ContextType">The type of the context that will be passed to the render function.</typeparam>
/// <param name="data">Render Pass specific data.</param>
/// <param name="renderGraphContext">Global Render Graph context.</param>
[MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public delegate void BaseRenderFunc<PassData, ContextType>(PassData data, ContextType renderGraphContext) where PassData : class, new();
/// <summary>
/// This class is the main entry point of the Render Graph system.
/// </summary>
[MovedFrom(true, "UnityEngine.Experimental.Rendering.RenderGraphModule", "UnityEngine.Rendering.RenderGraphModule")]
public partial class RenderGraph
{
///<summary>Maximum number of MRTs supported by Render Graph.</summary>
public static readonly int kMaxMRTCount = 8;
internal struct CompiledResourceInfo
{
public List<int> producers;
public List<int> consumers;
public int refCount;
public bool imported;
public void Reset()
{
if (producers == null)
producers = new List<int>();
if (consumers == null)
consumers = new List<int>();
producers.Clear();
consumers.Clear();
refCount = 0;
imported = false;
}
}
[DebuggerDisplay("RenderPass: {name} (Index:{index} Async:{enableAsyncCompute})")]
internal struct CompiledPassInfo
{
public string name;
public int index;
public List<int>[] resourceCreateList;
public List<int>[] resourceReleaseList;
public GraphicsFence fence;
#if DEVELOPMENT_BUILD || UNITY_EDITOR
// This members are only here to ease debugging.
public List<string>[] debugResourceReads;
public List<string>[] debugResourceWrites;
#endif
public int refCount;
public int syncToPassIndex; // Index of the pass that needs to be waited for.
public int syncFromPassIndex; // Smaller pass index that waits for this pass.
public bool enableAsyncCompute;
public bool allowPassCulling;
public bool needGraphicsFence;
public bool culled;
public bool culledByRendererList;
public bool hasSideEffect;
public bool enableFoveatedRasterization;
public void Reset(RenderGraphPass pass, int index)
{
name = pass.name;
this.index = index;
enableAsyncCompute = pass.enableAsyncCompute;
allowPassCulling = pass.allowPassCulling;
enableFoveatedRasterization = pass.enableFoveatedRasterization;
if (resourceCreateList == null)
{
resourceCreateList = new List<int>[(int)RenderGraphResourceType.Count];
resourceReleaseList = new List<int>[(int)RenderGraphResourceType.Count];
for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
{
resourceCreateList[i] = new List<int>();
resourceReleaseList[i] = new List<int>();
}
#if DEVELOPMENT_BUILD || UNITY_EDITOR
debugResourceReads = new List<string>[(int)RenderGraphResourceType.Count];
debugResourceWrites = new List<string>[(int)RenderGraphResourceType.Count];
for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
{
debugResourceReads[i] = new List<string>();
debugResourceWrites[i] = new List<string>();
}
#endif
}
for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
{
resourceCreateList[i].Clear();
resourceReleaseList[i].Clear();
}
refCount = 0;
culled = false;
culledByRendererList = false;
hasSideEffect = false;
syncToPassIndex = -1;
syncFromPassIndex = -1;
needGraphicsFence = false;
#if DEVELOPMENT_BUILD || UNITY_EDITOR
for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
{
debugResourceReads[i].Clear();
debugResourceWrites[i].Clear();
}
#endif
}
}
/// <summary>
/// Enable the use of the render pass API by the graph instead of traditional SetRenderTarget. This is an advanced
/// feature and users have to be aware of the specific impact it has on rendergraph/graphics APIs below.
///
/// When enabled, the render graph try to use render passes and supasses instead of relying on SetRendertarget. It
/// will try to aggressively optimize the number of BeginRenderPass+EndRenderPass calls as well as calls to NextSubPass.
/// This with the aim to maximize the time spent "on chip" on tile based renderers.
///
/// The Graph will automatically determine when to break render passes as well as the load and store actions to apply to these render passes.
/// To do this, the graph will analyze the use of textures. E.g. when a texture is used twice in a row as a active render target, the two
/// render graph passes will be merged in a single render pass with two surpasses. On the other hand if a render target is sampled as a texture in
/// a later pass this render target will be stored (and possibly resolved) and the render pass will be broken up.
///
/// When setting this setting to true some existing render graph API is no longer valid as it can't express detailed frame information needed to emit
/// native render pases. In particular:
/// - The ImportBackbuffer overload without a RenderTargetInfo argument.
/// - Any AddRenderPass overloads. The more specific AddRasterRenderPass/AddComputePass/AddUnsafePass functions should be used to register passes.
///
/// In addition to this, additional validation will be done on the correctness of arguments of existing API that was not previously done. This could lead
/// to new errors when using existing render graph code with nativeRenderPassesEnabled.
///
/// Note: that CommandBuffer.BeginRenderPass/EndRenderPass calls are different by design from SetRenderTarget so this could also have
/// effects outside of render graph (e.g. for code relying on the currently active render target as this will not be updated when using render passes).
/// </summary>
public bool nativeRenderPassesEnabled
{
get; set;
}
internal/*for tests*/ RenderGraphResourceRegistry m_Resources;
RenderGraphObjectPool m_RenderGraphPool = new RenderGraphObjectPool();
RenderGraphBuilders m_builderInstance = new RenderGraphBuilders();
internal/*for tests*/ List<RenderGraphPass> m_RenderPasses = new List<RenderGraphPass>(64);
List<RendererListHandle> m_RendererLists = new List<RendererListHandle>(32);
RenderGraphDebugParams m_DebugParameters = new RenderGraphDebugParams();
RenderGraphLogger m_FrameInformationLogger = new RenderGraphLogger();
RenderGraphDefaultResources m_DefaultResources = new RenderGraphDefaultResources();
Dictionary<int, ProfilingSampler> m_DefaultProfilingSamplers = new Dictionary<int, ProfilingSampler>();
InternalRenderGraphContext m_RenderGraphContext = new InternalRenderGraphContext();
CommandBuffer m_PreviousCommandBuffer;
List<int>[] m_ImmediateModeResourceList = new List<int>[(int)RenderGraphResourceType.Count];
RenderGraphCompilationCache m_CompilationCache;
RenderTargetIdentifier[][] m_TempMRTArrays = null;
internal interface ICompiledGraph
{
public void Clear();
}
// Compiled Render Graph info.
internal class CompiledGraph : ICompiledGraph
{
// This is a 1:1 mapping on the resource handle indexes, this means the first element with index 0 will represent the "null" handle
public DynamicArray<CompiledResourceInfo>[] compiledResourcesInfos = new DynamicArray<CompiledResourceInfo>[(int)RenderGraphResourceType.Count];
public DynamicArray<CompiledPassInfo> compiledPassInfos = new DynamicArray<CompiledPassInfo>();
public int lastExecutionFrame;
public CompiledGraph()
{
for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
{
compiledResourcesInfos[i] = new DynamicArray<CompiledResourceInfo>();
}
}
public void Clear()
{
for (int i = 0; i < (int)RenderGraphResourceType.Count; ++i)
compiledResourcesInfos[i].Clear();
compiledPassInfos.Clear();
}
void InitResourceInfosData(DynamicArray<CompiledResourceInfo> resourceInfos, int count)
{
resourceInfos.Resize(count);
for (int i = 0; i < resourceInfos.size; ++i)
resourceInfos[i].Reset();
}
public void InitializeCompilationData(List<RenderGraphPass> passes, RenderGraphResourceRegistry resources)
{
InitResourceInfosData(compiledResourcesInfos[(int)RenderGraphResourceType.Texture], resources.GetTextureResourceCount());
InitResourceInfosData(compiledResourcesInfos[(int)RenderGraphResourceType.Buffer], resources.GetBufferResourceCount());
InitResourceInfosData(compiledResourcesInfos[(int)RenderGraphResourceType.AccelerationStructure], resources.GetRayTracingAccelerationStructureResourceCount());
compiledPassInfos.Resize(passes.Count);
for (int i = 0; i < compiledPassInfos.size; ++i)
compiledPassInfos[i].Reset(passes[i], i);
}
}
Stack<int> m_CullingStack = new Stack<int>();
string m_CurrentExecutionName;
int m_ExecutionCount;
int m_CurrentFrameIndex;
int m_CurrentImmediatePassIndex;
bool m_ExecutionExceptionWasRaised;
bool m_HasRenderGraphBegun;
bool m_RendererListCulling;
bool m_EnableCompilationCaching;
CompiledGraph m_DefaultCompiledGraph = new();
CompiledGraph m_CurrentCompiledGraph;
string m_CaptureDebugDataForExecution; // Null unless debug data has been requested
Dictionary<string, DebugData> m_DebugData = new Dictionary<string, DebugData>();
// Global list of living render graphs
static List<RenderGraph> s_RegisteredGraphs = new List<RenderGraph>();
#region Public Interface
/// <summary>Name of the Render Graph.</summary>
public string name { get; private set; } = "RenderGraph";
/// <summary>Request debug data be captured for the provided execution on the next frame.</summary>
internal void RequestCaptureDebugData(string executionName)
{
m_CaptureDebugDataForExecution = executionName;
}
/// <summary>If true, the Render Graph Viewer is active.</summary>
public static bool isRenderGraphViewerActive { get; internal set; }
/// <summary>If true, the Render Graph will run its various validity checks while processing (not considered in release mode).</summary>
internal static bool enableValidityChecks { get; private set; }
/// <summary>
/// Set of default resources usable in a pass rendering code.
/// </summary>
public RenderGraphDefaultResources defaultResources
{
get
{
return m_DefaultResources;
}
}
/// <summary>
/// Render Graph constructor.
/// </summary>
/// <param name="name">Optional name used to identify the render graph instnace.</param>
public RenderGraph(string name = "RenderGraph")
{
this.name = name;
if (GraphicsSettings.TryGetRenderPipelineSettings<RenderGraphGlobalSettings>(out var renderGraphGlobalSettings))
{
m_EnableCompilationCaching = renderGraphGlobalSettings.enableCompilationCaching;
if (m_EnableCompilationCaching)
m_CompilationCache = new RenderGraphCompilationCache();
enableValidityChecks = renderGraphGlobalSettings.enableValidityChecks;
}
else // No SRP pipeline is present/active, it can happen with unit tests
{
enableValidityChecks = true;
}
m_TempMRTArrays = new RenderTargetIdentifier[kMaxMRTCount][];
for (int i = 0; i < kMaxMRTCount; ++i)
m_TempMRTArrays[i] = new RenderTargetIdentifier[i + 1];
m_Resources = new RenderGraphResourceRegistry(m_DebugParameters, m_FrameInformationLogger);
s_RegisteredGraphs.Add(this);
onGraphRegistered?.Invoke(this);
}
/// <summary>
/// Cleanup the Render Graph.
/// </summary>
public void Cleanup()
{
m_Resources.Cleanup();
m_DefaultResources.Cleanup();
m_RenderGraphPool.Cleanup();
s_RegisteredGraphs.Remove(this);
onGraphUnregistered?.Invoke(this);
nativeCompiler?.contextData?.Dispose();
m_CompilationCache?.Clear();
}
internal RenderGraphDebugParams debugParams => m_DebugParameters;
internal List<DebugUI.Widget> GetWidgetList()
{
return m_DebugParameters.GetWidgetList(name);
}
internal bool areAnySettingsActive => m_DebugParameters.AreAnySettingsActive;
/// <summary>
/// Register the render graph to the debug window.
/// </summary>
/// <param name="panel">Optional debug panel to which the render graph debug parameters will be registered.</param>
public void RegisterDebug(DebugUI.Panel panel = null)
{
m_DebugParameters.RegisterDebug(name, panel);
}
/// <summary>
/// Unregister render graph from the debug window.
/// </summary>
public void UnRegisterDebug()
{
m_DebugParameters.UnRegisterDebug(this.name);
}
/// <summary>
/// Get the list of all registered render graphs.
/// </summary>
/// <returns>The list of all registered render graphs.</returns>
public static List<RenderGraph> GetRegisteredRenderGraphs()
{
return s_RegisteredGraphs;
}
/// <summary>
/// Returns the last rendered frame debug data. Can be null if requireDebugData is set to false.
/// </summary>
/// <returns>The last rendered frame debug data</returns>
internal DebugData GetDebugData(string executionName)
{
if (m_DebugData.TryGetValue(executionName, out var debugData))
return debugData;
return null;
}
/// <summary>
/// End frame processing. Purge resources that have been used since last frame and resets internal states.
/// This need to be called once per frame.
/// </summary>
public void EndFrame()
{
m_Resources.PurgeUnusedGraphicsResources();
if (m_DebugParameters.logFrameInformation)
{
Debug.Log(m_FrameInformationLogger.GetAllLogs());
m_DebugParameters.logFrameInformation = false;
}
if (m_DebugParameters.logResources)
{
m_Resources.FlushLogs();
m_DebugParameters.logResources = false;
}
}
/// <summary>
/// Import an external texture to the Render Graph.
/// Any pass writing to an imported texture will be considered having side effects and can't be automatically culled.
/// </summary>
/// <param name="rt">External RTHandle that needs to be imported.</param>
/// <returns>A new TextureHandle that represents the imported texture in the context of this rendergraph.</returns>
public TextureHandle ImportTexture(RTHandle rt)
{
return m_Resources.ImportTexture(rt);
}
/// <summary>
/// Import an external texture to the Render Graph.
/// Any pass writing to an imported texture will be considered having side effects and can't be automatically culled.
///
/// Note: RTHandles that wrap RenderTargetIdentifier will fail to import using this overload as render graph can't derive the render texture's properties.
/// In that case the overload taking a RenderTargetInfo argument should be used instead.
/// </summary>
/// <param name="rt">External RTHandle that needs to be imported.</param>
/// <param name="importParams">Info describing the clear behavior of imported textures. Clearing textures using importParams may be more efficient than manually clearing the texture using `cmd.Clear` on some hardware.</param>
/// <returns>A new TextureHandle that represents the imported texture in the context of this rendergraph.</returns>
public TextureHandle ImportTexture(RTHandle rt, ImportResourceParams importParams )
{
return m_Resources.ImportTexture(rt, importParams);
}
/// <summary>
/// Import an external texture to the Render Graph. This overload should be used for RTHandles wrapping a RenderTargetIdentifier.
/// If the RTHandle is wrapping a RenderTargetIdentifer, Rendergrpah can't derive the render texture's properties so the user has to provide this info to the graph through RenderTargetInfo.
///
/// Any pass writing to an imported texture will be considered having side effects and can't be automatically culled.
///
/// Note: To avoid inconsistencies between the passed in RenderTargetInfo and render texture this overload can only be used when the RTHandle is wrapping a RenderTargetIdentifier.
/// If this is not the case, the overload of ImportTexture without a RenderTargetInfo argument should be used instead.
/// </summary>
/// <param name="rt">External RTHandle that needs to be imported.</param>
/// <param name="info">The properties of the passed in RTHandle.</param>
/// <param name="importParams">Info describing the clear behavior of imported textures. Clearing textures using importParams may be more efficient than manually clearing the texture using `cmd.Clear` on some hardware.</param>
/// <returns>A new TextureHandle that represents the imported texture in the context of this rendergraph.</returns>
public TextureHandle ImportTexture(RTHandle rt, RenderTargetInfo info, ImportResourceParams importParams = new ImportResourceParams() )
{
return m_Resources.ImportTexture(rt, info, importParams);
}
/// <summary>
/// Import an external texture to the Render Graph and set the handle as builtin handle. This can only happen from within the graph module
/// so it is internal.
/// </summary>
internal TextureHandle ImportTexture(RTHandle rt, bool isBuiltin)
{
return m_Resources.ImportTexture(rt, isBuiltin);
}
/// <summary>
/// Import the final backbuffer to render graph. The rendergraph can't derive the properties of a RenderTargetIdentifier as it is an opaque handle so the user has to pass them in through the info argument.
/// </summary>
/// <param name="rt">Backbuffer render target identifier.</param>
/// <param name="info">The properties of the passed in RTHandle.</param>
/// <param name="importParams">Info describing the clear behavior of imported textures. Clearing textures using importParams may be more efficient than manually clearing the texture using `cmd.Clear` on some hardware.</param>
/// <returns>A new TextureHandle that represents the imported texture in the context of this rendergraph.</returns>
public TextureHandle ImportBackbuffer(RenderTargetIdentifier rt, RenderTargetInfo info, ImportResourceParams importParams = new ImportResourceParams())
{
return m_Resources.ImportBackbuffer(rt, info, importParams);
}
/// <summary>
/// Import the final backbuffer to render graph.
/// This function can only be used when nativeRenderPassesEnabled is false.
/// </summary>
/// <param name="rt">Backbuffer render target identifier.</param>
/// <returns>A new TextureHandle that represents the imported texture in the context of this rendergraph.</returns>
public TextureHandle ImportBackbuffer(RenderTargetIdentifier rt)
{
RenderTargetInfo dummy = new RenderTargetInfo();
dummy.width = dummy.height = dummy.volumeDepth = dummy.msaaSamples = 1;
dummy.format = GraphicsFormat.R8G8B8A8_SRGB;
return m_Resources.ImportBackbuffer(rt, dummy, new ImportResourceParams());
}
/// <summary>
/// Create a new Render Graph Texture resource.
/// </summary>
/// <param name="desc">Texture descriptor.</param>
/// <returns>A new TextureHandle.</returns>
public TextureHandle CreateTexture(in TextureDesc desc)
{
return m_Resources.CreateTexture(desc);
}
/// <summary>
/// Create a new Render Graph Shared Texture resource.
/// This texture will be persistent across render graph executions.
/// </summary>
/// <param name="desc">Creation descriptor of the texture.</param>
/// <param name="explicitRelease">Set to true if you want to manage the lifetime of the resource yourself. Otherwise the resource will be released automatically if unused for a time.</param>
/// <returns>A new TextureHandle.</returns>
public TextureHandle CreateSharedTexture(in TextureDesc desc, bool explicitRelease = false)
{
if (m_HasRenderGraphBegun)
throw new InvalidOperationException("A shared texture can only be created outside of render graph execution.");
return m_Resources.CreateSharedTexture(desc, explicitRelease);
}
/// <summary>
/// Refresh a shared texture with a new descriptor.
/// </summary>
/// <param name="handle">Shared texture that needs to be updated.</param>
/// <param name="desc">New Descriptor for the texture.</param>
public void RefreshSharedTextureDesc(TextureHandle handle, in TextureDesc desc)
{
m_Resources.RefreshSharedTextureDesc(handle, desc);
}
/// <summary>
/// Release a Render Graph shared texture resource.
/// </summary>
/// <param name="texture">The handle to the texture that needs to be release.</param>
public void ReleaseSharedTexture(TextureHandle texture)
{
if (m_HasRenderGraphBegun)
throw new InvalidOperationException("A shared texture can only be release outside of render graph execution.");
m_Resources.ReleaseSharedTexture(texture);
}
/// <summary>
/// Create a new Render Graph Texture resource using the descriptor from another texture.
/// </summary>
/// <param name="texture">Texture from which the descriptor should be used.</param>
/// <returns>A new TextureHandle.</returns>
public TextureHandle CreateTexture(TextureHandle texture)
{
return m_Resources.CreateTexture(m_Resources.GetTextureResourceDesc(texture.handle));
}
/// <summary>
/// Create a new Render Graph Texture if the passed handle is invalid and use said handle as output.
/// If the passed handle is valid, no texture is created.
/// </summary>
/// <param name="desc">Desc used to create the texture.</param>
/// <param name="texture">Texture from which the descriptor should be used.</param>
public void CreateTextureIfInvalid(in TextureDesc desc, ref TextureHandle texture)
{
if (!texture.IsValid())
texture = m_Resources.CreateTexture(desc);
}
/// <summary>
/// Gets the descriptor of the specified Texture resource.
/// </summary>
/// <param name="texture">Texture resource from which the descriptor is requested.</param>
/// <returns>The input texture descriptor.</returns>
public TextureDesc GetTextureDesc(TextureHandle texture)
{
return m_Resources.GetTextureResourceDesc(texture.handle);
}
/// <summary>
/// Gets the descriptor of the specified Texture resource.
/// </summary>
/// <param name="texture">Texture resource from which the descriptor is requested.</param>
/// <returns>The input texture descriptor.</returns>
public RenderTargetInfo GetRenderTargetInfo(TextureHandle texture)
{
RenderTargetInfo info;
m_Resources.GetRenderTargetInfo(texture.handle, out info);
return info;
}
/// <summary>
/// Creates a new Renderer List Render Graph resource.
/// </summary>
/// <param name="desc">Renderer List descriptor.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateRendererList(in CoreRendererListDesc desc)
{
return m_Resources.CreateRendererList(desc);
}
/// <summary>
/// Creates a new Renderer List Render Graph resource.
/// </summary>
/// <param name="desc">Renderer List descriptor.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateRendererList(in RendererListParams desc)
{
return m_Resources.CreateRendererList(desc);
}
/// <summary>
/// Creates a new Shadow Renderer List Render Graph resource.
/// </summary>
/// <param name="shadowDrawingSettings">DrawSettings that describe the shadow drawcall.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateShadowRendererList(ref ShadowDrawingSettings shadowDrawingSettings)
{
return m_Resources.CreateShadowRendererList(m_RenderGraphContext.renderContext, ref shadowDrawingSettings);
}
/// <summary>
/// Creates a new Gizmo Renderer List Render Graph resource.
/// </summary>
/// <param name="camera">The camera that is used for rendering the Gizmo.</param>
/// <param name="gizmoSubset">GizmoSubset that specifies whether gizmos render before or after postprocessing for a camera render. </param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateGizmoRendererList(in Camera camera, in GizmoSubset gizmoSubset)
{
return m_Resources.CreateGizmoRendererList(m_RenderGraphContext.renderContext, camera, gizmoSubset);
}
/// <summary>
/// Creates a new UIOverlay Renderer List Render Graph resource.
/// </summary>
/// <param name="camera">The camera that is used for rendering the full UIOverlay.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateUIOverlayRendererList(in Camera camera)
{
return m_Resources.CreateUIOverlayRendererList(m_RenderGraphContext.renderContext, camera, UISubset.All);
}
/// <summary>
/// Creates a new UIOverlay Renderer List Render Graph resource.
/// </summary>
/// <param name="camera">The camera that is used for rendering some subset of the UIOverlay.</param>
/// <param name="uiSubset">Enum flag that specifies which subset to render.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateUIOverlayRendererList(in Camera camera, in UISubset uiSubset)
{
return m_Resources.CreateUIOverlayRendererList(m_RenderGraphContext.renderContext, camera, uiSubset);
}
/// <summary>
/// Creates a new WireOverlay Renderer List Render Graph resource.
/// </summary>
/// <param name="camera">The camera that is used for rendering the WireOverlay.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateWireOverlayRendererList(in Camera camera)
{
return m_Resources.CreateWireOverlayRendererList(m_RenderGraphContext.renderContext, camera);
}
/// <summary>
/// Creates a new Skybox Renderer List Render Graph resource.
/// </summary>
/// <param name="camera">The camera that is used for rendering the Skybox.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateSkyboxRendererList(in Camera camera)
{
return m_Resources.CreateSkyboxRendererList(m_RenderGraphContext.renderContext, camera);
}
/// <summary>
/// Creates a new Skybox Renderer List Render Graph resource.
/// </summary>
/// <param name="camera">The camera that is used for rendering the Skybox.</param>
/// <param name="projectionMatrix">The projection matrix used during XR rendering of the skybox.</param>
/// <param name="viewMatrix">The view matrix used during XR rendering of the skybox.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateSkyboxRendererList(in Camera camera, Matrix4x4 projectionMatrix, Matrix4x4 viewMatrix)
{
return m_Resources.CreateSkyboxRendererList(m_RenderGraphContext.renderContext, camera, projectionMatrix, viewMatrix);
}
/// <summary>
/// Creates a new Skybox Renderer List Render Graph resource.
/// </summary>
/// <param name="camera">The camera that is used for rendering the Skybox.</param>
/// <param name="projectionMatrixL">The left eye projection matrix used during Legacy single pass XR rendering of the skybox.</param>
/// <param name="viewMatrixL">The left eye view matrix used during Legacy single pass XR rendering of the skybox.</param>
/// <param name="projectionMatrixR">The right eye projection matrix used during Legacy single pass XR rendering of the skybox.</param>
/// <param name="viewMatrixR">The right eye view matrix used during Legacy single pass XR rendering of the skybox.</param>
/// <returns>A new RendererListHandle.</returns>
public RendererListHandle CreateSkyboxRendererList(in Camera camera, Matrix4x4 projectionMatrixL, Matrix4x4 viewMatrixL, Matrix4x4 projectionMatrixR, Matrix4x4 viewMatrixR)
{
return m_Resources.CreateSkyboxRendererList(m_RenderGraphContext.renderContext, camera, projectionMatrixL, viewMatrixL, projectionMatrixR, viewMatrixR);
}
/// <summary>
/// Import an external Graphics Buffer to the Render Graph.
/// Any pass writing to an imported graphics buffer will be considered having side effects and can't be automatically culled.
/// </summary>
/// <param name="graphicsBuffer">External Graphics Buffer that needs to be imported.</param>
/// <param name="forceRelease">The imported graphics buffer will be released after usage.</param>
/// <returns>A new GraphicsBufferHandle.</returns>
public BufferHandle ImportBuffer(GraphicsBuffer graphicsBuffer, bool forceRelease = false)
{
return m_Resources.ImportBuffer(graphicsBuffer, forceRelease);
}
/// <summary>
/// Create a new Render Graph Graphics Buffer resource.
/// </summary>
/// <param name="desc">Graphics Buffer descriptor.</param>
/// <returns>A new GraphicsBufferHandle.</returns>
public BufferHandle CreateBuffer(in BufferDesc desc)
{
return m_Resources.CreateBuffer(desc);
}
/// <summary>
/// Create a new Render Graph Graphics Buffer resource using the descriptor from another graphics buffer.
/// </summary>
/// <param name="graphicsBuffer">Graphics Buffer from which the descriptor should be used.</param>
/// <returns>A new GraphicsBufferHandle.</returns>
public BufferHandle CreateBuffer(in BufferHandle graphicsBuffer)
{
return m_Resources.CreateBuffer(m_Resources.GetBufferResourceDesc(graphicsBuffer.handle));
}
/// <summary>
/// Gets the descriptor of the specified Graphics Buffer resource.
/// </summary>
/// <param name="graphicsBuffer">Graphics Buffer resource from which the descriptor is requested.</param>
/// <returns>The input graphics buffer descriptor.</returns>
public BufferDesc GetBufferDesc(in BufferHandle graphicsBuffer)
{
return m_Resources.GetBufferResourceDesc(graphicsBuffer.handle);
}
/// <summary>
/// Import an external RayTracingAccelerationStructure to the Render Graph.
/// Any pass writing to (building) an imported RayTracingAccelerationStructure will be considered having side effects and can't be automatically culled.
/// </summary>
/// <param name="accelStruct">External RayTracingAccelerationStructure that needs to be imported.</param>
/// <param name="name">Optional name for identifying the RayTracingAccelerationStructure in the Render Graph.</param>
/// <returns>A new RayTracingAccelerationStructureHandle.</returns>
public RayTracingAccelerationStructureHandle ImportRayTracingAccelerationStructure(in RayTracingAccelerationStructure accelStruct, string name = null)
{
return m_Resources.ImportRayTracingAccelerationStructure(accelStruct, name);
}
/// <summary>
/// Add a new Raster Render Pass to the Render Graph. Raster passes can execute rasterization workloads but cannot do other GPU work like copies or compute.
/// </summary>
/// <typeparam name="PassData">Type of the class to use to provide data to the Render Pass.</typeparam>
/// <param name="passName">Name of the new Render Pass (this is also be used to generate a GPU profiling marker).</param>
/// <param name="passData">Instance of PassData that is passed to the render function and you must fill.</param>
/// <param name="file">File name of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it.</param>
/// <param name="line">File line of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it.</param>
/// <returns>A new instance of a IRasterRenderGraphBuilder used to setup the new Rasterization Render Pass.</returns>
public IRasterRenderGraphBuilder AddRasterRenderPass<PassData>(string passName, out PassData passData
#if !CORE_PACKAGE_DOCTOOLS
, [CallerFilePath] string file = "",
[CallerLineNumber] int line = 0) where PassData : class, new()
#endif
{
return AddRasterRenderPass(passName, out passData, GetDefaultProfilingSampler(passName), file, line);
}
/// <summary>
/// Add a new Raster Render Pass to the Render Graph. Raster passes can execute rasterization workloads but cannot do other GPU work like copies or compute.
/// </summary>
/// <typeparam name="PassData">Type of the class to use to provide data to the Render Pass.</typeparam>
/// <param name="passName">Name of the new Render Pass (this is also be used to generate a GPU profiling marker).</param>
/// <param name="passData">Instance of PassData that is passed to the render function and you must fill.</param>
/// <param name="sampler">Profiling sampler used around the pass.</param>
/// <param name="file">File name of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it.</param>
/// <param name="line">File line of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it.</param>
/// <returns>A new instance of a IRasterRenderGraphBuilder used to setup the new Rasterization Render Pass.</returns>
public IRasterRenderGraphBuilder AddRasterRenderPass<PassData>(string passName, out PassData passData, ProfilingSampler sampler
#if !CORE_PACKAGE_DOCTOOLS
,[CallerFilePath] string file = "",
[CallerLineNumber] int line = 0) where PassData : class, new()
#endif
{
var renderPass = m_RenderGraphPool.Get<RasterRenderGraphPass<PassData>>();
renderPass.Initialize(m_RenderPasses.Count, m_RenderGraphPool.Get<PassData>(), passName, RenderGraphPassType.Raster, sampler);
AddPassDebugMetadata(renderPass, file, line);
passData = renderPass.data;
m_RenderPasses.Add(renderPass);
m_builderInstance.Setup(renderPass, m_Resources, this);
return m_builderInstance;
}
/// <summary>
/// Add a new Compute Render Pass to the Render Graph. Raster passes can execute rasterization workloads but cannot do other GPU work like copies or compute.
/// </summary>
/// <typeparam name="PassData">Type of the class to use to provide data to the Render Pass.</typeparam>
/// <param name="passName">Name of the new Render Pass (this is also be used to generate a GPU profiling marker).</param>
/// <param name="passData">Instance of PassData that is passed to the render function and you must fill.</param>
/// <param name="file">File name of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it.</param>
/// <param name="line">File line of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it.</param>
/// <returns>A new instance of a IRasterRenderGraphBuilder used to setup the new Rasterization Render Pass.</returns>
public IComputeRenderGraphBuilder AddComputePass<PassData>(string passName, out PassData passData
#if !CORE_PACKAGE_DOCTOOLS
, [CallerFilePath] string file = "",
[CallerLineNumber] int line = 0) where PassData : class, new()
#endif
{
return AddComputePass(passName, out passData, GetDefaultProfilingSampler(passName), file, line);
}
/// <summary>
/// Add a new Compute Render Pass to the Render Graph. Compute passes can execute compute workloads but cannot do rasterization.
/// </summary>
/// <typeparam name="PassData">Type of the class to use to provide data to the Render Pass.</typeparam>
/// <param name="passName">Name of the new Render Pass (this is also be used to generate a GPU profiling marker).</param>
/// <param name="passData">Instance of PassData that is passed to the render function and you must fill.</param>
/// <param name="sampler">Profiling sampler used around the pass.</param>
/// <param name="file">File name of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it.</param>
/// <param name="line">File line of the source file this function is called from. Used for debugging. This parameter is automatically generated by the compiler. Users do not need to pass it.</param>