ScriptableRenderer.cs 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518
  1. using System;
  2. using System.Diagnostics;
  3. using System.Collections.Generic;
  4. using Unity.Collections;
  5. using UnityEditor;
  6. using UnityEngine.Experimental.Rendering;
  7. using UnityEngine.Profiling;
  8. namespace UnityEngine.Rendering.Universal
  9. {
  10. /// <summary>
  11. /// Class <c>ScriptableRenderer</c> implements a rendering strategy. It describes how culling and lighting works and
  12. /// the effects supported.
  13. ///
  14. /// A renderer can be used for all cameras or be overridden on a per-camera basis. It will implement light culling and setup
  15. /// and describe a list of <c>ScriptableRenderPass</c> to execute in a frame. The renderer can be extended to support more effect with additional
  16. /// <c>ScriptableRendererFeature</c>. Resources for the renderer are serialized in <c>ScriptableRendererData</c>.
  17. ///
  18. /// The renderer resources are serialized in <c>ScriptableRendererData</c>.
  19. /// <seealso cref="ScriptableRendererData"/>
  20. /// <seealso cref="ScriptableRendererFeature"/>
  21. /// <seealso cref="ScriptableRenderPass"/>
  22. /// </summary>
  23. public abstract partial class ScriptableRenderer : IDisposable
  24. {
  25. private static partial class Profiling
  26. {
  27. private const string k_Name = nameof(ScriptableRenderer);
  28. public static readonly ProfilingSampler setPerCameraShaderVariables = new ProfilingSampler($"{k_Name}.{nameof(SetPerCameraShaderVariables)}");
  29. public static readonly ProfilingSampler sortRenderPasses = new ProfilingSampler($"Sort Render Passes");
  30. public static readonly ProfilingSampler setupLights = new ProfilingSampler($"{k_Name}.{nameof(SetupLights)}");
  31. public static readonly ProfilingSampler setupCamera = new ProfilingSampler($"Setup Camera Parameters");
  32. public static readonly ProfilingSampler addRenderPasses = new ProfilingSampler($"{k_Name}.{nameof(AddRenderPasses)}");
  33. public static readonly ProfilingSampler clearRenderingState = new ProfilingSampler($"{k_Name}.{nameof(ClearRenderingState)}");
  34. public static readonly ProfilingSampler internalStartRendering = new ProfilingSampler($"{k_Name}.{nameof(InternalStartRendering)}");
  35. public static readonly ProfilingSampler internalFinishRendering = new ProfilingSampler($"{k_Name}.{nameof(InternalFinishRendering)}");
  36. public static readonly ProfilingSampler drawGizmos = new ProfilingSampler($"{nameof(DrawGizmos)}");
  37. public static class RenderBlock
  38. {
  39. private const string k_Name = nameof(RenderPassBlock);
  40. public static readonly ProfilingSampler beforeRendering = new ProfilingSampler($"{k_Name}.{nameof(RenderPassBlock.BeforeRendering)}");
  41. public static readonly ProfilingSampler mainRenderingOpaque = new ProfilingSampler($"{k_Name}.{nameof(RenderPassBlock.MainRenderingOpaque)}");
  42. public static readonly ProfilingSampler mainRenderingTransparent = new ProfilingSampler($"{k_Name}.{nameof(RenderPassBlock.MainRenderingTransparent)}");
  43. public static readonly ProfilingSampler afterRendering = new ProfilingSampler($"{k_Name}.{nameof(RenderPassBlock.AfterRendering)}");
  44. }
  45. public static class RenderPass
  46. {
  47. private const string k_Name = nameof(ScriptableRenderPass);
  48. public static readonly ProfilingSampler configure = new ProfilingSampler($"{k_Name}.{nameof(ScriptableRenderPass.Configure)}");
  49. }
  50. }
  51. /// <summary>
  52. /// Override to provide a custom profiling name
  53. /// </summary>
  54. protected ProfilingSampler profilingExecute { get; set; }
  55. /// <summary>
  56. /// Configures the supported features for this renderer. When creating custom renderers
  57. /// for Universal Render Pipeline you can choose to opt-in or out for specific features.
  58. /// </summary>
  59. public class RenderingFeatures
  60. {
  61. /// <summary>
  62. /// This setting controls if the camera editor should display the camera stack category.
  63. /// Renderers that don't support camera stacking will only render camera of type CameraRenderType.Base
  64. /// <see cref="CameraRenderType"/>
  65. /// <seealso cref="UniversalAdditionalCameraData.cameraStack"/>
  66. /// </summary>
  67. public bool cameraStacking { get; set; } = false;
  68. /// <summary>
  69. /// This setting controls if the Universal Render Pipeline asset should expose MSAA option.
  70. /// </summary>
  71. public bool msaa { get; set; } = true;
  72. }
  73. /// <summary>
  74. /// The class responsible for providing access to debug view settings to renderers and render passes.
  75. /// </summary>
  76. internal DebugHandler DebugHandler { get; }
  77. /// <summary>
  78. /// The renderer we are currently rendering with, for low-level render control only.
  79. /// <c>current</c> is null outside rendering scope.
  80. /// Similar to https://docs.unity3d.com/ScriptReference/Camera-current.html
  81. /// </summary>
  82. internal static ScriptableRenderer current = null;
  83. /// <summary>
  84. /// Set camera matrices. This method will set <c>UNITY_MATRIX_V</c>, <c>UNITY_MATRIX_P</c>, <c>UNITY_MATRIX_VP</c> to camera matrices.
  85. /// Additionally this will also set <c>unity_CameraProjection</c> and <c>unity_CameraProjection</c>.
  86. /// If <c>setInverseMatrices</c> is set to true this function will also set <c>UNITY_MATRIX_I_V</c> and <c>UNITY_MATRIX_I_VP</c>.
  87. /// This function has no effect when rendering in stereo. When in stereo rendering you cannot override camera matrices.
  88. /// If you need to set general purpose view and projection matrices call <see cref="SetViewAndProjectionMatrices(CommandBuffer, Matrix4x4, Matrix4x4, bool)"/> instead.
  89. /// </summary>
  90. /// <param name="cmd">CommandBuffer to submit data to GPU.</param>
  91. /// <param name="cameraData">CameraData containing camera matrices information.</param>
  92. /// <param name="setInverseMatrices">Set this to true if you also need to set inverse camera matrices.</param>
  93. public static void SetCameraMatrices(CommandBuffer cmd, ref CameraData cameraData, bool setInverseMatrices)
  94. {
  95. #if ENABLE_VR && ENABLE_XR_MODULE
  96. if (cameraData.xr.enabled)
  97. {
  98. cameraData.xr.UpdateGPUViewAndProjectionMatrices(cmd, ref cameraData, cameraData.xr.renderTargetIsRenderTexture);
  99. return;
  100. }
  101. #endif
  102. Matrix4x4 viewMatrix = cameraData.GetViewMatrix();
  103. Matrix4x4 projectionMatrix = cameraData.GetProjectionMatrix();
  104. // TODO: Investigate why SetViewAndProjectionMatrices is causing y-flip / winding order issue
  105. // for now using cmd.SetViewProjecionMatrices
  106. //SetViewAndProjectionMatrices(cmd, viewMatrix, cameraData.GetDeviceProjectionMatrix(), setInverseMatrices);
  107. cmd.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
  108. if (setInverseMatrices)
  109. {
  110. Matrix4x4 gpuProjectionMatrix = cameraData.GetGPUProjectionMatrix();
  111. Matrix4x4 viewAndProjectionMatrix = gpuProjectionMatrix * viewMatrix;
  112. Matrix4x4 inverseViewMatrix = Matrix4x4.Inverse(viewMatrix);
  113. Matrix4x4 inverseProjectionMatrix = Matrix4x4.Inverse(gpuProjectionMatrix);
  114. Matrix4x4 inverseViewProjection = inverseViewMatrix * inverseProjectionMatrix;
  115. // There's an inconsistency in handedness between unity_matrixV and unity_WorldToCamera
  116. // Unity changes the handedness of unity_WorldToCamera (see Camera::CalculateMatrixShaderProps)
  117. // we will also change it here to avoid breaking existing shaders. (case 1257518)
  118. Matrix4x4 worldToCameraMatrix = Matrix4x4.Scale(new Vector3(1.0f, 1.0f, -1.0f)) * viewMatrix;
  119. Matrix4x4 cameraToWorldMatrix = worldToCameraMatrix.inverse;
  120. cmd.SetGlobalMatrix(ShaderPropertyId.worldToCameraMatrix, worldToCameraMatrix);
  121. cmd.SetGlobalMatrix(ShaderPropertyId.cameraToWorldMatrix, cameraToWorldMatrix);
  122. cmd.SetGlobalMatrix(ShaderPropertyId.inverseViewMatrix, inverseViewMatrix);
  123. cmd.SetGlobalMatrix(ShaderPropertyId.inverseProjectionMatrix, inverseProjectionMatrix);
  124. cmd.SetGlobalMatrix(ShaderPropertyId.inverseViewAndProjectionMatrix, inverseViewProjection);
  125. }
  126. // TODO: Add SetPerCameraClippingPlaneProperties here once we are sure it correctly behaves in overlay camera for some time
  127. }
  128. /// <summary>
  129. /// Set camera and screen shader variables as described in https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
  130. /// </summary>
  131. /// <param name="cmd">CommandBuffer to submit data to GPU.</param>
  132. /// <param name="cameraData">CameraData containing camera matrices information.</param>
  133. void SetPerCameraShaderVariables(CommandBuffer cmd, ref CameraData cameraData)
  134. {
  135. using var profScope = new ProfilingScope(null, Profiling.setPerCameraShaderVariables);
  136. Camera camera = cameraData.camera;
  137. Rect pixelRect = cameraData.pixelRect;
  138. float renderScale = cameraData.isSceneViewCamera ? 1f : cameraData.renderScale;
  139. float scaledCameraWidth = (float)pixelRect.width * renderScale;
  140. float scaledCameraHeight = (float)pixelRect.height * renderScale;
  141. float cameraWidth = (float)pixelRect.width;
  142. float cameraHeight = (float)pixelRect.height;
  143. // Use eye texture's width and height as screen params when XR is enabled
  144. if (cameraData.xr.enabled)
  145. {
  146. scaledCameraWidth = (float)cameraData.cameraTargetDescriptor.width;
  147. scaledCameraHeight = (float)cameraData.cameraTargetDescriptor.height;
  148. cameraWidth = (float)cameraData.cameraTargetDescriptor.width;
  149. cameraHeight = (float)cameraData.cameraTargetDescriptor.height;
  150. useRenderPassEnabled = false;
  151. }
  152. if (camera.allowDynamicResolution)
  153. {
  154. scaledCameraWidth *= ScalableBufferManager.widthScaleFactor;
  155. scaledCameraHeight *= ScalableBufferManager.heightScaleFactor;
  156. }
  157. float near = camera.nearClipPlane;
  158. float far = camera.farClipPlane;
  159. float invNear = Mathf.Approximately(near, 0.0f) ? 0.0f : 1.0f / near;
  160. float invFar = Mathf.Approximately(far, 0.0f) ? 0.0f : 1.0f / far;
  161. float isOrthographic = camera.orthographic ? 1.0f : 0.0f;
  162. // From http://www.humus.name/temp/Linearize%20depth.txt
  163. // But as depth component textures on OpenGL always return in 0..1 range (as in D3D), we have to use
  164. // the same constants for both D3D and OpenGL here.
  165. // OpenGL would be this:
  166. // zc0 = (1.0 - far / near) / 2.0;
  167. // zc1 = (1.0 + far / near) / 2.0;
  168. // D3D is this:
  169. float zc0 = 1.0f - far * invNear;
  170. float zc1 = far * invNear;
  171. Vector4 zBufferParams = new Vector4(zc0, zc1, zc0 * invFar, zc1 * invFar);
  172. if (SystemInfo.usesReversedZBuffer)
  173. {
  174. zBufferParams.y += zBufferParams.x;
  175. zBufferParams.x = -zBufferParams.x;
  176. zBufferParams.w += zBufferParams.z;
  177. zBufferParams.z = -zBufferParams.z;
  178. }
  179. // Projection flip sign logic is very deep in GfxDevice::SetInvertProjectionMatrix
  180. // This setup is tailored especially for overlay camera game view
  181. // For other scenarios this will be overwritten correctly by SetupCameraProperties
  182. bool isOffscreen = cameraData.targetTexture != null;
  183. bool invertProjectionMatrix = isOffscreen && SystemInfo.graphicsUVStartsAtTop;
  184. float projectionFlipSign = invertProjectionMatrix ? -1.0f : 1.0f;
  185. Vector4 projectionParams = new Vector4(projectionFlipSign, near, far, 1.0f * invFar);
  186. cmd.SetGlobalVector(ShaderPropertyId.projectionParams, projectionParams);
  187. Vector4 orthoParams = new Vector4(camera.orthographicSize * cameraData.aspectRatio, camera.orthographicSize, 0.0f, isOrthographic);
  188. // Camera and Screen variables as described in https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
  189. cmd.SetGlobalVector(ShaderPropertyId.worldSpaceCameraPos, cameraData.worldSpaceCameraPos);
  190. cmd.SetGlobalVector(ShaderPropertyId.screenParams, new Vector4(cameraWidth, cameraHeight, 1.0f + 1.0f / cameraWidth, 1.0f + 1.0f / cameraHeight));
  191. cmd.SetGlobalVector(ShaderPropertyId.scaledScreenParams, new Vector4(scaledCameraWidth, scaledCameraHeight, 1.0f + 1.0f / scaledCameraWidth, 1.0f + 1.0f / scaledCameraHeight));
  192. cmd.SetGlobalVector(ShaderPropertyId.zBufferParams, zBufferParams);
  193. cmd.SetGlobalVector(ShaderPropertyId.orthoParams, orthoParams);
  194. cmd.SetGlobalVector(ShaderPropertyId.screenSize, new Vector4(cameraWidth, cameraHeight, 1.0f / cameraWidth, 1.0f / cameraHeight));
  195. // Calculate a bias value which corrects the mip lod selection logic when image scaling is active.
  196. // We clamp this value to 0.0 or less to make sure we don't end up reducing image detail in the downsampling case.
  197. float mipBias = Math.Min((float)-Math.Log(cameraWidth / scaledCameraWidth, 2.0f), 0.0f);
  198. cmd.SetGlobalVector(ShaderPropertyId.globalMipBias, new Vector2(mipBias, Mathf.Pow(2.0f, mipBias)));
  199. //Set per camera matrices.
  200. SetCameraMatrices(cmd, ref cameraData, true);
  201. }
  202. /// <summary>
  203. /// Set the Camera billboard properties.
  204. /// </summary>
  205. /// <param name="cmd">CommandBuffer to submit data to GPU.</param>
  206. /// <param name="cameraData">CameraData containing camera matrices information.</param>
  207. void SetPerCameraBillboardProperties(CommandBuffer cmd, ref CameraData cameraData)
  208. {
  209. Matrix4x4 worldToCameraMatrix = cameraData.GetViewMatrix();
  210. Vector3 cameraPos = cameraData.worldSpaceCameraPos;
  211. CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.BillboardFaceCameraPos, QualitySettings.billboardsFaceCameraPosition);
  212. Vector3 billboardTangent;
  213. Vector3 billboardNormal;
  214. float cameraXZAngle;
  215. CalculateBillboardProperties(worldToCameraMatrix, out billboardTangent, out billboardNormal, out cameraXZAngle);
  216. cmd.SetGlobalVector(ShaderPropertyId.billboardNormal, new Vector4(billboardNormal.x, billboardNormal.y, billboardNormal.z, 0.0f));
  217. cmd.SetGlobalVector(ShaderPropertyId.billboardTangent, new Vector4(billboardTangent.x, billboardTangent.y, billboardTangent.z, 0.0f));
  218. cmd.SetGlobalVector(ShaderPropertyId.billboardCameraParams, new Vector4(cameraPos.x, cameraPos.y, cameraPos.z, cameraXZAngle));
  219. }
  220. private static void CalculateBillboardProperties(
  221. in Matrix4x4 worldToCameraMatrix,
  222. out Vector3 billboardTangent,
  223. out Vector3 billboardNormal,
  224. out float cameraXZAngle)
  225. {
  226. Matrix4x4 cameraToWorldMatrix = worldToCameraMatrix;
  227. cameraToWorldMatrix = cameraToWorldMatrix.transpose;
  228. Vector3 cameraToWorldMatrixAxisX = new Vector3(cameraToWorldMatrix.m00, cameraToWorldMatrix.m10, cameraToWorldMatrix.m20);
  229. Vector3 cameraToWorldMatrixAxisY = new Vector3(cameraToWorldMatrix.m01, cameraToWorldMatrix.m11, cameraToWorldMatrix.m21);
  230. Vector3 cameraToWorldMatrixAxisZ = new Vector3(cameraToWorldMatrix.m02, cameraToWorldMatrix.m12, cameraToWorldMatrix.m22);
  231. Vector3 front = cameraToWorldMatrixAxisZ;
  232. Vector3 worldUp = Vector3.up;
  233. Vector3 cross = Vector3.Cross(front, worldUp);
  234. billboardTangent = !Mathf.Approximately(cross.sqrMagnitude, 0.0f)
  235. ? cross.normalized
  236. : cameraToWorldMatrixAxisX;
  237. billboardNormal = Vector3.Cross(worldUp, billboardTangent);
  238. billboardNormal = !Mathf.Approximately(billboardNormal.sqrMagnitude, 0.0f)
  239. ? billboardNormal.normalized
  240. : cameraToWorldMatrixAxisY;
  241. // SpeedTree generates billboards starting from looking towards X- and rotates counter clock-wisely
  242. Vector3 worldRight = new Vector3(0, 0, 1);
  243. // signed angle is calculated on X-Z plane
  244. float s = worldRight.x * billboardTangent.z - worldRight.z * billboardTangent.x;
  245. float c = worldRight.x * billboardTangent.x + worldRight.z * billboardTangent.z;
  246. cameraXZAngle = Mathf.Atan2(s, c);
  247. // convert to [0,2PI)
  248. if (cameraXZAngle < 0)
  249. cameraXZAngle += 2 * Mathf.PI;
  250. }
  251. private void SetPerCameraClippingPlaneProperties(CommandBuffer cmd, in CameraData cameraData)
  252. {
  253. Matrix4x4 projectionMatrix = cameraData.GetGPUProjectionMatrix();
  254. Matrix4x4 viewMatrix = cameraData.GetViewMatrix();
  255. Matrix4x4 viewProj = CoreMatrixUtils.MultiplyProjectionMatrix(projectionMatrix, viewMatrix, cameraData.camera.orthographic);
  256. Plane[] planes = s_Planes;
  257. GeometryUtility.CalculateFrustumPlanes(viewProj, planes);
  258. Vector4[] cameraWorldClipPlanes = s_VectorPlanes;
  259. for (int i = 0; i < planes.Length; ++i)
  260. cameraWorldClipPlanes[i] = new Vector4(planes[i].normal.x, planes[i].normal.y, planes[i].normal.z, planes[i].distance);
  261. cmd.SetGlobalVectorArray(ShaderPropertyId.cameraWorldClipPlanes, cameraWorldClipPlanes);
  262. }
  263. /// <summary>
  264. /// Set shader time variables as described in https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
  265. /// </summary>
  266. /// <param name="cmd">CommandBuffer to submit data to GPU.</param>
  267. /// <param name="time">Time.</param>
  268. /// <param name="deltaTime">Delta time.</param>
  269. /// <param name="smoothDeltaTime">Smooth delta time.</param>
  270. void SetShaderTimeValues(CommandBuffer cmd, float time, float deltaTime, float smoothDeltaTime)
  271. {
  272. float timeEights = time / 8f;
  273. float timeFourth = time / 4f;
  274. float timeHalf = time / 2f;
  275. // Time values
  276. Vector4 timeVector = time * new Vector4(1f / 20f, 1f, 2f, 3f);
  277. Vector4 sinTimeVector = new Vector4(Mathf.Sin(timeEights), Mathf.Sin(timeFourth), Mathf.Sin(timeHalf), Mathf.Sin(time));
  278. Vector4 cosTimeVector = new Vector4(Mathf.Cos(timeEights), Mathf.Cos(timeFourth), Mathf.Cos(timeHalf), Mathf.Cos(time));
  279. Vector4 deltaTimeVector = new Vector4(deltaTime, 1f / deltaTime, smoothDeltaTime, 1f / smoothDeltaTime);
  280. Vector4 timeParametersVector = new Vector4(time, Mathf.Sin(time), Mathf.Cos(time), 0.0f);
  281. cmd.SetGlobalVector(ShaderPropertyId.time, timeVector);
  282. cmd.SetGlobalVector(ShaderPropertyId.sinTime, sinTimeVector);
  283. cmd.SetGlobalVector(ShaderPropertyId.cosTime, cosTimeVector);
  284. cmd.SetGlobalVector(ShaderPropertyId.deltaTime, deltaTimeVector);
  285. cmd.SetGlobalVector(ShaderPropertyId.timeParameters, timeParametersVector);
  286. }
  287. /// <summary>
  288. /// Returns the camera color target for this renderer.
  289. /// It's only valid to call cameraColorTarget in the scope of <c>ScriptableRenderPass</c>.
  290. /// <seealso cref="ScriptableRenderPass"/>.
  291. /// </summary>
  292. public RenderTargetIdentifier cameraColorTarget
  293. {
  294. get
  295. {
  296. if (!(m_IsPipelineExecuting || isCameraColorTargetValid))
  297. {
  298. Debug.LogWarning("You can only call cameraColorTarget inside the scope of a ScriptableRenderPass. Otherwise the pipeline camera target texture might have not been created or might have already been disposed.");
  299. // TODO: Ideally we should return an error texture (BuiltinRenderTextureType.None?)
  300. // but this might break some existing content, so we return the pipeline texture in the hope it gives a "soft" upgrade to users.
  301. }
  302. return m_CameraColorTarget;
  303. }
  304. }
  305. /// <summary>
  306. /// Returns the frontbuffer color target. Returns 0 if not implemented by the renderer.
  307. /// It's only valid to call GetCameraColorFrontBuffer in the scope of <c>ScriptableRenderPass</c>.
  308. /// </summary>
  309. /// <param name="cmd"></param>
  310. /// <returns></returns>
  311. virtual internal RenderTargetIdentifier GetCameraColorFrontBuffer(CommandBuffer cmd)
  312. {
  313. return 0;
  314. }
  315. /// <summary>
  316. /// Returns the camera depth target for this renderer.
  317. /// It's only valid to call cameraDepthTarget in the scope of <c>ScriptableRenderPass</c>.
  318. /// <seealso cref="ScriptableRenderPass"/>.
  319. /// </summary>
  320. public RenderTargetIdentifier cameraDepthTarget
  321. {
  322. get
  323. {
  324. if (!m_IsPipelineExecuting)
  325. {
  326. Debug.LogWarning("You can only call cameraDepthTarget inside the scope of a ScriptableRenderPass. Otherwise the pipeline camera target texture might have not been created or might have already been disposed.");
  327. // TODO: Ideally we should return an error texture (BuiltinRenderTextureType.None?)
  328. // but this might break some existing content, so we return the pipeline texture in the hope it gives a "soft" upgrade to users.
  329. }
  330. return m_CameraDepthTarget;
  331. }
  332. }
  333. /// <summary>
  334. /// Returns a list of renderer features added to this renderer.
  335. /// <seealso cref="ScriptableRendererFeature"/>
  336. /// </summary>
  337. protected List<ScriptableRendererFeature> rendererFeatures
  338. {
  339. get => m_RendererFeatures;
  340. }
  341. /// <summary>
  342. /// Returns a list of render passes scheduled to be executed by this renderer.
  343. /// <seealso cref="ScriptableRenderPass"/>
  344. /// </summary>
  345. protected List<ScriptableRenderPass> activeRenderPassQueue
  346. {
  347. get => m_ActiveRenderPassQueue;
  348. }
  349. /// <summary>
  350. /// Supported rendering features by this renderer.
  351. /// <see cref="SupportedRenderingFeatures"/>
  352. /// </summary>
  353. public RenderingFeatures supportedRenderingFeatures { get; set; } = new RenderingFeatures();
  354. /// <summary>
  355. /// List of unsupported Graphics APIs for this renderer.
  356. /// <see cref="unsupportedGraphicsDeviceTypes"/>
  357. /// </summary>
  358. public GraphicsDeviceType[] unsupportedGraphicsDeviceTypes { get; set; } = new GraphicsDeviceType[0];
  359. static class RenderPassBlock
  360. {
  361. // Executes render passes that are inputs to the main rendering
  362. // but don't depend on camera state. They all render in monoscopic mode. f.ex, shadow maps.
  363. public static readonly int BeforeRendering = 0;
  364. // Main bulk of render pass execution. They required camera state to be properly set
  365. // and when enabled they will render in stereo.
  366. public static readonly int MainRenderingOpaque = 1;
  367. public static readonly int MainRenderingTransparent = 2;
  368. // Execute after Post-processing.
  369. public static readonly int AfterRendering = 3;
  370. }
  371. private StoreActionsOptimization m_StoreActionsOptimizationSetting = StoreActionsOptimization.Auto;
  372. private static bool m_UseOptimizedStoreActions = false;
  373. const int k_RenderPassBlockCount = 4;
  374. List<ScriptableRenderPass> m_ActiveRenderPassQueue = new List<ScriptableRenderPass>(32);
  375. List<ScriptableRendererFeature> m_RendererFeatures = new List<ScriptableRendererFeature>(10);
  376. RenderTargetIdentifier m_CameraColorTarget;
  377. RenderTargetIdentifier m_CameraDepthTarget;
  378. RenderTargetIdentifier m_CameraResolveTarget;
  379. bool m_FirstTimeCameraColorTargetIsBound = true; // flag used to track when m_CameraColorTarget should be cleared (if necessary), as well as other special actions only performed the first time m_CameraColorTarget is bound as a render target
  380. bool m_FirstTimeCameraDepthTargetIsBound = true; // flag used to track when m_CameraDepthTarget should be cleared (if necessary), the first time m_CameraDepthTarget is bound as a render target
  381. // The pipeline can only guarantee the camera target texture are valid when the pipeline is executing.
  382. // Trying to access the camera target before or after might be that the pipeline texture have already been disposed.
  383. bool m_IsPipelineExecuting = false;
  384. // This should be removed when early camera color target assignment is removed.
  385. internal bool isCameraColorTargetValid = false;
  386. // Temporary variable to disable custom passes using render pass ( due to it potentially breaking projects with custom render features )
  387. // To enable it - override SupportsNativeRenderPass method in the feature and return true
  388. internal bool disableNativeRenderPassInFeatures = false;
  389. internal bool useRenderPassEnabled = false;
  390. static RenderTargetIdentifier[] m_ActiveColorAttachments = new RenderTargetIdentifier[] { 0, 0, 0, 0, 0, 0, 0, 0 };
  391. static RenderTargetIdentifier m_ActiveDepthAttachment;
  392. private static RenderBufferStoreAction[] m_ActiveColorStoreActions = new RenderBufferStoreAction[]
  393. {
  394. RenderBufferStoreAction.Store, RenderBufferStoreAction.Store, RenderBufferStoreAction.Store, RenderBufferStoreAction.Store,
  395. RenderBufferStoreAction.Store, RenderBufferStoreAction.Store, RenderBufferStoreAction.Store, RenderBufferStoreAction.Store
  396. };
  397. private static RenderBufferStoreAction m_ActiveDepthStoreAction = RenderBufferStoreAction.Store;
  398. // CommandBuffer.SetRenderTarget(RenderTargetIdentifier[] colors, RenderTargetIdentifier depth, int mipLevel, CubemapFace cubemapFace, int depthSlice);
  399. // called from CoreUtils.SetRenderTarget will issue a warning assert from native c++ side if "colors" array contains some invalid RTIDs.
  400. // To avoid that warning assert we trim the RenderTargetIdentifier[] arrays we pass to CoreUtils.SetRenderTarget.
  401. // To avoid re-allocating a new array every time we do that, we re-use one of these arrays:
  402. static RenderTargetIdentifier[][] m_TrimmedColorAttachmentCopies = new RenderTargetIdentifier[][]
  403. {
  404. new RenderTargetIdentifier[0], // m_TrimmedColorAttachmentCopies[0] is an array of 0 RenderTargetIdentifier - only used to make indexing code easier to read
  405. new RenderTargetIdentifier[] {0}, // m_TrimmedColorAttachmentCopies[1] is an array of 1 RenderTargetIdentifier
  406. new RenderTargetIdentifier[] {0, 0}, // m_TrimmedColorAttachmentCopies[2] is an array of 2 RenderTargetIdentifiers
  407. new RenderTargetIdentifier[] {0, 0, 0}, // m_TrimmedColorAttachmentCopies[3] is an array of 3 RenderTargetIdentifiers
  408. new RenderTargetIdentifier[] {0, 0, 0, 0}, // m_TrimmedColorAttachmentCopies[4] is an array of 4 RenderTargetIdentifiers
  409. new RenderTargetIdentifier[] {0, 0, 0, 0, 0}, // m_TrimmedColorAttachmentCopies[5] is an array of 5 RenderTargetIdentifiers
  410. new RenderTargetIdentifier[] {0, 0, 0, 0, 0, 0}, // m_TrimmedColorAttachmentCopies[6] is an array of 6 RenderTargetIdentifiers
  411. new RenderTargetIdentifier[] {0, 0, 0, 0, 0, 0, 0}, // m_TrimmedColorAttachmentCopies[7] is an array of 7 RenderTargetIdentifiers
  412. new RenderTargetIdentifier[] {0, 0, 0, 0, 0, 0, 0, 0 }, // m_TrimmedColorAttachmentCopies[8] is an array of 8 RenderTargetIdentifiers
  413. };
  414. private static Plane[] s_Planes = new Plane[6];
  415. private static Vector4[] s_VectorPlanes = new Vector4[6];
  416. internal static void ConfigureActiveTarget(RenderTargetIdentifier colorAttachment,
  417. RenderTargetIdentifier depthAttachment)
  418. {
  419. m_ActiveColorAttachments[0] = colorAttachment;
  420. for (int i = 1; i < m_ActiveColorAttachments.Length; ++i)
  421. m_ActiveColorAttachments[i] = 0;
  422. m_ActiveDepthAttachment = depthAttachment;
  423. }
  424. internal bool useDepthPriming { get; set; } = false;
  425. internal bool stripShadowsOffVariants { get; set; } = false;
  426. internal bool stripAdditionalLightOffVariants { get; set; } = false;
  427. public ScriptableRenderer(ScriptableRendererData data)
  428. {
  429. if (Debug.isDebugBuild)
  430. DebugHandler = new DebugHandler(data);
  431. profilingExecute = new ProfilingSampler($"{nameof(ScriptableRenderer)}.{nameof(ScriptableRenderer.Execute)}: {data.name}");
  432. foreach (var feature in data.rendererFeatures)
  433. {
  434. if (feature == null)
  435. continue;
  436. feature.Create();
  437. m_RendererFeatures.Add(feature);
  438. }
  439. ResetNativeRenderPassFrameData();
  440. useRenderPassEnabled = data.useNativeRenderPass && SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES2;
  441. Clear(CameraRenderType.Base);
  442. m_ActiveRenderPassQueue.Clear();
  443. if (UniversalRenderPipeline.asset)
  444. m_StoreActionsOptimizationSetting = UniversalRenderPipeline.asset.storeActionsOptimization;
  445. m_UseOptimizedStoreActions = m_StoreActionsOptimizationSetting != StoreActionsOptimization.Store;
  446. }
  447. public void Dispose()
  448. {
  449. // Dispose all renderer features...
  450. for (int i = 0; i < m_RendererFeatures.Count; ++i)
  451. {
  452. if (rendererFeatures[i] == null)
  453. continue;
  454. rendererFeatures[i].Dispose();
  455. }
  456. Dispose(true);
  457. GC.SuppressFinalize(this);
  458. }
  459. protected virtual void Dispose(bool disposing)
  460. {
  461. }
  462. /// <summary>
  463. /// Configures the camera target.
  464. /// </summary>
  465. /// <param name="colorTarget">Camera color target. Pass BuiltinRenderTextureType.CameraTarget if rendering to backbuffer.</param>
  466. /// <param name="depthTarget">Camera depth target. Pass BuiltinRenderTextureType.CameraTarget if color has depth or rendering to backbuffer.</param>
  467. public void ConfigureCameraTarget(RenderTargetIdentifier colorTarget, RenderTargetIdentifier depthTarget)
  468. {
  469. m_CameraColorTarget = colorTarget;
  470. m_CameraDepthTarget = depthTarget;
  471. }
  472. internal void ConfigureCameraTarget(RenderTargetIdentifier colorTarget, RenderTargetIdentifier depthTarget, RenderTargetIdentifier resolveTarget)
  473. {
  474. m_CameraColorTarget = colorTarget;
  475. m_CameraDepthTarget = depthTarget;
  476. m_CameraResolveTarget = resolveTarget;
  477. }
  478. // This should be removed when early camera color target assignment is removed.
  479. internal void ConfigureCameraColorTarget(RenderTargetIdentifier colorTarget)
  480. {
  481. m_CameraColorTarget = colorTarget;
  482. }
  483. /// <summary>
  484. /// Configures the render passes that will execute for this renderer.
  485. /// This method is called per-camera every frame.
  486. /// </summary>
  487. /// <param name="context">Use this render context to issue any draw commands during execution.</param>
  488. /// <param name="renderingData">Current render state information.</param>
  489. /// <seealso cref="ScriptableRenderPass"/>
  490. /// <seealso cref="ScriptableRendererFeature"/>
  491. public abstract void Setup(ScriptableRenderContext context, ref RenderingData renderingData);
  492. /// <summary>
  493. /// Override this method to implement the lighting setup for the renderer. You can use this to
  494. /// compute and upload light CBUFFER for example.
  495. /// </summary>
  496. /// <param name="context">Use this render context to issue any draw commands during execution.</param>
  497. /// <param name="renderingData">Current render state information.</param>
  498. public virtual void SetupLights(ScriptableRenderContext context, ref RenderingData renderingData)
  499. {
  500. }
  501. /// <summary>
  502. /// Override this method to configure the culling parameters for the renderer. You can use this to configure if
  503. /// lights should be culled per-object or the maximum shadow distance for example.
  504. /// </summary>
  505. /// <param name="cullingParameters">Use this to change culling parameters used by the render pipeline.</param>
  506. /// <param name="cameraData">Current render state information.</param>
  507. public virtual void SetupCullingParameters(ref ScriptableCullingParameters cullingParameters,
  508. ref CameraData cameraData)
  509. {
  510. }
  511. /// <summary>
  512. /// Called upon finishing rendering the camera stack. You can release any resources created by the renderer here.
  513. /// </summary>
  514. /// <param name="cmd"></param>
  515. public virtual void FinishRendering(CommandBuffer cmd)
  516. {
  517. }
  518. /// <summary>
  519. /// Execute the enqueued render passes. This automatically handles editor and stereo rendering.
  520. /// </summary>
  521. /// <param name="context">Use this render context to issue any draw commands during execution.</param>
  522. /// <param name="renderingData">Current render state information.</param>
  523. public void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
  524. {
  525. // Disable Gizmos when using scene overrides. Gizmos break some effects like Overdraw debug.
  526. bool drawGizmos = DebugDisplaySettings.Instance.RenderingSettings.debugSceneOverrideMode == DebugSceneOverrideMode.None;
  527. m_IsPipelineExecuting = true;
  528. ref CameraData cameraData = ref renderingData.cameraData;
  529. Camera camera = cameraData.camera;
  530. CommandBuffer cmd = CommandBufferPool.Get();
  531. // TODO: move skybox code from C++ to URP in order to remove the call to context.Submit() inside DrawSkyboxPass
  532. // Until then, we can't use nested profiling scopes with XR multipass
  533. CommandBuffer cmdScope = renderingData.cameraData.xr.enabled ? null : cmd;
  534. using (new ProfilingScope(cmdScope, profilingExecute))
  535. {
  536. InternalStartRendering(context, ref renderingData);
  537. // Cache the time for after the call to `SetupCameraProperties` and set the time variables in shader
  538. // For now we set the time variables per camera, as we plan to remove `SetupCameraProperties`.
  539. // Setting the time per frame would take API changes to pass the variable to each camera render.
  540. // Once `SetupCameraProperties` is gone, the variable should be set higher in the call-stack.
  541. #if UNITY_EDITOR
  542. float time = Application.isPlaying ? Time.time : Time.realtimeSinceStartup;
  543. #else
  544. float time = Time.time;
  545. #endif
  546. float deltaTime = Time.deltaTime;
  547. float smoothDeltaTime = Time.smoothDeltaTime;
  548. // Initialize Camera Render State
  549. ClearRenderingState(cmd);
  550. SetShaderTimeValues(cmd, time, deltaTime, smoothDeltaTime);
  551. context.ExecuteCommandBuffer(cmd);
  552. cmd.Clear();
  553. using (new ProfilingScope(null, Profiling.sortRenderPasses))
  554. {
  555. // Sort the render pass queue
  556. SortStable(m_ActiveRenderPassQueue);
  557. }
  558. SetupNativeRenderPassFrameData(cameraData, useRenderPassEnabled);
  559. using var renderBlocks = new RenderBlocks(m_ActiveRenderPassQueue);
  560. using (new ProfilingScope(null, Profiling.setupLights))
  561. {
  562. SetupLights(context, ref renderingData);
  563. }
  564. // Before Render Block. This render blocks always execute in mono rendering.
  565. // Camera is not setup.
  566. // Used to render input textures like shadowmaps.
  567. if (renderBlocks.GetLength(RenderPassBlock.BeforeRendering) > 0)
  568. {
  569. // TODO: Separate command buffers per pass break the profiling scope order/hierarchy.
  570. // If a single buffer is used and passed as a param to passes,
  571. // put all of the "block" scopes back into the command buffer. (null -> cmd)
  572. using var profScope = new ProfilingScope(null, Profiling.RenderBlock.beforeRendering);
  573. ExecuteBlock(RenderPassBlock.BeforeRendering, in renderBlocks, context, ref renderingData);
  574. }
  575. using (new ProfilingScope(null, Profiling.setupCamera))
  576. {
  577. // This is still required because of the following reasons:
  578. // - Camera billboard properties.
  579. // - Camera frustum planes: unity_CameraWorldClipPlanes[6]
  580. // - _ProjectionParams.x logic is deep inside GfxDevice
  581. // NOTE: The only reason we have to call this here and not at the beginning (before shadows)
  582. // is because this need to be called for each eye in multi pass VR.
  583. // The side effect is that this will override some shader properties we already setup and we will have to
  584. // reset them.
  585. if (cameraData.renderType == CameraRenderType.Base)
  586. {
  587. context.SetupCameraProperties(camera);
  588. SetPerCameraShaderVariables(cmd, ref cameraData);
  589. }
  590. else
  591. {
  592. // Set new properties
  593. SetPerCameraShaderVariables(cmd, ref cameraData);
  594. SetPerCameraClippingPlaneProperties(cmd, in cameraData);
  595. SetPerCameraBillboardProperties(cmd, ref cameraData);
  596. }
  597. // Reset shader time variables as they were overridden in SetupCameraProperties. If we don't do it we might have a mismatch between shadows and main rendering
  598. SetShaderTimeValues(cmd, time, deltaTime, smoothDeltaTime);
  599. #if VISUAL_EFFECT_GRAPH_0_0_1_OR_NEWER
  600. //Triggers dispatch per camera, all global parameters should have been setup at this stage.
  601. VFX.VFXManager.ProcessCameraCommand(camera, cmd);
  602. #endif
  603. }
  604. context.ExecuteCommandBuffer(cmd);
  605. cmd.Clear();
  606. BeginXRRendering(cmd, context, ref renderingData.cameraData);
  607. // In the opaque and transparent blocks the main rendering executes.
  608. // Opaque blocks...
  609. if (renderBlocks.GetLength(RenderPassBlock.MainRenderingOpaque) > 0)
  610. {
  611. // TODO: Separate command buffers per pass break the profiling scope order/hierarchy.
  612. // If a single buffer is used (passed as a param) for passes,
  613. // put all of the "block" scopes back into the command buffer. (i.e. null -> cmd)
  614. using var profScope = new ProfilingScope(null, Profiling.RenderBlock.mainRenderingOpaque);
  615. ExecuteBlock(RenderPassBlock.MainRenderingOpaque, in renderBlocks, context, ref renderingData);
  616. }
  617. // Transparent blocks...
  618. if (renderBlocks.GetLength(RenderPassBlock.MainRenderingTransparent) > 0)
  619. {
  620. using var profScope = new ProfilingScope(null, Profiling.RenderBlock.mainRenderingTransparent);
  621. ExecuteBlock(RenderPassBlock.MainRenderingTransparent, in renderBlocks, context, ref renderingData);
  622. }
  623. #if ENABLE_VR && ENABLE_XR_MODULE
  624. if (cameraData.xr.enabled)
  625. cameraData.xr.canMarkLateLatch = false;
  626. #endif
  627. // Draw Gizmos...
  628. if (drawGizmos)
  629. {
  630. DrawGizmos(context, camera, GizmoSubset.PreImageEffects);
  631. }
  632. // In this block after rendering drawing happens, e.g, post processing, video player capture.
  633. if (renderBlocks.GetLength(RenderPassBlock.AfterRendering) > 0)
  634. {
  635. using var profScope = new ProfilingScope(null, Profiling.RenderBlock.afterRendering);
  636. ExecuteBlock(RenderPassBlock.AfterRendering, in renderBlocks, context, ref renderingData);
  637. }
  638. EndXRRendering(cmd, context, ref renderingData.cameraData);
  639. DrawWireOverlay(context, camera);
  640. if (drawGizmos)
  641. {
  642. DrawGizmos(context, camera, GizmoSubset.PostImageEffects);
  643. }
  644. InternalFinishRendering(context, cameraData.resolveFinalTarget);
  645. for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i)
  646. {
  647. m_ActiveRenderPassQueue[i].m_ColorAttachmentIndices.Dispose();
  648. m_ActiveRenderPassQueue[i].m_InputAttachmentIndices.Dispose();
  649. }
  650. }
  651. context.ExecuteCommandBuffer(cmd);
  652. CommandBufferPool.Release(cmd);
  653. }
  654. /// <summary>
  655. /// Enqueues a render pass for execution.
  656. /// </summary>
  657. /// <param name="pass">Render pass to be enqueued.</param>
  658. public void EnqueuePass(ScriptableRenderPass pass)
  659. {
  660. m_ActiveRenderPassQueue.Add(pass);
  661. if (disableNativeRenderPassInFeatures)
  662. pass.useNativeRenderPass = false;
  663. }
  664. /// <summary>
  665. /// Returns a clear flag based on CameraClearFlags.
  666. /// </summary>
  667. /// <param name="cameraClearFlags">Camera clear flags.</param>
  668. /// <returns>A clear flag that tells if color and/or depth should be cleared.</returns>
  669. protected static ClearFlag GetCameraClearFlag(ref CameraData cameraData)
  670. {
  671. var cameraClearFlags = cameraData.camera.clearFlags;
  672. // Universal RP doesn't support CameraClearFlags.DepthOnly and CameraClearFlags.Nothing.
  673. // CameraClearFlags.DepthOnly has the same effect of CameraClearFlags.SolidColor
  674. // CameraClearFlags.Nothing clears Depth on PC/Desktop and in mobile it clears both
  675. // depth and color.
  676. // CameraClearFlags.Skybox clears depth only.
  677. // Implementation details:
  678. // Camera clear flags are used to initialize the attachments on the first render pass.
  679. // ClearFlag is used together with Tile Load action to figure out how to clear the camera render target.
  680. // In Tile Based GPUs ClearFlag.Depth + RenderBufferLoadAction.DontCare becomes DontCare load action.
  681. // RenderBufferLoadAction.DontCare in PC/Desktop behaves as not clearing screen
  682. // RenderBufferLoadAction.DontCare in Vulkan/Metal behaves as DontCare load action
  683. // RenderBufferLoadAction.DontCare in GLES behaves as glInvalidateBuffer
  684. // Overlay cameras composite on top of previous ones. They don't clear color.
  685. // For overlay cameras we check if depth should be cleared on not.
  686. if (cameraData.renderType == CameraRenderType.Overlay)
  687. return (cameraData.clearDepth) ? ClearFlag.DepthStencil : ClearFlag.None;
  688. // Certain debug modes (e.g. wireframe/overdraw modes) require that we override clear flags and clear everything.
  689. var debugHandler = cameraData.renderer.DebugHandler;
  690. if (debugHandler != null && debugHandler.IsActiveForCamera(ref cameraData) && debugHandler.IsScreenClearNeeded)
  691. return ClearFlag.All;
  692. // XRTODO: remove once we have visible area of occlusion mesh available
  693. if (cameraClearFlags == CameraClearFlags.Skybox && RenderSettings.skybox != null && cameraData.postProcessEnabled && cameraData.xr.enabled)
  694. return ClearFlag.All;
  695. if ((cameraClearFlags == CameraClearFlags.Skybox && RenderSettings.skybox != null) ||
  696. cameraClearFlags == CameraClearFlags.Nothing)
  697. return ClearFlag.DepthStencil;
  698. return ClearFlag.All;
  699. }
  700. /// <summary>
  701. /// Calls <c>OnCull</c> for each feature added to this renderer.
  702. /// <seealso cref="ScriptableRendererFeature.OnCameraPreCull(ScriptableRenderer, in CameraData)"/>
  703. /// </summary>
  704. /// <param name="cameraData">Current render state information.</param>
  705. internal void OnPreCullRenderPasses(in CameraData cameraData)
  706. {
  707. // Add render passes from custom renderer features
  708. for (int i = 0; i < rendererFeatures.Count; ++i)
  709. {
  710. if (!rendererFeatures[i].isActive)
  711. {
  712. continue;
  713. }
  714. rendererFeatures[i].OnCameraPreCull(this, in cameraData);
  715. }
  716. }
  717. /// <summary>
  718. /// Calls <c>AddRenderPasses</c> for each feature added to this renderer.
  719. /// <seealso cref="ScriptableRendererFeature.AddRenderPasses(ScriptableRenderer, ref RenderingData)"/>
  720. /// </summary>
  721. /// <param name="renderingData"></param>
  722. protected void AddRenderPasses(ref RenderingData renderingData)
  723. {
  724. using var profScope = new ProfilingScope(null, Profiling.addRenderPasses);
  725. // Disable Native RenderPass for any passes that were directly injected prior to our passes and renderer features
  726. int count = activeRenderPassQueue.Count;
  727. for (int i = 0; i < count; i++)
  728. {
  729. if (activeRenderPassQueue[i] != null)
  730. activeRenderPassQueue[i].useNativeRenderPass = false;
  731. }
  732. // Add render passes from custom renderer features
  733. for (int i = 0; i < rendererFeatures.Count; ++i)
  734. {
  735. if (!rendererFeatures[i].isActive)
  736. {
  737. continue;
  738. }
  739. if (!rendererFeatures[i].SupportsNativeRenderPass())
  740. disableNativeRenderPassInFeatures = true;
  741. rendererFeatures[i].AddRenderPasses(this, ref renderingData);
  742. disableNativeRenderPassInFeatures = false;
  743. }
  744. // Remove any null render pass that might have been added by user by mistake
  745. count = activeRenderPassQueue.Count;
  746. for (int i = count - 1; i >= 0; i--)
  747. {
  748. if (activeRenderPassQueue[i] == null)
  749. activeRenderPassQueue.RemoveAt(i);
  750. }
  751. // if any pass was injected, the "automatic" store optimization policy will disable the optimized load actions
  752. if (count > 0 && m_StoreActionsOptimizationSetting == StoreActionsOptimization.Auto)
  753. m_UseOptimizedStoreActions = false;
  754. }
  755. void ClearRenderingState(CommandBuffer cmd)
  756. {
  757. using var profScope = new ProfilingScope(null, Profiling.clearRenderingState);
  758. // Reset per-camera shader keywords. They are enabled depending on which render passes are executed.
  759. cmd.DisableShaderKeyword(ShaderKeywordStrings.MainLightShadows);
  760. cmd.DisableShaderKeyword(ShaderKeywordStrings.MainLightShadowCascades);
  761. cmd.DisableShaderKeyword(ShaderKeywordStrings.AdditionalLightsVertex);
  762. cmd.DisableShaderKeyword(ShaderKeywordStrings.AdditionalLightsPixel);
  763. cmd.DisableShaderKeyword(ShaderKeywordStrings.ClusteredRendering);
  764. cmd.DisableShaderKeyword(ShaderKeywordStrings.AdditionalLightShadows);
  765. cmd.DisableShaderKeyword(ShaderKeywordStrings.ReflectionProbeBlending);
  766. cmd.DisableShaderKeyword(ShaderKeywordStrings.ReflectionProbeBoxProjection);
  767. cmd.DisableShaderKeyword(ShaderKeywordStrings.SoftShadows);
  768. cmd.DisableShaderKeyword(ShaderKeywordStrings.MixedLightingSubtractive); // Backward compatibility
  769. cmd.DisableShaderKeyword(ShaderKeywordStrings.LightmapShadowMixing);
  770. cmd.DisableShaderKeyword(ShaderKeywordStrings.ShadowsShadowMask);
  771. cmd.DisableShaderKeyword(ShaderKeywordStrings.LinearToSRGBConversion);
  772. cmd.DisableShaderKeyword(ShaderKeywordStrings.LightLayers);
  773. }
  774. internal void Clear(CameraRenderType cameraType)
  775. {
  776. m_ActiveColorAttachments[0] = BuiltinRenderTextureType.CameraTarget;
  777. for (int i = 1; i < m_ActiveColorAttachments.Length; ++i)
  778. m_ActiveColorAttachments[i] = 0;
  779. m_ActiveDepthAttachment = BuiltinRenderTextureType.CameraTarget;
  780. m_FirstTimeCameraColorTargetIsBound = cameraType == CameraRenderType.Base;
  781. m_FirstTimeCameraDepthTargetIsBound = true;
  782. m_CameraColorTarget = BuiltinRenderTextureType.CameraTarget;
  783. m_CameraDepthTarget = BuiltinRenderTextureType.CameraTarget;
  784. }
  785. void ExecuteBlock(int blockIndex, in RenderBlocks renderBlocks,
  786. ScriptableRenderContext context, ref RenderingData renderingData, bool submit = false)
  787. {
  788. foreach (int currIndex in renderBlocks.GetRange(blockIndex))
  789. {
  790. var renderPass = m_ActiveRenderPassQueue[currIndex];
  791. ExecuteRenderPass(context, renderPass, ref renderingData);
  792. }
  793. if (submit)
  794. context.Submit();
  795. }
  796. private bool IsRenderPassEnabled(ScriptableRenderPass renderPass)
  797. {
  798. return renderPass.useNativeRenderPass && useRenderPassEnabled;
  799. }
  800. void ExecuteRenderPass(ScriptableRenderContext context, ScriptableRenderPass renderPass,
  801. ref RenderingData renderingData)
  802. {
  803. // TODO: Separate command buffers per pass break the profiling scope order/hierarchy.
  804. // If a single buffer is used (passed as a param) and passed to renderPass.Execute, put the scope into command buffer (i.e. null -> cmd)
  805. using var profScope = new ProfilingScope(null, renderPass.profilingSampler);
  806. ref CameraData cameraData = ref renderingData.cameraData;
  807. CommandBuffer cmd = CommandBufferPool.Get();
  808. // Track CPU only as GPU markers for this scope were "too noisy".
  809. using (new ProfilingScope(null, Profiling.RenderPass.configure))
  810. {
  811. if (IsRenderPassEnabled(renderPass) && cameraData.isRenderPassSupportedCamera)
  812. ConfigureNativeRenderPass(cmd, renderPass, cameraData);
  813. else
  814. renderPass.Configure(cmd, cameraData.cameraTargetDescriptor);
  815. SetRenderPassAttachments(cmd, renderPass, ref cameraData);
  816. }
  817. // Also, we execute the commands recorded at this point to ensure SetRenderTarget is called before RenderPass.Execute
  818. context.ExecuteCommandBuffer(cmd);
  819. CommandBufferPool.Release(cmd);
  820. if (IsRenderPassEnabled(renderPass) && cameraData.isRenderPassSupportedCamera)
  821. ExecuteNativeRenderPass(context, renderPass, cameraData, ref renderingData);
  822. else
  823. renderPass.Execute(context, ref renderingData);
  824. #if ENABLE_VR && ENABLE_XR_MODULE
  825. if (cameraData.xr.enabled && cameraData.xr.hasMarkedLateLatch)
  826. cameraData.xr.UnmarkLateLatchShaderProperties(cmd, ref cameraData);
  827. #endif
  828. }
  829. void SetRenderPassAttachments(CommandBuffer cmd, ScriptableRenderPass renderPass, ref CameraData cameraData)
  830. {
  831. Camera camera = cameraData.camera;
  832. ClearFlag cameraClearFlag = GetCameraClearFlag(ref cameraData);
  833. // Invalid configuration - use current attachment setup
  834. // Note: we only check color buffers. This is only technically correct because for shadowmaps and depth only passes
  835. // we bind depth as color and Unity handles it underneath. so we never have a situation that all color buffers are null and depth is bound.
  836. uint validColorBuffersCount = RenderingUtils.GetValidColorBufferCount(renderPass.colorAttachments);
  837. if (validColorBuffersCount == 0)
  838. return;
  839. // We use a different code path for MRT since it calls a different version of API SetRenderTarget
  840. if (RenderingUtils.IsMRT(renderPass.colorAttachments))
  841. {
  842. // In the MRT path we assume that all color attachments are REAL color attachments,
  843. // and that the depth attachment is a REAL depth attachment too.
  844. // Determine what attachments need to be cleared. ----------------
  845. bool needCustomCameraColorClear = false;
  846. bool needCustomCameraDepthClear = false;
  847. int cameraColorTargetIndex = RenderingUtils.IndexOf(renderPass.colorAttachments, m_CameraColorTarget);
  848. if (cameraColorTargetIndex != -1 && (m_FirstTimeCameraColorTargetIsBound))
  849. {
  850. m_FirstTimeCameraColorTargetIsBound = false; // register that we did clear the camera target the first time it was bound
  851. // Overlay cameras composite on top of previous ones. They don't clear.
  852. // MTT: Commented due to not implemented yet
  853. // if (renderingData.cameraData.renderType == CameraRenderType.Overlay)
  854. // clearFlag = ClearFlag.None;
  855. // We need to specifically clear the camera color target.
  856. // But there is still a chance we don't need to issue individual clear() on each render-targets if they all have the same clear parameters.
  857. needCustomCameraColorClear = (cameraClearFlag & ClearFlag.Color) != (renderPass.clearFlag & ClearFlag.Color)
  858. || CoreUtils.ConvertSRGBToActiveColorSpace(camera.backgroundColor) != renderPass.clearColor;
  859. }
  860. // Note: if we have to give up the assumption that no depthTarget can be included in the MRT colorAttachments, we might need something like this:
  861. // int cameraTargetDepthIndex = IndexOf(renderPass.colorAttachments, m_CameraDepthTarget);
  862. // if( !renderTargetAlreadySet && cameraTargetDepthIndex != -1 && m_FirstTimeCameraDepthTargetIsBound)
  863. // { ...
  864. // }
  865. if (renderPass.depthAttachment == m_CameraDepthTarget && m_FirstTimeCameraDepthTargetIsBound)
  866. {
  867. m_FirstTimeCameraDepthTargetIsBound = false;
  868. needCustomCameraDepthClear = (cameraClearFlag & ClearFlag.DepthStencil) != (renderPass.clearFlag & ClearFlag.DepthStencil);
  869. }
  870. // Perform all clear operations needed. ----------------
  871. // We try to minimize calls to SetRenderTarget().
  872. // We get here only if cameraColorTarget needs to be handled separately from the rest of the color attachments.
  873. if (needCustomCameraColorClear)
  874. {
  875. // Clear camera color render-target separately from the rest of the render-targets.
  876. if ((cameraClearFlag & ClearFlag.Color) != 0 && (!IsRenderPassEnabled(renderPass) || !cameraData.isRenderPassSupportedCamera))
  877. SetRenderTarget(cmd, renderPass.colorAttachments[cameraColorTargetIndex], renderPass.depthAttachment, ClearFlag.Color, CoreUtils.ConvertSRGBToActiveColorSpace(camera.backgroundColor));
  878. if ((renderPass.clearFlag & ClearFlag.Color) != 0)
  879. {
  880. uint otherTargetsCount = RenderingUtils.CountDistinct(renderPass.colorAttachments, m_CameraColorTarget);
  881. var nonCameraAttachments = m_TrimmedColorAttachmentCopies[otherTargetsCount];
  882. int writeIndex = 0;
  883. for (int readIndex = 0; readIndex < renderPass.colorAttachments.Length; ++readIndex)
  884. {
  885. if (renderPass.colorAttachments[readIndex] != m_CameraColorTarget && renderPass.colorAttachments[readIndex] != 0)
  886. {
  887. nonCameraAttachments[writeIndex] = renderPass.colorAttachments[readIndex];
  888. ++writeIndex;
  889. }
  890. }
  891. if (writeIndex != otherTargetsCount)
  892. Debug.LogError("writeIndex and otherTargetsCount values differed. writeIndex:" + writeIndex + " otherTargetsCount:" + otherTargetsCount);
  893. if (!IsRenderPassEnabled(renderPass) || !cameraData.isRenderPassSupportedCamera)
  894. SetRenderTarget(cmd, nonCameraAttachments, m_CameraDepthTarget, ClearFlag.Color, renderPass.clearColor);
  895. }
  896. }
  897. // Bind all attachments, clear color only if there was no custom behaviour for cameraColorTarget, clear depth as needed.
  898. ClearFlag finalClearFlag = ClearFlag.None;
  899. finalClearFlag |= needCustomCameraDepthClear ? (cameraClearFlag & ClearFlag.DepthStencil) : (renderPass.clearFlag & ClearFlag.DepthStencil);
  900. finalClearFlag |= needCustomCameraColorClear ? (IsRenderPassEnabled(renderPass) ? (cameraClearFlag & ClearFlag.Color) : 0) : (renderPass.clearFlag & ClearFlag.Color);
  901. if (IsRenderPassEnabled(renderPass) && cameraData.isRenderPassSupportedCamera)
  902. SetNativeRenderPassMRTAttachmentList(renderPass, ref cameraData, needCustomCameraColorClear, finalClearFlag);
  903. // Only setup render target if current render pass attachments are different from the active ones.
  904. if (!RenderingUtils.SequenceEqual(renderPass.colorAttachments, m_ActiveColorAttachments) || renderPass.depthAttachment != m_ActiveDepthAttachment || finalClearFlag != ClearFlag.None)
  905. {
  906. int lastValidRTindex = RenderingUtils.LastValid(renderPass.colorAttachments);
  907. if (lastValidRTindex >= 0)
  908. {
  909. int rtCount = lastValidRTindex + 1;
  910. var trimmedAttachments = m_TrimmedColorAttachmentCopies[rtCount];
  911. for (int i = 0; i < rtCount; ++i)
  912. trimmedAttachments[i] = renderPass.colorAttachments[i];
  913. if (!IsRenderPassEnabled(renderPass) || !cameraData.isRenderPassSupportedCamera)
  914. {
  915. RenderTargetIdentifier depthAttachment = m_CameraDepthTarget;
  916. if (renderPass.overrideCameraTarget)
  917. {
  918. depthAttachment = renderPass.depthAttachment;
  919. }
  920. else
  921. {
  922. m_FirstTimeCameraDepthTargetIsBound = false;
  923. }
  924. SetRenderTarget(cmd, trimmedAttachments, depthAttachment, finalClearFlag, renderPass.clearColor);
  925. }
  926. #if ENABLE_VR && ENABLE_XR_MODULE
  927. if (cameraData.xr.enabled)
  928. {
  929. // SetRenderTarget might alter the internal device state(winding order).
  930. // Non-stereo buffer is already updated internally when switching render target. We update stereo buffers here to keep the consistency.
  931. int xrTargetIndex = RenderingUtils.IndexOf(renderPass.colorAttachments, cameraData.xr.renderTarget);
  932. bool isRenderToBackBufferTarget = (xrTargetIndex != -1) && !cameraData.xr.renderTargetIsRenderTexture;
  933. cameraData.xr.UpdateGPUViewAndProjectionMatrices(cmd, ref cameraData, !isRenderToBackBufferTarget);
  934. }
  935. #endif
  936. }
  937. }
  938. }
  939. else
  940. {
  941. // Currently in non-MRT case, color attachment can actually be a depth attachment.
  942. RenderTargetIdentifier passColorAttachment = renderPass.colorAttachment;
  943. RenderTargetIdentifier passDepthAttachment = renderPass.depthAttachment;
  944. // When render pass doesn't call ConfigureTarget we assume it's expected to render to camera target
  945. // which might be backbuffer or the framebuffer render textures.
  946. if (!renderPass.overrideCameraTarget)
  947. {
  948. // Default render pass attachment for passes before main rendering is current active
  949. // early return so we don't change current render target setup.
  950. if (renderPass.renderPassEvent < RenderPassEvent.BeforeRenderingPrePasses)
  951. return;
  952. // Otherwise default is the pipeline camera target.
  953. passColorAttachment = m_CameraColorTarget;
  954. passDepthAttachment = m_CameraDepthTarget;
  955. }
  956. ClearFlag finalClearFlag = ClearFlag.None;
  957. Color finalClearColor;
  958. if (passColorAttachment == m_CameraColorTarget && (m_FirstTimeCameraColorTargetIsBound))
  959. {
  960. m_FirstTimeCameraColorTargetIsBound = false; // register that we did clear the camera target the first time it was bound
  961. finalClearFlag |= (cameraClearFlag & ClearFlag.Color);
  962. finalClearColor = CoreUtils.ConvertSRGBToActiveColorSpace(camera.backgroundColor);
  963. if (m_FirstTimeCameraDepthTargetIsBound)
  964. {
  965. // m_CameraColorTarget can be an opaque pointer to a RenderTexture with depth-surface.
  966. // We cannot infer this information here, so we must assume both camera color and depth are first-time bound here (this is the legacy behaviour).
  967. m_FirstTimeCameraDepthTargetIsBound = false;
  968. finalClearFlag |= (cameraClearFlag & ClearFlag.DepthStencil);
  969. }
  970. }
  971. else
  972. {
  973. finalClearFlag |= (renderPass.clearFlag & ClearFlag.Color);
  974. finalClearColor = renderPass.clearColor;
  975. }
  976. // Condition (m_CameraDepthTarget!=BuiltinRenderTextureType.CameraTarget) below prevents m_FirstTimeCameraDepthTargetIsBound flag from being reset during non-camera passes (such as Color Grading LUT). This ensures that in those cases, cameraDepth will actually be cleared during the later camera pass.
  977. if ((m_CameraDepthTarget != BuiltinRenderTextureType.CameraTarget) && (passDepthAttachment == m_CameraDepthTarget || passColorAttachment == m_CameraDepthTarget) && m_FirstTimeCameraDepthTargetIsBound)
  978. {
  979. m_FirstTimeCameraDepthTargetIsBound = false;
  980. finalClearFlag |= (cameraClearFlag & ClearFlag.DepthStencil);
  981. // finalClearFlag |= (cameraClearFlag & ClearFlag.Color); // <- m_CameraDepthTarget is never a color-surface, so no need to add this here.
  982. }
  983. else
  984. finalClearFlag |= (renderPass.clearFlag & ClearFlag.DepthStencil);
  985. #if UNITY_EDITOR
  986. if (CoreUtils.IsSceneFilteringEnabled() && camera.sceneViewFilterMode == Camera.SceneViewFilterMode.ShowFiltered)
  987. {
  988. finalClearColor.a = 0;
  989. finalClearFlag &= ~ClearFlag.Depth;
  990. }
  991. #endif
  992. // If the debug-handler needs to clear the screen, update "finalClearColor" accordingly...
  993. if ((DebugHandler != null) && DebugHandler.IsActiveForCamera(ref cameraData))
  994. {
  995. DebugHandler.TryGetScreenClearColor(ref finalClearColor);
  996. }
  997. if (IsRenderPassEnabled(renderPass) && cameraData.isRenderPassSupportedCamera)
  998. {
  999. SetNativeRenderPassAttachmentList(renderPass, ref cameraData, passColorAttachment, passDepthAttachment, finalClearFlag, finalClearColor);
  1000. }
  1001. else
  1002. {
  1003. // Only setup render target if current render pass attachments are different from the active ones
  1004. if (passColorAttachment != m_ActiveColorAttachments[0] || passDepthAttachment != m_ActiveDepthAttachment || finalClearFlag != ClearFlag.None ||
  1005. renderPass.colorStoreActions[0] != m_ActiveColorStoreActions[0] || renderPass.depthStoreAction != m_ActiveDepthStoreAction)
  1006. {
  1007. SetRenderTarget(cmd, passColorAttachment, passDepthAttachment, finalClearFlag, finalClearColor, renderPass.colorStoreActions[0], renderPass.depthStoreAction);
  1008. #if ENABLE_VR && ENABLE_XR_MODULE
  1009. if (cameraData.xr.enabled)
  1010. {
  1011. bool isOculusMotionVec = renderPass is Internal.OculusMotionVectorPass;
  1012. // SetRenderTarget might alter the internal device state(winding order).
  1013. // Non-stereo buffer is already updated internally when switching render target. We update stereo buffers here to keep the consistency.
  1014. bool isRenderToBackBufferTarget = ((passColorAttachment == cameraData.xr.renderTarget) && !cameraData.xr.renderTargetIsRenderTexture) ||
  1015. ((passColorAttachment == cameraData.xr.motionVectorRenderTarget) && !cameraData.xr.motionVectorRenderTargetIsRenderTexture);
  1016. cameraData.xr.UpdateGPUViewAndProjectionMatrices(cmd, ref cameraData, !isRenderToBackBufferTarget, isOculusMotionVec);
  1017. }
  1018. #endif
  1019. }
  1020. }
  1021. }
  1022. }
  1023. void BeginXRRendering(CommandBuffer cmd, ScriptableRenderContext context, ref CameraData cameraData)
  1024. {
  1025. #if ENABLE_VR && ENABLE_XR_MODULE
  1026. if (cameraData.xr.enabled)
  1027. {
  1028. if (cameraData.xr.isLateLatchEnabled)
  1029. cameraData.xr.canMarkLateLatch = true;
  1030. cameraData.xr.StartSinglePass(cmd);
  1031. cmd.EnableShaderKeyword(ShaderKeywordStrings.UseDrawProcedural);
  1032. context.ExecuteCommandBuffer(cmd);
  1033. cmd.Clear();
  1034. }
  1035. #endif
  1036. }
  1037. void EndXRRendering(CommandBuffer cmd, ScriptableRenderContext context, ref CameraData cameraData)
  1038. {
  1039. #if ENABLE_VR && ENABLE_XR_MODULE
  1040. if (cameraData.xr.enabled)
  1041. {
  1042. cameraData.xr.StopSinglePass(cmd);
  1043. cmd.DisableShaderKeyword(ShaderKeywordStrings.UseDrawProcedural);
  1044. context.ExecuteCommandBuffer(cmd);
  1045. cmd.Clear();
  1046. }
  1047. #endif
  1048. }
  1049. internal static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorAttachment, RenderTargetIdentifier depthAttachment, ClearFlag clearFlag, Color clearColor)
  1050. {
  1051. m_ActiveColorAttachments[0] = colorAttachment;
  1052. for (int i = 1; i < m_ActiveColorAttachments.Length; ++i)
  1053. m_ActiveColorAttachments[i] = 0;
  1054. m_ActiveColorStoreActions[0] = RenderBufferStoreAction.Store;
  1055. m_ActiveDepthStoreAction = RenderBufferStoreAction.Store;
  1056. for (int i = 1; i < m_ActiveColorStoreActions.Length; ++i)
  1057. m_ActiveColorStoreActions[i] = RenderBufferStoreAction.Store;
  1058. m_ActiveDepthAttachment = depthAttachment;
  1059. RenderBufferLoadAction colorLoadAction = ((uint)clearFlag & (uint)ClearFlag.Color) != 0 ? RenderBufferLoadAction.DontCare : RenderBufferLoadAction.Load;
  1060. RenderBufferLoadAction depthLoadAction = ((uint)clearFlag & (uint)ClearFlag.Depth) != 0 || ((uint)clearFlag & (uint)ClearFlag.Stencil) != 0 ?
  1061. RenderBufferLoadAction.DontCare : RenderBufferLoadAction.Load;
  1062. SetRenderTarget(cmd, colorAttachment, colorLoadAction, RenderBufferStoreAction.Store,
  1063. depthAttachment, depthLoadAction, RenderBufferStoreAction.Store, clearFlag, clearColor);
  1064. }
  1065. internal static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorAttachment, RenderTargetIdentifier depthAttachment, ClearFlag clearFlag, Color clearColor, RenderBufferStoreAction colorStoreAction, RenderBufferStoreAction depthStoreAction)
  1066. {
  1067. m_ActiveColorAttachments[0] = colorAttachment;
  1068. for (int i = 1; i < m_ActiveColorAttachments.Length; ++i)
  1069. m_ActiveColorAttachments[i] = 0;
  1070. m_ActiveColorStoreActions[0] = colorStoreAction;
  1071. m_ActiveDepthStoreAction = depthStoreAction;
  1072. for (int i = 1; i < m_ActiveColorStoreActions.Length; ++i)
  1073. m_ActiveColorStoreActions[i] = RenderBufferStoreAction.Store;
  1074. m_ActiveDepthAttachment = depthAttachment;
  1075. RenderBufferLoadAction colorLoadAction = ((uint)clearFlag & (uint)ClearFlag.Color) != 0 ?
  1076. RenderBufferLoadAction.DontCare : RenderBufferLoadAction.Load;
  1077. RenderBufferLoadAction depthLoadAction = ((uint)clearFlag & (uint)ClearFlag.Depth) != 0 ?
  1078. RenderBufferLoadAction.DontCare : RenderBufferLoadAction.Load;
  1079. // if we shouldn't use optimized store actions then fall back to the conservative safe (un-optimal!) route and just store everything
  1080. if (!m_UseOptimizedStoreActions)
  1081. {
  1082. if (colorStoreAction != RenderBufferStoreAction.StoreAndResolve)
  1083. colorStoreAction = RenderBufferStoreAction.Store;
  1084. if (depthStoreAction != RenderBufferStoreAction.StoreAndResolve)
  1085. depthStoreAction = RenderBufferStoreAction.Store;
  1086. }
  1087. SetRenderTarget(cmd, colorAttachment, colorLoadAction, colorStoreAction,
  1088. depthAttachment, depthLoadAction, depthStoreAction, clearFlag, clearColor);
  1089. }
  1090. static void SetRenderTarget(CommandBuffer cmd,
  1091. RenderTargetIdentifier colorAttachment,
  1092. RenderBufferLoadAction colorLoadAction,
  1093. RenderBufferStoreAction colorStoreAction,
  1094. ClearFlag clearFlags,
  1095. Color clearColor)
  1096. {
  1097. CoreUtils.SetRenderTarget(cmd, colorAttachment, colorLoadAction, colorStoreAction, clearFlags, clearColor);
  1098. }
  1099. static void SetRenderTarget(CommandBuffer cmd,
  1100. RenderTargetIdentifier colorAttachment,
  1101. RenderBufferLoadAction colorLoadAction,
  1102. RenderBufferStoreAction colorStoreAction,
  1103. RenderTargetIdentifier depthAttachment,
  1104. RenderBufferLoadAction depthLoadAction,
  1105. RenderBufferStoreAction depthStoreAction,
  1106. ClearFlag clearFlags,
  1107. Color clearColor)
  1108. {
  1109. // XRTODO: Revisit the logic. Why treat CameraTarget depth specially?
  1110. if (depthAttachment == BuiltinRenderTextureType.CameraTarget)
  1111. {
  1112. CoreUtils.SetRenderTarget(cmd, colorAttachment, colorLoadAction, colorStoreAction, depthLoadAction, depthStoreAction, clearFlags, clearColor);
  1113. }
  1114. else
  1115. {
  1116. CoreUtils.SetRenderTarget(cmd, colorAttachment, colorLoadAction, colorStoreAction,
  1117. depthAttachment, depthLoadAction, depthStoreAction, clearFlags, clearColor);
  1118. }
  1119. }
  1120. static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorAttachments, RenderTargetIdentifier depthAttachment, ClearFlag clearFlag, Color clearColor)
  1121. {
  1122. m_ActiveColorAttachments = colorAttachments;
  1123. m_ActiveDepthAttachment = depthAttachment;
  1124. CoreUtils.SetRenderTarget(cmd, colorAttachments, depthAttachment, clearFlag, clearColor);
  1125. }
  1126. internal virtual void SwapColorBuffer(CommandBuffer cmd) { }
  1127. internal virtual void EnableSwapBufferMSAA(bool enable) { }
  1128. [Conditional("UNITY_EDITOR")]
  1129. void DrawGizmos(ScriptableRenderContext context, Camera camera, GizmoSubset gizmoSubset)
  1130. {
  1131. #if UNITY_EDITOR
  1132. if (!Handles.ShouldRenderGizmos() || camera.sceneViewFilterMode == Camera.SceneViewFilterMode.ShowFiltered)
  1133. return;
  1134. CommandBuffer cmd = CommandBufferPool.Get();
  1135. using (new ProfilingScope(cmd, Profiling.drawGizmos))
  1136. {
  1137. context.ExecuteCommandBuffer(cmd);
  1138. cmd.Clear();
  1139. context.DrawGizmos(camera, gizmoSubset);
  1140. }
  1141. context.ExecuteCommandBuffer(cmd);
  1142. CommandBufferPool.Release(cmd);
  1143. #endif
  1144. }
  1145. [Conditional("UNITY_EDITOR")]
  1146. void DrawWireOverlay(ScriptableRenderContext context, Camera camera)
  1147. {
  1148. context.DrawWireOverlay(camera);
  1149. }
  1150. void InternalStartRendering(ScriptableRenderContext context, ref RenderingData renderingData)
  1151. {
  1152. CommandBuffer cmd = CommandBufferPool.Get();
  1153. using (new ProfilingScope(null, Profiling.internalStartRendering))
  1154. {
  1155. for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i)
  1156. {
  1157. m_ActiveRenderPassQueue[i].OnCameraSetup(cmd, ref renderingData);
  1158. }
  1159. }
  1160. context.ExecuteCommandBuffer(cmd);
  1161. CommandBufferPool.Release(cmd);
  1162. }
  1163. void InternalFinishRendering(ScriptableRenderContext context, bool resolveFinalTarget)
  1164. {
  1165. CommandBuffer cmd = CommandBufferPool.Get();
  1166. using (new ProfilingScope(null, Profiling.internalFinishRendering))
  1167. {
  1168. for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i)
  1169. m_ActiveRenderPassQueue[i].FrameCleanup(cmd);
  1170. // Happens when rendering the last camera in the camera stack.
  1171. if (resolveFinalTarget)
  1172. {
  1173. for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i)
  1174. m_ActiveRenderPassQueue[i].OnFinishCameraStackRendering(cmd);
  1175. FinishRendering(cmd);
  1176. // We finished camera stacking and released all intermediate pipeline textures.
  1177. m_IsPipelineExecuting = false;
  1178. }
  1179. m_ActiveRenderPassQueue.Clear();
  1180. }
  1181. ResetNativeRenderPassFrameData();
  1182. context.ExecuteCommandBuffer(cmd);
  1183. CommandBufferPool.Release(cmd);
  1184. }
  1185. internal static void SortStable(List<ScriptableRenderPass> list)
  1186. {
  1187. int j;
  1188. for (int i = 1; i < list.Count; ++i)
  1189. {
  1190. ScriptableRenderPass curr = list[i];
  1191. j = i - 1;
  1192. for (; j >= 0 && curr < list[j]; --j)
  1193. list[j + 1] = list[j];
  1194. list[j + 1] = curr;
  1195. }
  1196. }
  1197. internal struct RenderBlocks : IDisposable
  1198. {
  1199. private NativeArray<RenderPassEvent> m_BlockEventLimits;
  1200. private NativeArray<int> m_BlockRanges;
  1201. private NativeArray<int> m_BlockRangeLengths;
  1202. public RenderBlocks(List<ScriptableRenderPass> activeRenderPassQueue)
  1203. {
  1204. // Upper limits for each block. Each block will contains render passes with events below the limit.
  1205. m_BlockEventLimits = new NativeArray<RenderPassEvent>(k_RenderPassBlockCount, Allocator.Temp);
  1206. m_BlockRanges = new NativeArray<int>(m_BlockEventLimits.Length + 1, Allocator.Temp);
  1207. m_BlockRangeLengths = new NativeArray<int>(m_BlockRanges.Length, Allocator.Temp);
  1208. m_BlockEventLimits[RenderPassBlock.BeforeRendering] = RenderPassEvent.BeforeRenderingPrePasses;
  1209. m_BlockEventLimits[RenderPassBlock.MainRenderingOpaque] = RenderPassEvent.AfterRenderingOpaques;
  1210. m_BlockEventLimits[RenderPassBlock.MainRenderingTransparent] = RenderPassEvent.AfterRenderingPostProcessing;
  1211. m_BlockEventLimits[RenderPassBlock.AfterRendering] = (RenderPassEvent)Int32.MaxValue;
  1212. // blockRanges[0] is always 0
  1213. // blockRanges[i] is the index of the first RenderPass found in m_ActiveRenderPassQueue that has a ScriptableRenderPass.renderPassEvent higher than blockEventLimits[i] (i.e, should be executed after blockEventLimits[i])
  1214. // blockRanges[blockEventLimits.Length] is m_ActiveRenderPassQueue.Count
  1215. FillBlockRanges(activeRenderPassQueue);
  1216. m_BlockEventLimits.Dispose();
  1217. for (int i = 0; i < m_BlockRanges.Length - 1; i++)
  1218. {
  1219. m_BlockRangeLengths[i] = m_BlockRanges[i + 1] - m_BlockRanges[i];
  1220. }
  1221. }
  1222. // RAII like Dispose pattern implementation for 'using' keyword
  1223. public void Dispose()
  1224. {
  1225. m_BlockRangeLengths.Dispose();
  1226. m_BlockRanges.Dispose();
  1227. }
  1228. // Fill in render pass indices for each block. End index is startIndex + 1.
  1229. void FillBlockRanges(List<ScriptableRenderPass> activeRenderPassQueue)
  1230. {
  1231. int currRangeIndex = 0;
  1232. int currRenderPass = 0;
  1233. m_BlockRanges[currRangeIndex++] = 0;
  1234. // For each block, it finds the first render pass index that has an event
  1235. // higher than the block limit.
  1236. for (int i = 0; i < m_BlockEventLimits.Length - 1; ++i)
  1237. {
  1238. while (currRenderPass < activeRenderPassQueue.Count &&
  1239. activeRenderPassQueue[currRenderPass].renderPassEvent < m_BlockEventLimits[i])
  1240. currRenderPass++;
  1241. m_BlockRanges[currRangeIndex++] = currRenderPass;
  1242. }
  1243. m_BlockRanges[currRangeIndex] = activeRenderPassQueue.Count;
  1244. }
  1245. public int GetLength(int index)
  1246. {
  1247. return m_BlockRangeLengths[index];
  1248. }
  1249. // Minimal foreach support
  1250. public struct BlockRange : IDisposable
  1251. {
  1252. int m_Current;
  1253. int m_End;
  1254. public BlockRange(int begin, int end)
  1255. {
  1256. Assertions.Assert.IsTrue(begin <= end);
  1257. m_Current = begin < end ? begin : end;
  1258. m_End = end >= begin ? end : begin;
  1259. m_Current -= 1;
  1260. }
  1261. public BlockRange GetEnumerator() { return this; }
  1262. public bool MoveNext() { return ++m_Current < m_End; }
  1263. public int Current { get => m_Current; }
  1264. public void Dispose() { }
  1265. }
  1266. public BlockRange GetRange(int index)
  1267. {
  1268. return new BlockRange(m_BlockRanges[index], m_BlockRanges[index + 1]);
  1269. }
  1270. }
  1271. }
  1272. }