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