A game about forced loneliness, made by TACStudios
at master 1029 lines 51 kB view raw
1using NUnit.Framework; 2using System; 3using System.Collections.Generic; 4using UnityEngine.Experimental.Rendering; 5using UnityEngine.Rendering.RenderGraphModule; 6using UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler; 7 8namespace UnityEngine.Rendering.Tests 9{ 10 class NativePassCompilerRenderGraphTests 11 { 12 class RenderGraphTestPassData 13 { 14 public TextureHandle[] textures = new TextureHandle[8]; 15 public BufferHandle[] buffers = new BufferHandle[8]; 16 } 17 18 TextureDesc SimpleTextureDesc(string name, int w, int h, int samples) 19 { 20 TextureDesc result = new TextureDesc(w, h); 21 result.msaaSamples = (MSAASamples)samples; 22 result.format = GraphicsFormat.R8G8B8A8_UNorm; 23 result.name = name; 24 return result; 25 } 26 27 class TestBuffers 28 { 29 public TextureHandle backBuffer; 30 public TextureHandle depthBuffer; 31 public TextureHandle[] extraBuffers = new TextureHandle[10]; 32 public TextureHandle extraDepthBuffer; 33 }; 34 35 TestBuffers ImportAndCreateBuffers(RenderGraph g) 36 { 37 TestBuffers result = new TestBuffers(); 38 var backBuffer = BuiltinRenderTextureType.CameraTarget; 39 var backBufferHandle = RTHandles.Alloc(backBuffer, "Backbuffer Color"); 40 var depthBuffer = BuiltinRenderTextureType.Depth; 41 var depthBufferHandle = RTHandles.Alloc(depthBuffer, "Backbuffer Depth"); 42 var extraDepthBufferHandle = RTHandles.Alloc(depthBuffer, "Extra Depth Buffer"); 43 44 RenderTargetInfo importInfo = new RenderTargetInfo(); 45 RenderTargetInfo importInfoDepth = new RenderTargetInfo(); 46 importInfo.width = 1024; 47 importInfo.height = 768; 48 importInfo.volumeDepth = 1; 49 importInfo.msaaSamples = 1; 50 importInfo.format = GraphicsFormat.R16G16B16A16_SFloat; 51 result.backBuffer = g.ImportTexture(backBufferHandle, importInfo); 52 53 importInfoDepth = importInfo; 54 importInfoDepth.format = GraphicsFormat.D32_SFloat_S8_UInt; 55 result.depthBuffer = g.ImportTexture(depthBufferHandle, importInfoDepth); 56 57 importInfo.format = GraphicsFormat.D24_UNorm; 58 result.extraDepthBuffer = g.ImportTexture(extraDepthBufferHandle, importInfoDepth); 59 60 for (int i = 0; i < result.extraBuffers.Length; i++) 61 { 62 result.extraBuffers[i] = g.CreateTexture(SimpleTextureDesc("ExtraBuffer" + i, 1024, 768, 1)); 63 } 64 65 return result; 66 } 67 68 RenderGraph AllocateRenderGraph() 69 { 70 RenderGraph g = new RenderGraph(); 71 g.nativeRenderPassesEnabled = true; 72 return g; 73 } 74 75 [Test] 76 public void SimpleMergePasses() 77 { 78 var g = AllocateRenderGraph(); 79 80 var buffers = ImportAndCreateBuffers(g); 81 82 // Render something to 0,1 83 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 84 { 85 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 86 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 87 builder.SetRenderAttachment(buffers.extraBuffers[1], 1, AccessFlags.Write); 88 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 89 } 90 91 // Render extra bits to 1 92 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 93 { 94 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 95 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 96 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 97 } 98 // Render to final buffer 99 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData)) 100 { 101 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 102 builder.SetRenderAttachment(buffers.extraBuffers[1], 1, AccessFlags.Write); 103 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 104 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 105 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 106 } 107 108 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 109 var passes = result.contextData.GetNativePasses(); 110 111 Assert.AreEqual(1, passes.Count); 112 Assert.AreEqual(4, passes[0].attachments.size); 113 Assert.AreEqual(3, passes[0].numGraphPasses); 114 115 ref var firstAttachment = ref passes[0].attachments[0]; 116 Assert.AreEqual(RenderBufferLoadAction.Load, firstAttachment.loadAction); 117 118 ref var secondAttachment = ref passes[0].attachments[1]; 119 Assert.AreEqual(RenderBufferLoadAction.Clear, secondAttachment.loadAction); 120 121 ref var thirdAttachment = ref passes[0].attachments[2]; 122 Assert.AreEqual(RenderBufferLoadAction.Clear, thirdAttachment.loadAction); 123 124 ref var fourthAttachment = ref passes[0].attachments[3]; 125 Assert.AreEqual(RenderBufferLoadAction.Load, fourthAttachment.loadAction); 126 } 127 128 /*[Test] 129 public void MergeNonRenderPasses() 130 { 131 RenderGraph g = new RenderGraph(); 132 133 var buffers = ImportAndCreateBuffers(g); 134 135 // Render something to 0,1 136 { 137 var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData); 138 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 139 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 140 builder.SetRenderAttachment(buffers.extraBuffers[1], 1, AccessFlags.Write); 141 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 142 builder.Dispose(); 143 } 144 145 // Render extra bits to 1 146 { 147 var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData); 148 // This does something like CommandBufffer.SetGlobal or something that doesn't do any rendering 149 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 150 builder.AllowPassCulling(false); 151 builder.Dispose(); 152 } 153 // Render to final buffer 154 { 155 var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData); 156 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 157 builder.SetRenderAttachment(buffers.extraBuffers[1], 1, AccessFlags.Write); 158 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 159 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 160 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 161 builder.Dispose(); 162 } 163 164 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 165 var passes = result.contextData.GetNativePasses(); 166 167 Assert.AreEqual(1, passes.Count); 168 Assert.AreEqual(4, passes[0].attachments.size); 169 Assert.AreEqual(3, passes[0].numGraphPasses); 170 Assert.AreEqual(2, passes[0].numNativeSubPasses); 171 }*/ 172 173 [Test] 174 public void MergeDepthPassWithNoDepthPass() 175 { 176 var g = AllocateRenderGraph(); 177 var buffers = ImportAndCreateBuffers(g); 178 179 // depth 180 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 181 { 182 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 183 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 184 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 185 } 186 187 // with no depth 188 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 189 { 190 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 191 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 192 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 193 } 194 195 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 196 var passes = result.contextData.GetNativePasses(); 197 198 Assert.AreEqual(1, passes.Count); 199 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.EndOfGraph, passes[0].breakAudit.reason); 200 } 201 202 [Test] 203 public void MergeNoDepthPassWithDepthPass() 204 { 205 var g = AllocateRenderGraph(); 206 var buffers = ImportAndCreateBuffers(g); 207 208 // no depth 209 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 210 { 211 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 212 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 213 } 214 215 // with depth 216 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 217 { 218 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 219 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 220 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 221 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 222 } 223 224 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 225 var passes = result.contextData.GetNativePasses(); 226 227 Assert.AreEqual(1, passes.Count); 228 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.EndOfGraph, passes[0].breakAudit.reason); 229 } 230 231 [Test] 232 public void MergeMultiplePassesDifferentDepth() 233 { 234 var g = AllocateRenderGraph(); 235 var buffers = ImportAndCreateBuffers(g); 236 237 // no depth 238 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 239 { 240 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 241 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 242 } 243 244 // with depth 245 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 246 { 247 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 248 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 249 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 250 } 251 252 // with no depth 253 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData)) 254 { 255 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 256 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 257 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 258 } 259 260 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 261 var passes = result.contextData.GetNativePasses(); 262 263 Assert.AreEqual(1, passes.Count); 264 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.EndOfGraph, passes[0].breakAudit.reason); 265 } 266 267 [Test] 268 public void MergeDifferentDepthFormatsBreaksPass() 269 { 270 var g = AllocateRenderGraph(); 271 var buffers = ImportAndCreateBuffers(g); 272 273 // depth 274 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 275 { 276 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 277 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 278 } 279 280 // with different depth 281 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 282 { 283 builder.SetRenderAttachmentDepth(buffers.extraDepthBuffer, AccessFlags.Write); 284 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 285 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 286 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 287 } 288 289 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 290 var passes = result.contextData.GetNativePasses(); 291 292 Assert.AreEqual(2, passes.Count); 293 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.DifferentDepthTextures, passes[0].breakAudit.reason); 294 } 295 296 [Test] 297 public void VerifyMergeStateAfterMergingPasses() 298 { 299 var g = AllocateRenderGraph(); 300 var buffers = ImportAndCreateBuffers(g); 301 302 // First pass, not culled. 303 { 304 var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData); 305 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 306 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 307 builder.AllowPassCulling(false); 308 builder.Dispose(); 309 } 310 311 // Second pass, culled. 312 { 313 var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData); 314 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 315 builder.AllowPassCulling(true); 316 builder.Dispose(); 317 } 318 319 // Third pass, not culled. 320 { 321 var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData); 322 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 323 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 324 builder.AllowPassCulling(false); 325 builder.Dispose(); 326 } 327 328 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 329 var passes = result.contextData.GetNativePasses(); 330 331 Assert.IsTrue(passes != null && passes.Count > 0); 332 var firstNativePass = passes[0]; 333 334 var firstGraphPass = result.contextData.passData.ElementAt(firstNativePass.firstGraphPass); 335 var lastGraphPass = result.contextData.passData.ElementAt(firstNativePass.lastGraphPass); 336 var middleGraphPass = result.contextData.passData.ElementAt(firstNativePass.lastGraphPass - 1); 337 338 // Only 2 passes since one have been culled 339 Assert.IsTrue(firstNativePass.numGraphPasses == 2); 340 341 // All 3 passes including the culled one. We need to add +1 to obtain the correct passes count 342 // e.g lastGraphPass index = 2, firstGraphPass index = 0, so 2 - 0 = 2 passes, but we have 3 passes to consider 343 // (index 0, 1 and 2) so we add +1 for the correct count. 344 Assert.IsTrue(firstNativePass.lastGraphPass - firstNativePass.firstGraphPass + 1 == 3); 345 346 Assert.IsTrue(firstGraphPass.mergeState == PassMergeState.Begin); 347 Assert.IsTrue(lastGraphPass.mergeState == PassMergeState.End); 348 Assert.IsTrue(middleGraphPass.mergeState == PassMergeState.None); 349 } 350 351 [Test] 352 public void NonFragmentUseBreaksPass() 353 { 354 var g = AllocateRenderGraph(); 355 var buffers = ImportAndCreateBuffers(g); 356 357 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 358 { 359 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 360 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 361 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 362 } 363 364 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 365 { 366 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 367 builder.UseTexture(buffers.extraBuffers[0], AccessFlags.Read); 368 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 369 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 370 } 371 372 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 373 var passes = result.contextData.GetNativePasses(); 374 375 Assert.AreEqual(2, passes.Count); 376 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.NextPassReadsTexture, passes[0].breakAudit.reason); 377 } 378 379 [Test] 380 public void NonRasterBreaksPass() 381 { 382 var g = AllocateRenderGraph(); 383 384 var buffers = ImportAndCreateBuffers(g); 385 386 // No depth 387 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 388 { 389 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 390 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 391 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 392 } 393 394 // Compute touches extraBuffers[0] 395 using (var builder = g.AddComputePass<RenderGraphTestPassData>("ComputePass", out var passData)) 396 { 397 builder.UseTexture(buffers.extraBuffers[0], AccessFlags.ReadWrite); 398 builder.SetRenderFunc((RenderGraphTestPassData data, ComputeGraphContext context) => { }); 399 } 400 401 // With depth 402 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 403 { 404 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 405 builder.SetRenderAttachment(buffers.extraBuffers[0], 1, AccessFlags.Read); 406 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 407 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 408 } 409 410 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 411 var passes = result.contextData.GetNativePasses(); 412 413 Assert.AreEqual(2, passes.Count); 414 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.NonRasterPass, passes[0].breakAudit.reason); 415 } 416 417 [Test] 418 public void TooManyAttachmentsBreaksPass() 419 { 420 var g = AllocateRenderGraph(); 421 var buffers = ImportAndCreateBuffers(g); 422 423 // 8 attachments 424 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 425 { 426 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 427 for (int i = 0; i < 6; i++) 428 { 429 builder.SetRenderAttachment(buffers.extraBuffers[i], i, AccessFlags.Write); 430 } 431 builder.SetRenderAttachment(buffers.backBuffer, 7, AccessFlags.Write); 432 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 433 } 434 435 // 2 additional attachments 436 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 437 { 438 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 439 for (int i = 0; i < 2; i++) 440 { 441 builder.SetRenderAttachment(buffers.extraBuffers[i + 6], i, AccessFlags.Write); 442 } 443 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 444 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 445 } 446 447 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 448 var passes = result.contextData.GetNativePasses(); 449 450 Assert.AreEqual(2, passes.Count); 451 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.AttachmentLimitReached, passes[0].breakAudit.reason); 452 } 453 454 [Test] 455 public void NativeSubPassesLimitNotExceeded() 456 { 457 var g = AllocateRenderGraph(); 458 var buffers = ImportAndCreateBuffers(g); 459 460 // Native subpasses limit is 8 so go above 461 for (int i = 0; i < Rendering.RenderGraphModule.NativeRenderPassCompiler.NativePassCompiler.k_MaxSubpass + 2; i++) 462 { 463 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>($"TestPass_{i}", out var passData)) 464 { 465 builder.SetInputAttachment(buffers.extraBuffers[1 - i % 2], 0); 466 builder.SetRenderAttachmentDepth(buffers.depthBuffer); 467 builder.SetRenderAttachment(buffers.extraBuffers[i % 2], 1); 468 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 469 } 470 } 471 472 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 473 var passes = result.contextData.GetNativePasses(); 474 475 Assert.AreEqual(2, passes.Count); 476 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.NativePassCompiler.k_MaxSubpass, passes[0].numGraphPasses); 477 Assert.AreEqual(Rendering.RenderGraphModule.NativeRenderPassCompiler.PassBreakReason.SubPassLimitReached, passes[0].breakAudit.reason); 478 } 479 480 [Test] 481 public void AllocateFreeInMergedPassesWorks() 482 { 483 var g = AllocateRenderGraph(); 484 485 var buffers = ImportAndCreateBuffers(g); 486 487 // Render something to extra 0 488 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 489 { 490 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 491 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 492 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 493 } 494 495 // Render extra bits to extra 1, this causes 1 to be allocated in pass 1 which will be the first sub pass of the merged native pass 496 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 497 { 498 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 499 builder.SetRenderAttachment(buffers.extraBuffers[1], 0, AccessFlags.Write); 500 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 501 } 502 503 // Render extra bits to extra 2, this causes 2 to be allocated in pass 2 which will be the second sub pass of the merged native pass 504 // It's also the last time extra 1 is used so it gets freed 505 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData)) 506 { 507 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 508 builder.SetRenderAttachment(buffers.extraBuffers[1], 0, AccessFlags.ReadWrite); 509 builder.SetRenderAttachment(buffers.extraBuffers[2], 1, AccessFlags.Write); 510 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 511 } 512 513 // Render to final buffer 514 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData)) 515 { 516 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 517 builder.SetRenderAttachment(buffers.extraBuffers[2], 1, AccessFlags.Write); 518 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 519 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 520 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 521 } 522 523 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 524 var passes = result.contextData.GetNativePasses(); 525 526 Assert.AreEqual(1, passes.Count); 527 Assert.AreEqual(5, passes[0].attachments.size); //3 extra + color + depth 528 Assert.AreEqual(4, passes[0].numGraphPasses); 529 530 // Pass 1 first used = {extra 1} 531 List<ResourceHandle> firstUsed = new List<ResourceHandle>(); 532 ref var pass1Data = ref result.contextData.passData.ElementAt(1); 533 foreach (ref readonly var res in pass1Data.FirstUsedResources(result.contextData)) 534 firstUsed.Add(res); 535 536 Assert.AreEqual(1, firstUsed.Count); 537 Assert.AreEqual(buffers.extraBuffers[1].handle.index, firstUsed[0].index); 538 539 // Pass 2 last used = { 540 List<ResourceHandle> lastUsed = new List<ResourceHandle>(); 541 ref var pass2Data = ref result.contextData.passData.ElementAt(2); 542 foreach (ref readonly var res in pass2Data.LastUsedResources(result.contextData)) 543 lastUsed.Add(res); 544 545 Assert.AreEqual(1, lastUsed.Count); 546 Assert.AreEqual(buffers.extraBuffers[1].handle.index, lastUsed[0].index); 547 548 } 549 550 [Test] 551 public void MemorylessWorks() 552 { 553 var g = AllocateRenderGraph(); 554 555 var buffers = ImportAndCreateBuffers(g); 556 557 // Render something to extra 0 558 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 559 { 560 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 561 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 562 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 563 } 564 565 // Render to final buffer 566 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData)) 567 { 568 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 569 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.ReadWrite); 570 builder.SetRenderAttachment(buffers.backBuffer, 1, AccessFlags.Write); 571 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 572 } 573 574 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 575 var passes = result.contextData.GetNativePasses(); 576 577 Assert.AreEqual(1, passes.Count); 578 Assert.AreEqual(3, passes[0].attachments.size); //1 extra + color + depth 579 Assert.AreEqual(2, passes[0].numGraphPasses); 580 581 // Pass 0 : first used = {depthBuffer, extraBuffers[0]} 582 List<ResourceHandle> firstUsed = new List<ResourceHandle>(); 583 ref var pass0Data = ref result.contextData.passData.ElementAt(0); 584 foreach (ref readonly var res in pass0Data.FirstUsedResources(result.contextData)) 585 firstUsed.Add(res); 586 587 //Extra buffer 0 should be memoryless 588 Assert.AreEqual(2, firstUsed.Count); 589 Assert.AreEqual(buffers.extraBuffers[0].handle.index, firstUsed[1].index); 590 ref var info = ref result.contextData.UnversionedResourceData(firstUsed[1]); 591 Assert.AreEqual(true, info.memoryLess); 592 593 // Pass 1 : last used = {depthBuffer, extraBuffers[0], backBuffer} 594 List<ResourceHandle> lastUsed = new List<ResourceHandle>(); 595 ref var pass1Data = ref result.contextData.passData.ElementAt(1); 596 foreach (var res in pass1Data.LastUsedResources(result.contextData)) 597 lastUsed.Add(res); 598 599 Assert.AreEqual(3, lastUsed.Count); 600 Assert.AreEqual(buffers.extraBuffers[0].handle.index, lastUsed[1].index); 601 } 602 603 [Test] 604 public void InputAttachmentsWork() 605 { 606 var g = AllocateRenderGraph(); 607 608 var buffers = ImportAndCreateBuffers(g); 609 610 // Render something to extra 0,1,2 611 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 612 { 613 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.Write); 614 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 615 builder.SetRenderAttachment(buffers.extraBuffers[1], 1, AccessFlags.Write); 616 builder.SetRenderAttachment(buffers.extraBuffers[2], 2, AccessFlags.Write); 617 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 618 } 619 620 // Render to final buffer using extra 0 as attachment 621 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData)) 622 { 623 builder.SetRenderAttachmentDepth(buffers.depthBuffer, AccessFlags.ReadWrite); 624 builder.SetRenderAttachment(buffers.backBuffer, 1, AccessFlags.Write); 625 builder.SetInputAttachment(buffers.extraBuffers[0], 0, AccessFlags.Read); 626 builder.SetInputAttachment(buffers.extraBuffers[1], 1, AccessFlags.Read); 627 builder.SetInputAttachment(buffers.extraBuffers[2], 2, AccessFlags.Read); 628 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 629 } 630 631 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 632 var nativePasses = result.contextData.GetNativePasses(); 633 634 Assert.AreEqual(1, nativePasses.Count); 635 Assert.AreEqual(5, nativePasses[0].attachments.size); //3 extra + color + depth 636 Assert.AreEqual(2, nativePasses[0].numGraphPasses); 637 638 // Validate attachments 639 Assert.AreEqual(buffers.depthBuffer.handle.index, nativePasses[0].attachments[0].handle.index); 640 Assert.AreEqual(buffers.extraBuffers[0].handle.index, nativePasses[0].attachments[1].handle.index); 641 Assert.AreEqual(buffers.extraBuffers[1].handle.index, nativePasses[0].attachments[2].handle.index); 642 Assert.AreEqual(buffers.extraBuffers[2].handle.index, nativePasses[0].attachments[3].handle.index); 643 Assert.AreEqual(buffers.backBuffer.handle.index, nativePasses[0].attachments[4].handle.index); 644 645 // Sub Pass 0 646 ref var subPass = ref result.contextData.nativeSubPassData.ElementAt(nativePasses[0].firstNativeSubPass); 647 Assert.AreEqual(0, subPass.inputs.Length); 648 649 Assert.AreEqual(3, subPass.colorOutputs.Length); 650 Assert.AreEqual(1, subPass.colorOutputs[0]); 651 Assert.AreEqual(2, subPass.colorOutputs[1]); 652 Assert.AreEqual(3, subPass.colorOutputs[2]); 653 654 // Sub Pass 1 655 ref var subPass2 = ref result.contextData.nativeSubPassData.ElementAt(nativePasses[0].firstNativeSubPass + 1); 656 Assert.AreEqual(3, subPass2.inputs.Length); 657 Assert.AreEqual(1, subPass2.inputs[0]); 658 Assert.AreEqual(2, subPass2.inputs[1]); 659 Assert.AreEqual(3, subPass2.inputs[2]); 660 661 Assert.AreEqual(1, subPass2.colorOutputs.Length); 662 Assert.AreEqual(4, subPass2.colorOutputs[0]); 663 } 664 665 [Test] 666 public void ImportParametersWork() 667 { 668 var g = AllocateRenderGraph(); 669 var buffers = ImportAndCreateBuffers(g); 670 671 // Import with parameters 672 var backBuffer = BuiltinRenderTextureType.CameraTarget; 673 var backBufferHandle = RTHandles.Alloc(backBuffer, "Test Import"); 674 675 RenderTargetInfo importInfo = new RenderTargetInfo(); 676 importInfo.width = 1024; 677 importInfo.height = 768; 678 importInfo.msaaSamples = 1; 679 importInfo.volumeDepth = 1; 680 importInfo.format = GraphicsFormat.R16G16B16A16_SFloat; 681 682 ImportResourceParams importResourceParams = new ImportResourceParams(); 683 importResourceParams.clearOnFirstUse = true; 684 importResourceParams.discardOnLastUse = true; 685 var importedTexture = g.ImportTexture(backBufferHandle, importInfo, importResourceParams); 686 687 // Render something to importedTexture 688 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 689 { 690 builder.SetRenderAttachment(importedTexture, 0, AccessFlags.Write); 691 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 692 } 693 694 // Compute does something or other 695 using (var builder = g.AddComputePass<RenderGraphTestPassData>("ComputePass", out var passData)) 696 { 697 builder.UseTexture(buffers.extraBuffers[0], AccessFlags.ReadWrite); 698 builder.SetRenderFunc((RenderGraphTestPassData data, ComputeGraphContext context) => { }); 699 } 700 701 // Render to final buffer 702 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData)) 703 { 704 builder.SetRenderAttachment(buffers.extraBuffers[0], 0, AccessFlags.Write); 705 builder.SetRenderAttachment(importedTexture, 1, AccessFlags.Write); 706 builder.SetRenderAttachment(buffers.backBuffer, 2, AccessFlags.Write); 707 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 708 } 709 710 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 711 var passes = result.contextData.GetNativePasses(); 712 713 // Validate nr pass 0 714 Assert.AreEqual(2, passes.Count); 715 Assert.AreEqual(1, passes[0].attachments.size); 716 Assert.AreEqual(1, passes[0].numGraphPasses); 717 718 // Clear on first use 719 ref var firstAttachment = ref passes[0].attachments[0]; 720 Assert.AreEqual(RenderBufferLoadAction.Clear, firstAttachment.loadAction); 721 722 // Validate nr pass 1 723 Assert.AreEqual(3, passes[1].attachments.size); 724 Assert.AreEqual(1, passes[1].numGraphPasses); 725 726 // Discard on last use 727 Assert.AreEqual(RenderBufferStoreAction.DontCare, passes[1].attachments[1].storeAction); 728 // Regular imports do a full load/store 729 Assert.AreEqual(RenderBufferLoadAction.Load, passes[1].attachments[2].loadAction); 730 Assert.AreEqual(RenderBufferStoreAction.Store, passes[1].attachments[2].storeAction); 731 } 732 733 [Test] 734 public void FencesWork() 735 { 736 var g = AllocateRenderGraph(); 737 var buffers = ImportAndCreateBuffers(g); 738 739 // Pass #1: Render pass writing to backbuffer 740 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("#1 RenderPass", out _)) 741 { 742 builder.UseTexture(buffers.backBuffer, AccessFlags.Write); 743 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 744 } 745 746 // Pass #2: Async compute pass writing to back buffer 747 using (var builder = g.AddComputePass<RenderGraphTestPassData>("#2 AsyncComputePass", out _)) 748 { 749 builder.EnableAsyncCompute(true); 750 builder.UseTexture(buffers.backBuffer, AccessFlags.Write); 751 builder.SetRenderFunc((RenderGraphTestPassData data, ComputeGraphContext context) => { }); 752 } 753 754 // Pass #3: Render pass writing to backbuffer 755 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("#3 RenderPass", out _)) 756 { 757 builder.UseTexture(buffers.backBuffer, AccessFlags.Write); 758 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 759 } 760 761 // Pass #4: Render pass writing to backbuffer 762 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("#4 RenderPass", out _)) 763 { 764 builder.UseTexture(buffers.backBuffer, AccessFlags.Write); 765 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 766 } 767 768 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 769 var passData = result.contextData.passData; 770 771 // #1 waits for nothing, inserts a fence 772 Assert.AreEqual(-1, passData[0].waitOnGraphicsFencePassId); 773 Assert.True(passData[0].insertGraphicsFence); 774 775 // #2 (async compute) pass waits on #1, inserts a fence 776 Assert.AreEqual(0, passData[1].waitOnGraphicsFencePassId); 777 Assert.True(passData[1].insertGraphicsFence); 778 779 // #3 waits on #2 (async compute) pass, doesn't insert a fence 780 Assert.AreEqual(1, passData[2].waitOnGraphicsFencePassId); 781 Assert.False(passData[2].insertGraphicsFence); 782 783 // #4 waits for nothing, doesn't insert a fence 784 Assert.AreEqual(-1, passData[3].waitOnGraphicsFencePassId); 785 Assert.False(passData[3].insertGraphicsFence); 786 } 787 788 [Test] 789 public void BuffersWork() 790 { 791 var g = AllocateRenderGraph(); 792 var rendertargets = ImportAndCreateBuffers(g); 793 794 var desc = new BufferDesc(1024, 16); 795 var buffer = g.CreateBuffer(desc); 796 797 // Render something to extra 0 and write uav 798 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 799 { 800 builder.SetRenderAttachmentDepth(rendertargets.depthBuffer, AccessFlags.Write); 801 builder.SetRenderAttachment(rendertargets.extraBuffers[0], 0, AccessFlags.Write); 802 builder.UseBufferRandomAccess(buffer, 1, AccessFlags.ReadWrite); 803 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 804 } 805 806 // Render extra bits to 0 reading from the uav 807 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 808 { 809 builder.SetRenderAttachmentDepth(rendertargets.depthBuffer, AccessFlags.Write); 810 builder.SetRenderAttachment(rendertargets.extraBuffers[0], 0, AccessFlags.Write); 811 builder.UseBuffer(buffer, AccessFlags.Read); 812 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 813 } 814 815 // Render to final buffer 816 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass2", out var passData)) 817 { 818 builder.UseTexture(rendertargets.extraBuffers[0]); 819 builder.SetRenderAttachment(rendertargets.backBuffer, 2, AccessFlags.Write); 820 builder.SetRenderAttachmentDepth(rendertargets.depthBuffer, AccessFlags.Write); 821 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 822 } 823 824 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 825 var passes = result.contextData.GetNativePasses(); 826 827 // Validate Pass 0 : uav is first used and created 828 ref var pass0Data = ref result.contextData.passData.ElementAt(0); 829 var firstUsedList = pass0Data.FirstUsedResources(result.contextData).ToArray(); 830 831 Assert.AreEqual(3, firstUsedList.Length); 832 Assert.AreEqual(rendertargets.depthBuffer.handle.index, firstUsedList[0].index); 833 Assert.AreEqual(RenderGraphResourceType.Texture, firstUsedList[0].type); 834 Assert.AreEqual(rendertargets.extraBuffers[0].handle.index, firstUsedList[1].index); 835 Assert.AreEqual(RenderGraphResourceType.Texture, firstUsedList[1].type); 836 Assert.AreEqual(buffer.handle.index, firstUsedList[2].index); 837 Assert.AreEqual(RenderGraphResourceType.Buffer, firstUsedList[2].type); 838 839 var randomAccessList = pass0Data.RandomWriteTextures(result.contextData).ToArray(); 840 Assert.AreEqual(1, randomAccessList.Length); 841 Assert.AreEqual(buffer.handle.index, randomAccessList[0].resource.index); 842 Assert.AreEqual(RenderGraphResourceType.Buffer, randomAccessList[0].resource.type); 843 Assert.AreEqual(1, randomAccessList[0].index); // we asked for it to be at index 1 in the builder 844 Assert.AreEqual(true, randomAccessList[0].preserveCounterValue); // preserve is default 845 846 // Validate Pass 1 : uav buffer is last used and destroyed 847 ref var pass1Data = ref result.contextData.passData.ElementAt(1); 848 var lastUsedList = pass1Data.LastUsedResources(result.contextData).ToArray(); 849 850 Assert.AreEqual(1, lastUsedList.Length); 851 Assert.AreEqual(buffer.handle.index, lastUsedList[0].index); 852 Assert.AreEqual(RenderGraphResourceType.Buffer, lastUsedList[0].type); 853 } 854 855 [Test] 856 public void ResolveMSAAImportColor() 857 { 858 var g = AllocateRenderGraph(); 859 var buffers = ImportAndCreateBuffers(g); 860 861 // Import with parameters 862 // Depth 863 var depthBuffer = BuiltinRenderTextureType.Depth; 864 var depthBufferHandle = RTHandles.Alloc(depthBuffer, "Test Import Depth"); 865 866 RenderTargetInfo importInfoDepth = new RenderTargetInfo(); 867 importInfoDepth.width = 1024; 868 importInfoDepth.height = 768; 869 importInfoDepth.msaaSamples = 4; 870 importInfoDepth.volumeDepth = 1; 871 importInfoDepth.format = GraphicsFormat.D32_SFloat_S8_UInt; 872 873 ImportResourceParams importResourceParams = new ImportResourceParams(); 874 importResourceParams.clearOnFirstUse = true; 875 importResourceParams.discardOnLastUse = true; 876 877 var importedDepth = g.ImportTexture(depthBufferHandle, importInfoDepth, importResourceParams); 878 879 // Color 880 var backBuffer = BuiltinRenderTextureType.CameraTarget; 881 var backBufferHandle = RTHandles.Alloc(backBuffer, "Test Import Color"); 882 883 RenderTargetInfo importInfoColor = new RenderTargetInfo(); 884 importInfoColor.width = 1024; 885 importInfoColor.height = 768; 886 importInfoColor.msaaSamples = 4; 887 importInfoColor.volumeDepth = 1; 888 importInfoColor.format = GraphicsFormat.R16G16B16A16_SFloat; 889 890 var importedColor = g.ImportTexture(backBufferHandle, importInfoColor, importResourceParams); 891 892 // Render something to importedColor and importedDepth 893 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass", out var passData)) 894 { 895 builder.SetRenderAttachmentDepth(importedDepth, AccessFlags.Write); 896 builder.SetRenderAttachment(importedColor, 1, AccessFlags.Write); 897 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 898 } 899 900 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 901 var passes = result.contextData.GetNativePasses(); 902 903 // Validate nr pass 904 Assert.AreEqual(1, passes.Count); 905 Assert.AreEqual(2, passes[0].attachments.size); 906 Assert.AreEqual(1, passes[0].numGraphPasses); 907 908 // Clear on first use 909 ref var firstAttachment = ref passes[0].attachments[0]; 910 Assert.AreEqual(RenderBufferLoadAction.Clear, firstAttachment.loadAction); 911 ref var secondAttachment = ref passes[0].attachments[1]; 912 Assert.AreEqual(RenderBufferLoadAction.Clear, secondAttachment.loadAction); 913 914 // Discard on last use 915 Assert.AreEqual(RenderBufferStoreAction.DontCare, passes[0].attachments[0].storeAction); 916 // When discarding MSAA color, we only discard the MSAA buffers but keep the resolved texture 917 Assert.AreEqual(RenderBufferStoreAction.Resolve, passes[0].attachments[1].storeAction); 918 } 919 920 [Test] 921 public void TransientTexturesCantBeReused() 922 { 923 var g = AllocateRenderGraph(); 924 var buffers = ImportAndCreateBuffers(g); 925 var textureTransientHandle = TextureHandle.nullHandle; 926 927 // Render something to textureTransientHandle, created locally in the pass. 928 // No exception and no error(s) should be thrown in the Console. 929 { 930 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 931 { 932 var textDesc = new TextureDesc(Vector2.one, false, false) 933 { 934 width = 1920, 935 height = 1080, 936 format = GraphicsFormat.B10G11R11_UFloatPack32, 937 clearBuffer = true, 938 clearColor = Color.red, 939 name = "Transient Texture" 940 }; 941 textureTransientHandle = builder.CreateTransientTexture(textDesc); 942 943 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 944 } 945 946 Assert.IsTrue(g.m_RenderPasses.Count != 0); 947 Assert.IsTrue(g.m_RenderPasses[^1].transientResourceList[(int)textureTransientHandle.handle.type].Count != 0); 948 } 949 950 // Try to render something to textureTransientHandle, reusing the previous TextureHandle. 951 // UseTexture should throw an exception. 952 Assert.Throws<ArgumentException>(() => 953 { 954 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 955 { 956 builder.UseTexture(textureTransientHandle, AccessFlags.Read | AccessFlags.Write); 957 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 958 } 959 }); 960 } 961 962 [Test] 963 public void TransientBuffersCantBeReused() 964 { 965 var g = AllocateRenderGraph(); 966 var buffers = ImportAndCreateBuffers(g); 967 var bufferTransientHandle = BufferHandle.nullHandle; 968 969 // Render something to textureTransientHandle, created locally in the pass. 970 // No error(s) should be thrown in the Console. 971 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 972 { 973 var prefixBuffer0Desc = new BufferDesc(1920 * 1080, 4, GraphicsBuffer.Target.Raw) { name = "prefixBuffer0" }; 974 bufferTransientHandle = builder.CreateTransientBuffer(prefixBuffer0Desc); 975 976 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 977 978 Assert.IsTrue(g.m_RenderPasses.Count != 0); 979 Assert.IsTrue(g.m_RenderPasses[^1].transientResourceList[(int)bufferTransientHandle.handle.type].Count != 0); 980 } 981 982 // Try to render something to textureTransientHandle, reusing the previous TextureHandle. 983 // UseTexture should throw an exception. 984 Assert.Throws<ArgumentException>(() => 985 { 986 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 987 { 988 builder.UseBuffer(bufferTransientHandle, AccessFlags.Read | AccessFlags.Write); 989 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 990 } 991 }); 992 } 993 994 [Test] 995 public void ChangingGlobalStateDisablesCulling() 996 { 997 var g = AllocateRenderGraph(); 998 var buffers = ImportAndCreateBuffers(g); 999 1000 // First pass ; culling should be set to false after calling AllowGlobalStateModification. 1001 { 1002 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass0", out var passData)) 1003 { 1004 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 1005 builder.AllowPassCulling(true); 1006 builder.AllowGlobalStateModification(true); 1007 } 1008 } 1009 1010 // Second pass ; culling should be set to false even if we are setting it to true after calling AllowGlobalStateModification. 1011 { 1012 using (var builder = g.AddRasterRenderPass<RenderGraphTestPassData>("TestPass1", out var passData)) 1013 { 1014 builder.SetRenderFunc((RenderGraphTestPassData data, RasterGraphContext context) => { }); 1015 builder.AllowGlobalStateModification(true); 1016 builder.AllowPassCulling(true); 1017 } 1018 } 1019 1020 var result = g.CompileNativeRenderGraph(g.ComputeGraphHash()); 1021 var passes = result.contextData.GetNativePasses(); 1022 1023 Assert.IsTrue(passes != null && passes.Count > 0); 1024 var firstNativePass = passes[0]; 1025 1026 Assert.IsTrue(firstNativePass.numGraphPasses == 2); 1027 } 1028 } 1029}