A game about forced loneliness, made by TACStudios
1using System;
2using System.Diagnostics;
3using UnityEngine.Rendering.RenderGraphModule;
4
5namespace UnityEngine.Rendering
6{
7 /// <summary>
8 /// Render graph command buffer types inherit from this base class.
9 /// It provides some shared functionality for all command buffer types.
10 /// </summary>
11 public class BaseCommandBuffer
12 {
13 /// <summary>
14 /// The instance of Unity's CommandBuffer that this class encapsulates, providing access to lower-level rendering commands.
15 /// </summary>
16 protected internal CommandBuffer m_WrappedCommandBuffer;
17 internal RenderGraphPass m_ExecutingPass;
18
19 // Users cannot directly create command buffers. The rendergraph creates them and passes them to callbacks.
20 internal BaseCommandBuffer(CommandBuffer wrapped, RenderGraphPass executingPass, bool isAsync)
21 {
22 m_WrappedCommandBuffer = wrapped;
23 m_ExecutingPass = executingPass;
24 if (isAsync) m_WrappedCommandBuffer.SetExecutionFlags(CommandBufferExecutionFlags.AsyncCompute);
25 }
26
27 ///<summary>See (https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer-name.html)</summary>
28 public string name => m_WrappedCommandBuffer.name;
29
30 ///<summary>See (https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer-sizeInBytes.html)</summary>
31 public int sizeInBytes => m_WrappedCommandBuffer.sizeInBytes;
32
33 /// <summary>
34 /// Checks if modifying the global state is permitted by the currently executing render graph pass.
35 /// If such modifications are not allowed, an InvalidOperationException is thrown.
36 /// </summary>
37 /// <exception cref="InvalidOperationException">
38 /// Thrown if the current render graph pass does not permit modifications to global state.
39 /// </exception>
40 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
41 protected internal void ThrowIfGlobalStateNotAllowed()
42 {
43 if (m_ExecutingPass != null && !m_ExecutingPass.allowGlobalState) throw new InvalidOperationException($"{m_ExecutingPass.name}: Modifying global state from this command buffer is not allowed. Please ensure your render graph pass allows modifying global state.");
44 }
45
46 /// <summary>
47 /// Checks if the Raster Command Buffer has set a valid render target.
48 /// </summary>
49 /// <exception cref="InvalidOperationException">Thrown if the there are no active render targets.</exception>
50 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
51 protected internal void ThrowIfRasterNotAllowed()
52 {
53 if (m_ExecutingPass != null && !m_ExecutingPass.HasRenderAttachments()) throw new InvalidOperationException($"{m_ExecutingPass.name}: Using raster commands from a pass with no active render targets is not allowed as it will use an undefined render target state. Please set-up the pass's render targets using SetRenderAttachments.");
54 }
55
56 /// <summary>
57 /// Ensures that the texture handle being used is valid for the currently executing render graph pass.
58 /// This includes checks to ensure that the texture handle is registered for read or write access
59 /// and is not being used incorrectly as a render target attachment.
60 /// </summary>
61 /// <param name="h">The TextureHandle to validate for the current pass.</param>
62 /// <exception cref="Exception">
63 /// Throws an exception if the texture handle is not properly registered for the pass or being used incorrectly.
64 /// </exception>
65 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
66 protected internal void ValidateTextureHandle(TextureHandle h)
67 {
68 if(RenderGraph.enableValidityChecks)
69 {
70 if (m_ExecutingPass == null) return;
71
72 if (h.IsBuiltin()) return;
73
74 if (!m_ExecutingPass.IsRead(h.handle) && !m_ExecutingPass.IsWritten(h.handle))
75 {
76 throw new Exception("Pass '" + m_ExecutingPass.name + "' is trying to use a texture on the command buffer that was never registered with the pass builder. Please indicate the texture use to the pass builder.");
77 }
78 if (m_ExecutingPass.IsAttachment(h))
79 {
80 throw new Exception("Pass '" + m_ExecutingPass.name + "' is using a texture as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth) but is also trying to bind it as regular texture. Please fix this pass. ");
81 }
82 }
83 }
84
85 /// <summary>
86 /// Validates that the specified texture handle is registered for read access within the context of the current executing render graph pass.
87 /// Throws an exception if the texture is not registered for reading or is used incorrectly as a render target attachment.
88 /// </summary>
89 /// <param name="h">The TextureHandle to validate for read access.</param>
90 /// <exception cref="Exception">
91 /// Throws an exception if the texture handle is either not registered as a readable resource or misused as both an attachment and a regular texture.
92 /// </exception>
93 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
94 protected internal void ValidateTextureHandleRead(TextureHandle h)
95 {
96 if(RenderGraph.enableValidityChecks)
97 {
98 if (m_ExecutingPass == null) return;
99
100 if (!m_ExecutingPass.IsRead(h.handle))
101 {
102 throw new Exception("Pass '" + m_ExecutingPass.name + "' is trying to read a texture on the command buffer that was never registered with the pass builder. Please indicate the texture as read to the pass builder.");
103 }
104 if (m_ExecutingPass.IsAttachment(h))
105 {
106 throw new Exception("Pass '" + m_ExecutingPass.name + "' is using a texture as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth) but is also trying to bind it as regular texture. Please fix this pass. ");
107 }
108 }
109 }
110
111 /// <summary>
112 /// Validates that the specified texture handle is registered for write access within the context of the current executing render graph pass.
113 /// Additionally, it checks that built-in textures are not being written to, and that the texture is not incorrectly used as a render target attachment.
114 /// An exception is thrown if any of these checks fail.
115 /// </summary>
116 /// <param name="h">The TextureHandle to validate for write access.</param>
117 /// <exception cref="Exception">
118 /// Throws an exception if the texture handle is not registered for writing, attempts to write to a built-in texture, or is misused as both a writeable resource and a render target attachment.
119 /// </exception>
120 [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
121 protected internal void ValidateTextureHandleWrite(TextureHandle h)
122 {
123 if(RenderGraph.enableValidityChecks)
124 {
125 if (m_ExecutingPass == null) return;
126
127 if (h.IsBuiltin())
128 {
129 throw new Exception("Pass '" + m_ExecutingPass.name + "' is trying to write to a built-in texture. This is not allowed built-in textures are small default resources like `white` or `black` that cannot be written to.");
130 }
131
132 if (!m_ExecutingPass.IsWritten(h.handle))
133 {
134 throw new Exception("Pass '" + m_ExecutingPass.name + "' is trying to write a texture on the command buffer that was never registered with the pass builder. Please indicate the texture as written to the pass builder.");
135 }
136 if (m_ExecutingPass.IsAttachment(h))
137 {
138 throw new Exception("Pass '" + m_ExecutingPass.name + "' is using a texture as a fragment attachment (SetRenderAttachment/SetRenderAttachmentDepth) but is also trying to bind it as regular texture. Please fix this pass. ");
139 }
140 }
141 }
142 }
143}