暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FrameBufferFetchRenderFeature.cs 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using UnityEngine;
  2. using UnityEngine.Rendering;
  3. using UnityEngine.Rendering.RenderGraphModule;
  4. using UnityEngine.Rendering.Universal;
  5. using UnityEngine.Serialization;
  6. // This example copies the target of the previous pass to a new texture using a custom material and framebuffer fetch. This example is for API demonstrative purposes,
  7. // so the new texture is not used anywhere else in the frame, you can use the frame debugger to verify its contents.
  8. // Framebuffer fetch: this is an advanced TBDR GPU optimization that allows subpasses to read the output of previous subpasses directly from the framebuffer,
  9. // greatly reducing the bandwidth usage.
  10. public class FrameBufferFetchRenderFeature : ScriptableRendererFeature
  11. {
  12. class FrameBufferFetchPass : ScriptableRenderPass
  13. {
  14. private Material m_BlitMaterial;
  15. private Material m_FBFetchMaterial;
  16. public FrameBufferFetchPass(Material blitMaterial, Material fbFetchMaterial)
  17. {
  18. m_BlitMaterial = blitMaterial;
  19. m_FBFetchMaterial = fbFetchMaterial;
  20. }
  21. // This class stores the data needed by the pass, passed as parameter to the delegate function that executes the pass
  22. private class PassData
  23. {
  24. internal TextureHandle src;
  25. internal Material material;
  26. }
  27. // This static method is used to execute the pass and passed as the RenderFunc delegate to the RenderGraph render pass
  28. static void ExecuteBlitPass(PassData data, RasterGraphContext context)
  29. {
  30. Blitter.BlitTexture(context.cmd, data.src, new Vector4(1, 1, 0, 0), data.material, 0);
  31. }
  32. // This static method is used to execute the pass and passed as the RenderFunc delegate to the RenderGraph render pass
  33. static void ExecuteFBFetchPass(PassData data, RasterGraphContext context)
  34. {
  35. context.cmd.DrawProcedural(Matrix4x4.identity, data.material, 1, MeshTopology.Triangles, 3, 1, null);
  36. // other ways to draw a fullscreen triangle/quad:
  37. //CoreUtils.DrawFullScreen(context.cmd, data.material, null, 1);
  38. //Blitter.BlitTexture(context.cmd, new Vector4(1, 1, 0, 0), data.material, 1);
  39. }
  40. private void BlitPass(RenderGraph renderGraph, ContextContainer frameData, TextureHandle destination)
  41. {
  42. string passName = "InitialBlitPass";
  43. // This simple pass copies the active color texture to a new texture using a custom material. This sample is for API demonstrative purposes,
  44. // so the new texture is not used anywhere else in the frame, you can use the frame debugger to verify its contents.
  45. // add a raster render pass to the render graph, specifying the name and the data type that will be passed to the ExecutePass function
  46. using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName, out var passData))
  47. {
  48. // UniversalResourceData contains all the texture handles used by the renderer, including the active color and depth textures
  49. // The active color and depth textures are the main color and depth buffers that the camera renders into
  50. UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
  51. // Get the active color texture through the frame data, and set it as the source texture for the blit
  52. passData.src = resourceData.activeColorTexture;
  53. passData.material = m_BlitMaterial;
  54. // We declare the src texture as an input dependency to this pass, via UseTexture()
  55. builder.UseTexture(passData.src);
  56. // Setup as a render target via UseTextureFragment, which is the equivalent of using the old cmd.SetRenderTarget
  57. builder.SetRenderAttachment(destination, 0);
  58. // We disable culling for this pass for the demonstrative purpose of this sample, as normally this pass would be culled,
  59. // since the destination texture is not used anywhere else
  60. builder.AllowPassCulling(false);
  61. // Assign the ExecutePass function to the render pass delegate, which will be called by the render graph when executing the pass
  62. builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecuteBlitPass(data, context));
  63. }
  64. }
  65. private void FBFetchPass(RenderGraph renderGraph, ContextContainer frameData, TextureHandle source, TextureHandle destination)
  66. {
  67. string passName = "FrameBufferFetchPass";
  68. // This simple pass copies the target of the previous pass to a new texture using a custom material and framebuffer fetch. This sample is for API demonstrative purposes,
  69. // so the new texture is not used anywhere else in the frame, you can use the frame debugger to verify its contents.
  70. // add a raster render pass to the render graph, specifying the name and the data type that will be passed to the ExecutePass function
  71. using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName, out var passData))
  72. {
  73. // Fill the pass data
  74. passData.material = m_FBFetchMaterial;
  75. // We declare the src texture as an input dependency to this pass, via UseTexture()
  76. //builder.UseTexture(passData.blitDest);
  77. builder.SetInputAttachment(source, 0, AccessFlags.Read);
  78. // Setup as a render target via UseTextureFragment, which is the equivalent of using the old cmd.SetRenderTarget
  79. builder.SetRenderAttachment(destination, 0);
  80. // We disable culling for this pass for the demonstrative purpose of this sample, as normally this pass would be culled,
  81. // since the destination texture is not used anywhere else
  82. builder.AllowPassCulling(false);
  83. // Assign the ExecutePass function to the render pass delegate, which will be called by the render graph when executing the pass
  84. builder.SetRenderFunc((PassData data, RasterGraphContext context) => ExecuteFBFetchPass(data, context));
  85. }
  86. }
  87. // This is where the renderGraph handle can be accessed.
  88. // Each ScriptableRenderPass can use the RenderGraph handle to add multiple render passes to the render graph
  89. public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
  90. {
  91. // This pass showcases how to implement framebuffer fetch: this is an advanced TBDR GPU optimization
  92. // that allows subpasses to read the output of previous subpasses directly from the framebuffer, reducing greatly the bandwidth usage.
  93. // The first pass BlitPass simply copies the Camera Color in a temporary render target, the second pass FBFetchPass copies the temporary render target
  94. // to another render target using framebuffer fetch.
  95. // As a result, the passes are merged (you can verify in the RenderGraph Visualizer) and the bandwidth usage is reduced, since we can discard the temporary render target.
  96. // The destination textures are created here,
  97. // the texture is created with the same dimensions as the active color texture, but with no depth buffer, being a copy of the color texture
  98. // we also disable MSAA as we don't need multisampled textures for this sample.
  99. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  100. RenderTextureDescriptor desc = cameraData.cameraTargetDescriptor;
  101. desc.msaaSamples = 1;
  102. desc.depthBufferBits = 0;
  103. TextureHandle blitDestination = UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc, "BlitDestTexture", false);
  104. TextureHandle fbFetchDestination = UniversalRenderer.CreateRenderGraphTexture(renderGraph, desc, "FBFetchDestTextureTexture", false);
  105. BlitPass(renderGraph, frameData, blitDestination);
  106. FBFetchPass(renderGraph, frameData, blitDestination, fbFetchDestination);
  107. }
  108. }
  109. FrameBufferFetchPass m_FbFetchPass;
  110. public Material m_BlitColorMaterial;
  111. public Material m_FBFetchMaterial;
  112. /// <inheritdoc/>
  113. public override void Create()
  114. {
  115. m_FbFetchPass = new FrameBufferFetchPass(m_BlitColorMaterial, m_FBFetchMaterial);
  116. // Configures where the render pass should be injected.
  117. m_FbFetchPass.renderPassEvent = RenderPassEvent.BeforeRenderingTransparents;
  118. }
  119. // Here you can inject one or multiple render passes in the renderer.
  120. // This method is called when setting up the renderer once per-camera.
  121. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
  122. {
  123. renderer.EnqueuePass(m_FbFetchPass);
  124. }
  125. }