Brak opisu
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.

CopyDepthPass.cs 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. using System;
  2. using UnityEngine.Experimental.Rendering;
  3. using UnityEngine.Rendering.RenderGraphModule;
  4. namespace UnityEngine.Rendering.Universal.Internal
  5. {
  6. /// <summary>
  7. /// Copy the given depth buffer into the given destination depth buffer.
  8. ///
  9. /// You can use this pass to copy a depth buffer to a destination,
  10. /// so you can use it later in rendering. If the source texture has MSAA
  11. /// enabled, the pass uses a custom MSAA resolve. If the source texture
  12. /// does not have MSAA enabled, the pass uses a Blit or a Copy Texture
  13. /// operation, depending on what the current platform supports.
  14. /// </summary>
  15. public class CopyDepthPass : ScriptableRenderPass
  16. {
  17. private RTHandle source { get; set; }
  18. private RTHandle destination { get; set; }
  19. internal int MssaSamples { get; set; }
  20. // In some cases (Scene view, XR and etc.) we actually want to output to depth buffer
  21. // So this variable needs to be set to true to enable the correct copy shader semantic
  22. internal bool CopyToDepth { get; set; }
  23. Material m_CopyDepthMaterial;
  24. internal bool m_CopyResolvedDepth;
  25. internal bool m_ShouldClear;
  26. private PassData m_PassData;
  27. /// <summary>
  28. /// Creates a new <c>CopyDepthPass</c> instance.
  29. /// </summary>
  30. /// <param name="evt">The <c>RenderPassEvent</c> to use.</param>
  31. /// <param name="copyDepthShader">The <c>Shader</c> to use for copying the depth.</param>
  32. /// <param name="shouldClear">Controls whether it should do a clear before copying the depth.</param>
  33. /// <param name="copyToDepth">Controls whether it should do a copy to a depth format target.</param>
  34. /// <param name="copyResolvedDepth">Set to true if the source depth is MSAA resolved.</param>
  35. /// <param name="customPassName">An optional custom profiling name to disambiguate multiple copy passes.</param>
  36. /// <seealso cref="RenderPassEvent"/>
  37. public CopyDepthPass(RenderPassEvent evt, Shader copyDepthShader, bool shouldClear = false, bool copyToDepth = false, bool copyResolvedDepth = false, string customPassName = null)
  38. {
  39. base.profilingSampler = customPassName != null ? new ProfilingSampler(customPassName) : new ProfilingSampler("Copy Depth");
  40. m_PassData = new PassData();
  41. CopyToDepth = copyToDepth;
  42. m_CopyDepthMaterial = copyDepthShader != null ? CoreUtils.CreateEngineMaterial(copyDepthShader) : null;
  43. renderPassEvent = evt;
  44. m_CopyResolvedDepth = copyResolvedDepth;
  45. m_ShouldClear = shouldClear;
  46. }
  47. /// <summary>
  48. /// Configure the pass with the source and destination to execute on.
  49. /// </summary>
  50. /// <param name="source">Source Render Target</param>
  51. /// <param name="destination">Destination Render Target</param>
  52. public void Setup(RTHandle source, RTHandle destination)
  53. {
  54. this.source = source;
  55. this.destination = destination;
  56. this.MssaSamples = -1;
  57. }
  58. /// <summary>
  59. /// Cleans up resources used by the pass.
  60. /// </summary>
  61. public void Dispose()
  62. {
  63. CoreUtils.Destroy(m_CopyDepthMaterial);
  64. }
  65. /// <inheritdoc />
  66. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  67. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
  68. {
  69. // Disable obsolete warning for internal usage
  70. #pragma warning disable CS0618
  71. #if UNITY_EDITOR
  72. // This is a temporary workaround for Editor as not setting any depth here
  73. // would lead to overwriting depth in certain scenarios (reproducable while running DX11 tests)
  74. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11)
  75. ConfigureTarget(destination, destination);
  76. else
  77. #endif
  78. ConfigureTarget(destination);
  79. if (m_ShouldClear)
  80. ConfigureClear(ClearFlag.All, Color.black);
  81. #pragma warning restore CS0618
  82. }
  83. private class PassData
  84. {
  85. internal TextureHandle source;
  86. internal TextureHandle destination;
  87. internal UniversalCameraData cameraData;
  88. internal Material copyDepthMaterial;
  89. internal int msaaSamples;
  90. internal bool copyResolvedDepth;
  91. internal bool copyToDepth;
  92. }
  93. /// <inheritdoc/>
  94. [Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
  95. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  96. {
  97. var cameraData = renderingData.frameData.Get<UniversalCameraData>();
  98. m_PassData.copyDepthMaterial = m_CopyDepthMaterial;
  99. m_PassData.msaaSamples = MssaSamples;
  100. m_PassData.copyResolvedDepth = m_CopyResolvedDepth;
  101. m_PassData.copyToDepth = CopyToDepth;
  102. m_PassData.cameraData = cameraData;
  103. var cmd = renderingData.commandBuffer;
  104. cmd.SetGlobalTexture("_CameraDepthAttachment", source.nameID);
  105. #if ENABLE_VR && ENABLE_XR_MODULE
  106. if (m_PassData.cameraData.xr.enabled)
  107. {
  108. if (m_PassData.cameraData.xr.supportsFoveatedRendering)
  109. cmd.SetFoveatedRenderingMode(FoveatedRenderingMode.Disabled);
  110. }
  111. #endif
  112. ExecutePass(CommandBufferHelpers.GetRasterCommandBuffer(cmd), m_PassData, this.source, this.destination);
  113. }
  114. private static void ExecutePass(RasterCommandBuffer cmd, PassData passData, RTHandle source, RTHandle destination)
  115. {
  116. var copyDepthMaterial = passData.copyDepthMaterial;
  117. var msaaSamples = passData.msaaSamples;
  118. var copyResolvedDepth = passData.copyResolvedDepth;
  119. var copyToDepth = passData.copyToDepth;
  120. if (copyDepthMaterial == null)
  121. {
  122. Debug.LogErrorFormat("Missing {0}. Copy Depth render pass will not execute. Check for missing reference in the renderer resources.", copyDepthMaterial);
  123. return;
  124. }
  125. using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.CopyDepth)))
  126. {
  127. int cameraSamples = 0;
  128. if (msaaSamples == -1)
  129. {
  130. RTHandle sourceTex = source;
  131. cameraSamples = sourceTex.rt.antiAliasing;
  132. }
  133. else
  134. cameraSamples = msaaSamples;
  135. // When depth resolve is supported or multisampled texture is not supported, set camera samples to 1
  136. if (SystemInfo.supportsMultisampledTextures == 0 || copyResolvedDepth)
  137. cameraSamples = 1;
  138. switch (cameraSamples)
  139. {
  140. case 8:
  141. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa2, false);
  142. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa4, false);
  143. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa8, true);
  144. break;
  145. case 4:
  146. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa2, false);
  147. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa4, true);
  148. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa8, false);
  149. break;
  150. case 2:
  151. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa2, true);
  152. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa4, false);
  153. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa8, false);
  154. break;
  155. // MSAA disabled, auto resolve supported or ms textures not supported
  156. default:
  157. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa2, false);
  158. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa4, false);
  159. cmd.SetKeyword(ShaderGlobalKeywords.DepthMsaa8, false);
  160. break;
  161. }
  162. if (copyToDepth || destination.rt.graphicsFormat == GraphicsFormat.None)
  163. cmd.SetKeyword(ShaderGlobalKeywords._OUTPUT_DEPTH, true);
  164. else
  165. cmd.SetKeyword(ShaderGlobalKeywords._OUTPUT_DEPTH, false);
  166. Vector2 viewportScale = source.useScaling ? new Vector2(source.rtHandleProperties.rtHandleScale.x, source.rtHandleProperties.rtHandleScale.y) : Vector2.one;
  167. // We y-flip if
  168. // 1) we are blitting from render texture to back buffer(UV starts at bottom) and
  169. // 2) renderTexture starts UV at top
  170. bool isGameViewFinalTarget = passData.cameraData.cameraType == CameraType.Game && destination.nameID == BuiltinRenderTextureType.CameraTarget;
  171. #if ENABLE_VR && ENABLE_XR_MODULE
  172. if (passData.cameraData.xr.enabled)
  173. {
  174. isGameViewFinalTarget |= new RenderTargetIdentifier(destination.nameID, 0, CubemapFace.Unknown, 0) == new RenderTargetIdentifier(passData.cameraData.xr.renderTarget, 0, CubemapFace.Unknown, 0);
  175. }
  176. #endif
  177. bool yflip = passData.cameraData.IsHandleYFlipped(source) != passData.cameraData.IsHandleYFlipped(destination);
  178. Vector4 scaleBias = yflip ? new Vector4(viewportScale.x, -viewportScale.y, 0, viewportScale.y) : new Vector4(viewportScale.x, viewportScale.y, 0, 0);
  179. if (isGameViewFinalTarget)
  180. cmd.SetViewport(passData.cameraData.pixelRect);
  181. copyDepthMaterial.SetTexture(Shader.PropertyToID("_CameraDepthAttachment"), source);
  182. Blitter.BlitTexture(cmd, source, scaleBias, copyDepthMaterial, 0);
  183. }
  184. }
  185. /// <inheritdoc/>
  186. public override void OnCameraCleanup(CommandBuffer cmd)
  187. {
  188. if (cmd == null)
  189. throw new ArgumentNullException("cmd");
  190. // Disable obsolete warning for internal usage
  191. #pragma warning disable CS0618
  192. destination = k_CameraTarget;
  193. #pragma warning restore CS0618
  194. }
  195. /// <summary>
  196. /// Sets up the Copy Depth pass for RenderGraph execution
  197. /// </summary>
  198. /// <param name="renderGraph">The current RenderGraph used for recording and execution of a frame.</param>
  199. /// <param name="frameData">The renderer settings containing rendering data of the current frame.</param>
  200. /// <param name="destination"><c>TextureHandle</c> of the destination it will copy to.</param>
  201. /// <param name="source"><c>TextureHandle</c> of the source it will copy from.</param>
  202. /// <param name="bindAsCameraDepth">If this is true, the destination texture is bound as _CameraDepthTexture after the copy pass</param>
  203. /// <param name="passName">The pass name used for debug and identifying the pass.</param>
  204. public void Render(RenderGraph renderGraph, ContextContainer frameData, TextureHandle destination, TextureHandle source, bool bindAsCameraDepth = false, string passName = "Copy Depth")
  205. {
  206. UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
  207. UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
  208. Render(renderGraph, destination, source, resourceData, cameraData, bindAsCameraDepth, passName);
  209. }
  210. /// <summary>
  211. /// Sets up the Copy Depth pass for RenderGraph execution
  212. /// </summary>
  213. /// <param name="renderGraph">The current RenderGraph used for recording and execution of a frame.</param>
  214. /// <param name="destination"><c>TextureHandle</c> of the destination it will copy to.</param>
  215. /// <param name="source"><c>TextureHandle</c> of the source it will copy from.</param>
  216. /// <param name="resourceData">URP texture handles for the current frame.</param>
  217. /// <param name="cameraData">Camera settings for the current frame.</param>
  218. /// <param name="bindAsCameraDepth">If this is true, the destination texture is bound as _CameraDepthTexture after the copy pass</param>
  219. /// <param name="passName">The pass name used for debug and identifying the pass.</param>
  220. public void Render(RenderGraph renderGraph, TextureHandle destination, TextureHandle source, UniversalResourceData resourceData, UniversalCameraData cameraData, bool bindAsCameraDepth = false, string passName = "Copy Depth")
  221. {
  222. // TODO RENDERGRAPH: should call the equivalent of Setup() to initialise everything correctly
  223. MssaSamples = -1;
  224. //Having a different pass name than profilingSampler.name is bad practice but this method was public before we cleaned up this naming
  225. using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName, out var passData, profilingSampler))
  226. {
  227. passData.copyDepthMaterial = m_CopyDepthMaterial;
  228. passData.msaaSamples = MssaSamples;
  229. passData.cameraData = cameraData;
  230. passData.copyResolvedDepth = m_CopyResolvedDepth;
  231. passData.copyToDepth = CopyToDepth;
  232. if (CopyToDepth)
  233. {
  234. // Writes depth using custom depth output
  235. passData.destination = destination;
  236. builder.SetRenderAttachmentDepth(destination, AccessFlags.Write);
  237. #if UNITY_EDITOR
  238. // binding a dummy color target as a workaround to an OSX issue in Editor scene view (UUM-47698).
  239. // Also required for preview camera rendering for grid drawn with builtin RP (UUM-55171).
  240. if (cameraData.isSceneViewCamera || cameraData.isPreviewCamera)
  241. builder.SetRenderAttachment(resourceData.activeColorTexture, 0);
  242. #endif
  243. }
  244. else
  245. {
  246. // Writes depth as "grayscale color" output
  247. passData.destination = destination;
  248. builder.SetRenderAttachment(destination, 0, AccessFlags.Write);
  249. }
  250. passData.source = source;
  251. builder.UseTexture(source, AccessFlags.Read);
  252. if (bindAsCameraDepth && destination.IsValid())
  253. builder.SetGlobalTextureAfterPass(destination, Shader.PropertyToID("_CameraDepthTexture"));
  254. // TODO RENDERGRAPH: culling? force culling off for testing
  255. builder.AllowPassCulling(false);
  256. builder.AllowGlobalStateModification(true);
  257. builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
  258. {
  259. ExecutePass(context.cmd, data, data.source, data.destination);
  260. });
  261. }
  262. }
  263. }
  264. }