No Description
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.

DrawScreenSpaceUIPass.cs 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. using System;
  2. using UnityEngine.Experimental.Rendering;
  3. using UnityEngine.Rendering.RenderGraphModule;
  4. using UnityEngine.Rendering.Universal.Internal;
  5. namespace UnityEngine.Rendering.Universal
  6. {
  7. /// <summary>
  8. /// Draw screen space overlay UI into the given color and depth target
  9. /// </summary>
  10. internal class DrawScreenSpaceUIPass : ScriptableRenderPass
  11. {
  12. PassData m_PassData;
  13. RTHandle m_ColorTarget;
  14. RTHandle m_DepthTarget;
  15. // Whether to render on an offscreen render texture or on the current active render target
  16. bool m_RenderOffscreen;
  17. static readonly int s_CameraDepthTextureID = Shader.PropertyToID("_CameraDepthTexture");
  18. static readonly int s_CameraOpaqueTextureID = Shader.PropertyToID("_CameraOpaqueTexture");
  19. /// <summary>
  20. /// Creates a new <c>DrawScreenSpaceUIPass</c> instance.
  21. /// </summary>
  22. /// <param name="evt">The <c>RenderPassEvent</c> to use.</param>
  23. /// <seealso cref="RenderPassEvent"/>
  24. public DrawScreenSpaceUIPass(RenderPassEvent evt, bool renderOffscreen)
  25. {
  26. base.profilingSampler = new ProfilingSampler(nameof(DrawScreenSpaceUIPass));
  27. renderPassEvent = evt;
  28. useNativeRenderPass = false;
  29. m_RenderOffscreen = renderOffscreen;
  30. m_PassData = new PassData();
  31. }
  32. /// <summary>
  33. /// Get a descriptor for the required color texture for this pass.
  34. /// </summary>
  35. /// <param name="descriptor">Camera target descriptor.</param>
  36. /// <param name="cameraWidth">Unscaled pixel width of the camera.</param>
  37. /// <param name="cameraHeight">Unscaled pixel height of the camera.</param>
  38. /// <seealso cref="RenderTextureDescriptor"/>
  39. public static void ConfigureColorDescriptor(ref RenderTextureDescriptor descriptor, int cameraWidth, int cameraHeight)
  40. {
  41. descriptor.graphicsFormat = GraphicsFormat.R8G8B8A8_SRGB;
  42. descriptor.depthStencilFormat = GraphicsFormat.None;
  43. descriptor.width = cameraWidth;
  44. descriptor.height = cameraHeight;
  45. }
  46. /// <summary>
  47. /// Get a descriptor for the required depth texture for this pass.
  48. /// </summary>
  49. /// <param name="descriptor">Camera target descriptor.</param>
  50. /// <param name="depthStencilFormat">Depth stencil format required.</param>
  51. /// <param name="cameraWidth">Unscaled pixel width of the camera.</param>
  52. /// <param name="cameraHeight">Unscaled pixel height of the camera.</param>
  53. /// <seealso cref="RenderTextureDescriptor"/>
  54. public static void ConfigureDepthDescriptor(ref RenderTextureDescriptor descriptor, GraphicsFormat depthStencilFormat, int cameraWidth, int cameraHeight)
  55. {
  56. descriptor.graphicsFormat = GraphicsFormat.None;
  57. descriptor.depthStencilFormat = depthStencilFormat;
  58. descriptor.width = cameraWidth;
  59. descriptor.height = cameraHeight;
  60. }
  61. private static void ExecutePass(RasterCommandBuffer commandBuffer, PassData passData, RendererList rendererList)
  62. {
  63. commandBuffer.DrawRendererList(rendererList);
  64. }
  65. // Specific to RG cases which have to go through Unsafe commands
  66. private static void ExecutePass(UnsafeCommandBuffer commandBuffer, UnsafePassData passData, RendererList rendererList)
  67. {
  68. commandBuffer.DrawRendererList(rendererList);
  69. }
  70. // Non-RenderGraph path
  71. public void Dispose()
  72. {
  73. m_ColorTarget?.Release();
  74. m_DepthTarget?.Release();
  75. }
  76. /// <summary>
  77. /// Configure the pass with the off-screen destination color texture and depth texture to execute the pass on.
  78. /// </summary>
  79. /// <param name="cameraData">Camera rendering data containing all relevant render target information.</param>
  80. /// <param name="depthStencilFormat">Depth stencil format required for depth/stencil effects.</param>
  81. public void Setup(UniversalCameraData cameraData, GraphicsFormat depthStencilFormat)
  82. {
  83. if (m_RenderOffscreen)
  84. {
  85. RenderTextureDescriptor colorDescriptor = cameraData.cameraTargetDescriptor;
  86. ConfigureColorDescriptor(ref colorDescriptor, cameraData.pixelWidth, cameraData.pixelHeight);
  87. RenderingUtils.ReAllocateHandleIfNeeded(ref m_ColorTarget, colorDescriptor, name: "_OverlayUITexture");
  88. RenderTextureDescriptor depthDescriptor = cameraData.cameraTargetDescriptor;
  89. ConfigureDepthDescriptor(ref depthDescriptor, depthStencilFormat, cameraData.pixelWidth, cameraData.pixelHeight);
  90. RenderingUtils.ReAllocateHandleIfNeeded(ref m_DepthTarget, depthDescriptor, name: "_OverlayUITexture_Depth");
  91. }
  92. }
  93. /// <inheritdoc/>
  94. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  95. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  96. {
  97. if(m_RenderOffscreen)
  98. {
  99. // Disable obsolete warning for internal usage
  100. #pragma warning disable CS0618
  101. ConfigureTarget(m_ColorTarget, m_DepthTarget);
  102. ConfigureClear(ClearFlag.Color, Color.clear);
  103. #pragma warning restore CS0618
  104. cmd?.SetGlobalTexture(ShaderPropertyId.overlayUITexture, m_ColorTarget);
  105. }
  106. else
  107. {
  108. UniversalCameraData cameraData = renderingData.frameData.Get<UniversalCameraData>();
  109. DebugHandler debugHandler = GetActiveDebugHandler(cameraData);
  110. bool resolveToDebugScreen = debugHandler != null && debugHandler.WriteToDebugScreenTexture(cameraData.resolveFinalTarget);
  111. if (resolveToDebugScreen)
  112. {
  113. // Disable obsolete warning for internal usage
  114. #pragma warning disable CS0618
  115. ConfigureTarget(debugHandler.DebugScreenColorHandle, debugHandler.DebugScreenDepthHandle);
  116. #pragma warning restore CS0618
  117. }
  118. else
  119. {
  120. // Get RTHandle alias to use RTHandle apis
  121. var cameraTarget = RenderingUtils.GetCameraTargetIdentifier(ref renderingData);
  122. RTHandleStaticHelpers.SetRTHandleStaticWrapper(cameraTarget);
  123. var colorTargetHandle = RTHandleStaticHelpers.s_RTHandleWrapper;
  124. // Disable obsolete warning for internal usage
  125. #pragma warning disable CS0618
  126. ConfigureTarget(colorTargetHandle);
  127. #pragma warning restore CS0618
  128. }
  129. }
  130. }
  131. /// <inheritdoc/>
  132. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  133. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  134. {
  135. using (new ProfilingScope(renderingData.commandBuffer, ProfilingSampler.Get(URPProfileId.DrawScreenSpaceUI)))
  136. {
  137. RendererList rendererList = context.CreateUIOverlayRendererList(renderingData.cameraData.camera);
  138. ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(renderingData.commandBuffer), m_PassData, rendererList);
  139. }
  140. }
  141. //RenderGraph path
  142. private class PassData
  143. {
  144. internal RendererListHandle rendererList;
  145. }
  146. // Specific to RG cases which have to go through Unsafe commands
  147. private class UnsafePassData
  148. {
  149. internal RendererListHandle rendererList;
  150. internal TextureHandle colorTarget;
  151. }
  152. internal void RenderOffscreen(RenderGraph renderGraph, ContextContainer frameData, GraphicsFormat depthStencilFormat, out TextureHandle output)
  153. {
  154. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  155. RenderTextureDescriptor colorDescriptor = cameraData.cameraTargetDescriptor;
  156. ConfigureColorDescriptor(ref colorDescriptor, cameraData.pixelWidth, cameraData.pixelHeight);
  157. output = UniversalRenderer.CreateRenderGraphTexture(renderGraph, colorDescriptor, "_OverlayUITexture", true);
  158. RenderTextureDescriptor depthDescriptor = cameraData.cameraTargetDescriptor;
  159. ConfigureDepthDescriptor(ref depthDescriptor, depthStencilFormat, cameraData.pixelWidth, cameraData.pixelHeight);
  160. TextureHandle depthBuffer = UniversalRenderer.CreateRenderGraphTexture(renderGraph, depthDescriptor, "_OverlayUITexture_Depth", false);
  161. // Render uGUI and UIToolkit overlays
  162. using (var builder = renderGraph.AddRasterRenderPass<PassData>("Screen Space UIToolkit/uGUI Pass - Offscreen", out var passData, base.profilingSampler))
  163. {
  164. builder.SetRenderAttachment(output, 0);
  165. passData.rendererList = renderGraph.CreateUIOverlayRendererList(cameraData.camera, UISubset.UIToolkit_UGUI);
  166. builder.UseRendererList(passData.rendererList);
  167. builder.SetRenderAttachmentDepth(depthBuffer, AccessFlags.ReadWrite);
  168. if (output.IsValid())
  169. builder.SetGlobalTextureAfterPass(output, ShaderPropertyId.overlayUITexture);
  170. builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
  171. {
  172. ExecutePass(context.cmd, data, data.rendererList);
  173. });
  174. }
  175. // Render IMGUI overlay and software cursor in a UnsafePass
  176. // Doing so allow us to safely cover cases when graphics commands called through onGUI() in user scripts are not supported by RenderPass API
  177. // Besides, Vulkan backend doesn't support SetSRGWrite() in RenderPass API and we have some of them at IMGUI levels
  178. // Note, these specific UI calls doesn't need depth buffer unlike UIToolkit/uGUI
  179. using (var builder = renderGraph.AddUnsafePass<UnsafePassData>("Screen Space IMGUI/SoftwareCursor Pass - Offscreen", out var passData, base.profilingSampler))
  180. {
  181. passData.colorTarget = output;
  182. builder.UseTexture(output, AccessFlags.Write);
  183. passData.rendererList = renderGraph.CreateUIOverlayRendererList(cameraData.camera, UISubset.LowLevel);
  184. builder.UseRendererList(passData.rendererList);
  185. builder.SetRenderFunc((UnsafePassData data, UnsafeGraphContext context) =>
  186. {
  187. context.cmd.SetRenderTarget(data.colorTarget);
  188. ExecutePass(context.cmd, data, data.rendererList);
  189. });
  190. }
  191. }
  192. internal void RenderOverlay(RenderGraph renderGraph, ContextContainer frameData, in TextureHandle colorBuffer, in TextureHandle depthBuffer)
  193. {
  194. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  195. UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
  196. UniversalRenderer renderer = cameraData.renderer as UniversalRenderer;
  197. // Render uGUI and UIToolkit overlays
  198. using (var builder = renderGraph.AddRasterRenderPass<PassData>("Draw UIToolkit/uGUI Overlay", out var passData, base.profilingSampler))
  199. {
  200. if (cameraData.requiresOpaqueTexture && renderer != null)
  201. builder.UseGlobalTexture(s_CameraOpaqueTextureID);
  202. builder.SetRenderAttachment(colorBuffer, 0);
  203. builder.SetRenderAttachmentDepth(depthBuffer, AccessFlags.ReadWrite);
  204. passData.rendererList = renderGraph.CreateUIOverlayRendererList(cameraData.camera, UISubset.UIToolkit_UGUI);
  205. builder.UseRendererList(passData.rendererList);
  206. builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
  207. {
  208. ExecutePass(context.cmd, data, data.rendererList);
  209. });
  210. }
  211. // Render IMGUI overlay and software cursor in a UnsafePass
  212. // Doing so allow us to safely cover cases when graphics commands called through onGUI() in user scripts are not supported by RenderPass API
  213. // Besides, Vulkan backend doesn't support SetSRGWrite() in RenderPass API and we have some of them at IMGUI levels
  214. // Note, these specific UI calls doesn't need depth buffer unlike UIToolkit/uGUI
  215. using (var builder = renderGraph.AddUnsafePass<UnsafePassData>("Draw IMGUI/SoftwareCursor Overlay", out var passData, base.profilingSampler))
  216. {
  217. passData.colorTarget = colorBuffer;
  218. builder.UseTexture(colorBuffer, AccessFlags.Write);
  219. passData.rendererList = renderGraph.CreateUIOverlayRendererList(cameraData.camera, UISubset.LowLevel);
  220. builder.UseRendererList(passData.rendererList);
  221. builder.SetRenderFunc((UnsafePassData data, UnsafeGraphContext context) =>
  222. {
  223. context.cmd.SetRenderTarget(data.colorTarget);
  224. ExecutePass(context.cmd, data, data.rendererList);
  225. });
  226. }
  227. }
  228. }
  229. }