-
Notifications
You must be signed in to change notification settings - Fork 869
Expand file tree
/
Copy pathRenderGraph.cs
More file actions
3233 lines (2770 loc) · 154 KB
/
RenderGraph.cs
File metadata and controls
3233 lines (2770 loc) · 154 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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>
/// Expresses additional pass properties that can be used to perform optimizations on some platforms.
/// </summary>
[Flags]
public enum ExtendedFeatureFlags
{
///<summary>Default state with no extended features enabled.</summary>
None = 0,
///<summary>On Meta XR, this flag can be set for the pass that performs the most 3D rendering to achieve better performance.</summary>
TileProperties = 1 << 0,
///<summary>On XR, this flag can be set for passes that are compatible with Multiview Render Regions</summary>
MultiviewRenderRegionsCompatible = 1 << 1,
///<summary>On Meta XR, this flag can be set to use MSAA shader resolve in the last subpass of a render pass. </summary>
MultisampledShaderResolve = 1 << 2,
}
[Flags]
internal enum RenderGraphState
{
/// <summary>
/// Render Graph is not doing anything.
/// </summary>
Idle = 0,
/// <summary>
/// Render Graph is recording the graph.
/// </summary>
RecordingGraph = 1 << 0,
/// <summary>
/// Render Graph is recording a low level pass.
/// </summary>
RecordingPass = 1 << 1,
/// <summary>
/// Render Graph is executing the graph.
/// </summary>
Executing = 1 << 2,
/// <summary>
/// Utility flag to check if the graph is active.
/// </summary>
Active = RecordingGraph | RecordingPass | Executing
}
/// <summary>
/// The strategy that the render pipeline should use to determine the UV origin of RenderTextures who have an Unknown TextureUVOrigin when rendering.
/// </summary>
public enum RenderTextureUVOriginStrategy
{
/// <summary>RenderTextures are always treated as bottom left orientation.</summary>
BottomLeft,
/// <summary>RenderTextures may inherit the backbuffer attachment orientation if they are only used via attachment reads.</summary>
PropagateAttachmentOrientation
}
/// <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 NativeRenderPassCompiler.CompilerContextData compilerContext;
internal bool contextlessTesting;
internal bool forceResourceCreation;
}
// InternalRenderGraphContext is public (but all members are internal)
// only because the C# standard says that all interface member function implementations must 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.
/// <summary>
/// Interface implemented by the different render graph contexts provided at execution timeline (via SetRenderFunc())
/// </summary>
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>
/// Retrieves the TextureUVOrigin of the Render Graph texture from its handle.
/// </summary>
/// <remarks>
/// This function can only be called when using the Native Render Pass Compiler (enabled by default).
/// </remarks>
/// <param name="textureHandle">The texture handle to query.</param>
/// <returns>The TextureUVOrigin of the texture.</returns>
public TextureUVOrigin GetTextureUVOrigin(in TextureHandle textureHandle);
}
/// <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")]
[Obsolete("RenderGraphContext is deprecated, use RasterGraphContext/ComputeGraphContext/UnsafeGraphContext instead.")]
public struct RenderGraphContext : IDerivedRendergraphContext
{
private InternalRenderGraphContext wrappedContext;
/// <inheritdoc />
public void FromInternalContext(InternalRenderGraphContext context)
{
wrappedContext = context;
}
/// <inheritdoc />
public readonly TextureUVOrigin GetTextureUVOrigin(in TextureHandle textureHandle) { return TextureUVOrigin.BottomLeft; }
///<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;
}
public int CurrentRGPassId() {
return cmd.m_ExecutingPass.index;
}
/// <inheritdoc />
public readonly TextureUVOrigin GetTextureUVOrigin(in TextureHandle textureHandle)
{
if (!SystemInfo.graphicsUVStartsAtTop)
return TextureUVOrigin.BottomLeft;
if (wrappedContext.compilerContext != null)
{
return wrappedContext.compilerContext.GetTextureUVOrigin(textureHandle);
}
return TextureUVOrigin.BottomLeft;
}
}
/// <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;
}
/// <inheritdoc />
public TextureUVOrigin GetTextureUVOrigin(in TextureHandle textureHandle)
{
if (!SystemInfo.graphicsUVStartsAtTop)
return TextureUVOrigin.BottomLeft;
if (wrappedContext.compilerContext != null)
{
return wrappedContext.compilerContext.GetTextureUVOrigin(textureHandle);
}
return TextureUVOrigin.BottomLeft;
}
}
/// <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;
}
/// <inheritdoc />
public TextureUVOrigin GetTextureUVOrigin(in TextureHandle textureHandle)
{
if (!SystemInfo.graphicsUVStartsAtTop)
return TextureUVOrigin.BottomLeft;
if (wrappedContext.compilerContext != null)
{
return wrappedContext.compilerContext.GetTextureUVOrigin(textureHandle);
}
return TextureUVOrigin.BottomLeft;
}
}
/// <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>
[Obsolete("Not used anymore. The debugging tools use the name of the object identified by executionId. #from(6000.3)")]
public string executionName;
///<summary>Identifier for this render graph execution (i.e. EntityId of the Camera rendering). Used for debugging tools.</summary>
public EntityId executionId;
///<summary>Whether the execution should generate debug data and be visible in Render Graph Viewer.</summary>
public bool generateDebugData;
///<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 strategy that the rendergraph should use to determine the texture uv origin if Unknown of RenderTextures when rendering.</summary>
public RenderTextureUVOriginStrategy renderTextureUVOriginStrategy;
}
/// <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 ExtendedFeatureFlags extendedFeatureFlags;
public bool hasShadingRateImage;
public bool hasShadingRateStates;
public void Reset(RenderGraphPass pass, int index)
{
name = pass.name;
this.index = index;
enableAsyncCompute = pass.enableAsyncCompute;
allowPassCulling = pass.allowPassCulling;
enableFoveatedRasterization = pass.enableFoveatedRasterization;
extendedFeatureFlags = ExtendedFeatureFlags.None;
hasShadingRateImage = pass.hasShadingRateImage && !pass.enableFoveatedRasterization;
hasShadingRateStates = pass.hasShadingRateStates && !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 instead of the traditional SetRenderTarget workflow for AddRasterRenderPass() API. Enabled by default since 6000.3.
/// </summary>
/// <remarks>
/// 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).
/// </remarks>
public bool nativeRenderPassesEnabled { get; set; } = true;
internal static bool hasAnyRenderGraphWithNativeRenderPassesEnabled
{
get
{
foreach (var (graph, _) in s_RegisteredExecutions)
if (graph.nativeRenderPassesEnabled)
return true;
return false;
}
}
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>();
EntityId m_CurrentExecutionId;
bool m_CurrentExecutionCanGenerateDebugData;
int m_ExecutionCount;
int m_CurrentFrameIndex;
int m_CurrentImmediatePassIndex;
bool m_ExecutionExceptionWasRaised;
bool m_RendererListCulling;
bool m_EnableCompilationCaching;
internal/*for tests*/ static bool? s_EnableCompilationCachingForTests;
CompiledGraph m_DefaultCompiledGraph = new();
CompiledGraph m_CurrentCompiledGraph;
RenderGraphState m_RenderGraphState;
RenderTextureUVOriginStrategy m_renderTextureUVOriginStrategy;
// Global container of registered render graphs, associated with the list of executions that have been registered for them.
// When a RenderGraph is created, an entry is added to this dictionary. When that RenderGraph renders something,
// and a debug session is active, an entry is added to the list of executions for that RenderGraph using the executionId
// as the key. So when you render multiple times with the same executionId, only one DebugExecutionItem is created.
static Dictionary<RenderGraph, List<DebugExecutionItem>> s_RegisteredExecutions = new ();
#region Public Interface
/// <summary>Name of the Render Graph.</summary>
public string name { get; private set; } = "RenderGraph";
internal RenderGraphState RenderGraphState
{
get { return m_RenderGraphState; }
set { m_RenderGraphState = value; }
}
/// <summary>The strategy the Render Graph will take for the uv origin of RenderTextures in the graph.</summary>
public RenderTextureUVOriginStrategy renderTextureUVOriginStrategy
{
get { return m_renderTextureUVOriginStrategy; }
internal set { m_renderTextureUVOriginStrategy = value; }
}
/// <summary>If true, the Render Graph Viewer is active.</summary>
public static bool isRenderGraphViewerActive => RenderGraphDebugSession.hasActiveDebugSession;
/// <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 instance.</param>
public RenderGraph(string name = "RenderGraph")
{
this.name = name;
if (GraphicsSettings.TryGetRenderPipelineSettings<RenderGraphGlobalSettings>(out var renderGraphGlobalSettings))
{
m_EnableCompilationCaching = renderGraphGlobalSettings.enableCompilationCaching;
enableValidityChecks = renderGraphGlobalSettings.enableValidityChecks;
}
else // No SRP pipeline is present/active, it can happen with unit tests
{
enableValidityChecks = true;
}
if (s_EnableCompilationCachingForTests.HasValue)
m_EnableCompilationCaching = s_EnableCompilationCachingForTests.Value;
if (m_EnableCompilationCaching)
m_CompilationCache = new RenderGraphCompilationCache();
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);
RegisterGraph();
m_RenderGraphState = RenderGraphState.Idle;
RenderGraph.RenderGraphExceptionMessages.enableCaller = true;
#if !UNITY_EDITOR && DEVELOPMENT_BUILD
if (RenderGraphDebugSession.currentDebugSession == null)
RenderGraphDebugSession.Create<RenderGraphPlayerRemoteDebugSession>();
#endif
}
// Internal, only for testing
// Useful when we need to clean when calling
// internal functions in tests even if Render Graph is active
// This API shouldn't be called when the render graph is active!
internal void CleanupResourcesAndGraph()
{
// Usually done at the end of Execute step
// Also doing it here in case RG stopped before it
ClearCurrentCompiledGraph();
m_Resources.Cleanup();
m_DefaultResources.Cleanup();
m_RenderGraphPool.Cleanup();
nativeCompiler?.Cleanup();
m_CompilationCache?.Clear();
DelegateHashCodeUtils.ClearCache();
}
/// <summary>
/// Free up all resources used internally by the Render Graph instance, and unregister it so it won't be visible in the Render Graph Viewer.
/// </summary>
public void Cleanup()
{
CheckNotUsedWhenActive();
// Dispose of the compiled graphs left over in the cache
m_CompilationCache?.Cleanup();
CleanupResourcesAndGraph();
UnregisterGraph();
}
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>
/// <remarks>
/// This API cannot be called when Render Graph is active, please call it outside of RecordRenderGraph().
/// </remarks>
/// <param name="panel">Optional debug panel to which the render graph debug parameters will be registered.</param>
public void RegisterDebug(DebugUI.Panel panel = null)
{
CheckNotUsedWhenActive();
m_DebugParameters.RegisterDebug(name, panel);
}
/// <summary>
/// Unregister render graph from the debug window.
/// </summary>
/// <remarks>
/// This API cannot be called when Render Graph is active, please call it outside of RecordRenderGraph().
/// </remarks>
public void UnRegisterDebug()
{
CheckNotUsedWhenActive();
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 new List<RenderGraph>(s_RegisteredExecutions.Keys);
}
internal static Dictionary<RenderGraph, List<DebugExecutionItem>> GetRegisteredExecutions() => s_RegisteredExecutions;
/// <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>
/// <remarks>
/// This API cannot be called when Render Graph is active, please call it outside of RecordRenderGraph().
/// </remarks>
public void EndFrame()
{
CheckNotUsedWhenActive();
m_Resources.PurgeUnusedGraphicsResources();
if (m_DebugParameters.logFrameInformation)
m_FrameInformationLogger.FlushLogs();
if (m_DebugParameters.logResources)
m_Resources.FlushLogs();
m_DebugParameters.ResetLogging();
}
/// <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>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <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)
{
CheckNotUsedWhenExecuting();
return m_Resources.ImportTexture(rt);
}
/// <summary>
/// Import an external Variable Rate Shading (VRS) textures to the RenderGraph.
/// Any pass writing to an imported texture will be considered having side effects and can't be automatically culled.
/// </summary>
/// <param name="rt">External shading rate image RTHandle that needs to be imported.</param>
/// <returns>New TextureHandle that represents the imported shading rate images in the context of this rendergraph.</returns>
public TextureHandle ImportShadingRateImageTexture(RTHandle rt)
{
if (ShadingRateInfo.supportsPerImageTile)
return m_Resources.ImportTexture(rt);
return TextureHandle.nullHandle;
}
/// <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>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <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)
{
CheckNotUsedWhenExecuting();
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, Rendergraph 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>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <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())
{
CheckNotUsedWhenExecuting();
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>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <param name="rt">External RTHandle that needs to be imported.</param>
/// <param name="isBuiltin">The handle is a builtin handle managed by RenderGraph internally.</param>
/// <returns>A new TextureHandle that represents the imported texture in the context of this rendergraph.</returns>
internal TextureHandle ImportTexture(RTHandle rt, bool isBuiltin)
{
CheckNotUsedWhenExecuting();
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>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <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())
{
CheckNotUsedWhenExecuting();
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>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <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)
{
CheckNotUsedWhenExecuting();
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>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <param name="desc">Texture descriptor.</param>
/// <returns>A new TextureHandle.</returns>
public TextureHandle CreateTexture(in TextureDesc desc)
{
CheckNotUsedWhenExecuting();
return m_Resources.CreateTexture(desc);
}
/// <summary>
/// Create a new Render Graph Shared Texture resource.
/// This texture will be persistent across render graph executions.
/// </summary>
/// <remarks>
/// This API should not be used with URP NRP Render Graph. This API cannot be called when Render Graph is active, please call it outside of RecordRenderGraph().
/// </remarks>
/// <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>
[Obsolete("CreateSharedTexture() and shared texture workflow are deprecated, use ImportTexture() workflow instead.")]
public TextureHandle CreateSharedTexture(in TextureDesc desc, bool explicitRelease = false)
{
CheckNotUsingNativeRenderPassCompiler();
CheckNotUsedWhenActive();
return m_Resources.CreateSharedTexture(desc, explicitRelease);
}
/// <summary>
/// Refresh a shared texture with a new descriptor.
/// </summary>
/// <remarks>
/// This API should not be used with URP NRP Render Graph.
/// </remarks>
/// <param name="handle">Shared texture that needs to be updated.</param>
/// <param name="desc">New Descriptor for the texture.</param>
[Obsolete("RefreshSharedTextureDesc() and shared texture workflow are deprecated, use ImportTexture() workflow instead.")]
public void RefreshSharedTextureDesc(TextureHandle handle, in TextureDesc desc)
{
CheckNotUsingNativeRenderPassCompiler();
m_Resources.RefreshSharedTextureDesc(handle, desc);
}
/// <summary>
/// Release a Render Graph shared texture resource.
/// </summary>
/// <remarks>
/// This API should not be used with URP NRP Render Graph. This API cannot be called when Render Graph is active, please call it outside of RecordRenderGraph().
/// </remarks>
/// <param name="texture">The handle to the texture that needs to be release.</param>
[Obsolete("ReleaseSharedTexture() and shared texture workflow are deprecated, use ImportTexture() workflow instead.")]
public void ReleaseSharedTexture(TextureHandle texture)
{
CheckNotUsingNativeRenderPassCompiler();
CheckNotUsedWhenActive();
m_Resources.ReleaseSharedTexture(texture);
}
/// <summary>
/// Create a new Render Graph Texture resource using the descriptor from another texture.
/// </summary>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <param name="texture">Texture from which the descriptor should be used.</param>
/// <returns>A new TextureHandle.</returns>
public TextureHandle CreateTexture(TextureHandle texture)
{
CheckNotUsedWhenExecuting();
return m_Resources.CreateTexture(in m_Resources.GetTextureResourceDesc(texture.handle));
}
/// <summary>
/// Create a new Render Graph Texture resource using the descriptor from another texture.
/// </summary>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <param name="texture">Texture from which the descriptor should be used.</param>
/// <param name="name">The destination texture name.</param>
/// <param name="clear">Texture needs to be cleared on first use.</param>
/// <returns>A new TextureHandle.</returns>
public TextureHandle CreateTexture(TextureHandle texture, string name, bool clear = false)
{
CheckNotUsedWhenExecuting();
var destinationDesc = GetTextureDesc(texture);
destinationDesc.name = name;
destinationDesc.clearBuffer = clear;
return m_Resources.CreateTexture(destinationDesc);
}