ShaderPreprocessor.cs 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEditor.Build;
  5. using UnityEditor.Build.Reporting;
  6. using UnityEngine;
  7. using UnityEngine.Profiling;
  8. using UnityEngine.Rendering.Universal;
  9. using UnityEngine.Rendering;
  10. using System.Runtime.CompilerServices;
  11. #if XR_MANAGEMENT_4_0_1_OR_NEWER
  12. using UnityEditor.XR.Management;
  13. #endif
  14. namespace UnityEditor.Rendering.Universal
  15. {
  16. [Flags]
  17. enum ShaderFeatures
  18. {
  19. None = 0,
  20. MainLight = (1 << 0),
  21. MainLightShadows = (1 << 1),
  22. AdditionalLights = (1 << 2),
  23. AdditionalLightShadows = (1 << 3),
  24. VertexLighting = (1 << 4),
  25. SoftShadows = (1 << 5),
  26. MixedLighting = (1 << 6),
  27. TerrainHoles = (1 << 7),
  28. DeferredShading = (1 << 8), // DeferredRenderer is in the list of renderer
  29. AccurateGbufferNormals = (1 << 9),
  30. ScreenSpaceOcclusion = (1 << 10),
  31. ScreenSpaceShadows = (1 << 11),
  32. UseFastSRGBLinearConversion = (1 << 12),
  33. LightLayers = (1 << 13),
  34. ReflectionProbeBlending = (1 << 14),
  35. ReflectionProbeBoxProjection = (1 << 15),
  36. DBufferMRT1 = (1 << 16),
  37. DBufferMRT2 = (1 << 17),
  38. DBufferMRT3 = (1 << 18),
  39. DecalScreenSpace = (1 << 19),
  40. DecalGBuffer = (1 << 20),
  41. DecalNormalBlendLow = (1 << 21),
  42. DecalNormalBlendMedium = (1 << 22),
  43. DecalNormalBlendHigh = (1 << 23),
  44. ClusteredRendering = (1 << 24),
  45. RenderPassEnabled = (1 << 25),
  46. MainLightShadowsCascade = (1 << 26),
  47. DrawProcedural = (1 << 27),
  48. ScreenSpaceOcclusionAfterOpaque = (1 << 28),
  49. AdditionalLightsKeepOffVariants = (1 << 29),
  50. ShadowsKeepOffVariants = (1 << 30),
  51. }
  52. [Flags]
  53. enum VolumeFeatures
  54. {
  55. None = 0,
  56. Calculated = (1 << 0),
  57. LensDistortion = (1 << 1),
  58. Bloom = (1 << 2),
  59. ChromaticAberration = (1 << 3),
  60. ToneMaping = (1 << 4),
  61. FilmGrain = (1 << 5),
  62. DepthOfField = (1 << 6),
  63. CameraMotionBlur = (1 << 7),
  64. PaniniProjection = (1 << 8),
  65. }
  66. internal class ShaderPreprocessor : IPreprocessShaders
  67. {
  68. public static readonly string kPassNameGBuffer = "GBuffer";
  69. public static readonly string kTerrainShaderName = "Universal Render Pipeline/Terrain/Lit";
  70. #if PROFILE_BUILD
  71. private const string k_ProcessShaderTag = "OnProcessShader";
  72. #endif
  73. // Event callback to report shader stripping info. Form:
  74. // ReportShaderStrippingData(Shader shader, ShaderSnippetData data, int currentVariantCount, double strippingTime)
  75. internal static event Action<Shader, ShaderSnippetData, int, double> shaderPreprocessed;
  76. private static readonly System.Diagnostics.Stopwatch m_stripTimer = new System.Diagnostics.Stopwatch();
  77. LocalKeyword m_MainLightShadows;
  78. LocalKeyword m_MainLightShadowsCascades;
  79. LocalKeyword m_MainLightShadowsScreen;
  80. LocalKeyword m_AdditionalLightsVertex;
  81. LocalKeyword m_AdditionalLightsPixel;
  82. LocalKeyword m_AdditionalLightShadows;
  83. LocalKeyword m_ReflectionProbeBlending;
  84. LocalKeyword m_ReflectionProbeBoxProjection;
  85. LocalKeyword m_CastingPunctualLightShadow;
  86. LocalKeyword m_SoftShadows;
  87. LocalKeyword m_MixedLightingSubtractive;
  88. LocalKeyword m_LightmapShadowMixing;
  89. LocalKeyword m_ShadowsShadowMask;
  90. LocalKeyword m_Lightmap;
  91. LocalKeyword m_DynamicLightmap;
  92. LocalKeyword m_DirectionalLightmap;
  93. LocalKeyword m_AlphaTestOn;
  94. LocalKeyword m_DeferredStencil;
  95. LocalKeyword m_GbufferNormalsOct;
  96. LocalKeyword m_UseDrawProcedural;
  97. LocalKeyword m_ScreenSpaceOcclusion;
  98. LocalKeyword m_UseFastSRGBLinearConversion;
  99. LocalKeyword m_LightLayers;
  100. LocalKeyword m_RenderPassEnabled;
  101. LocalKeyword m_DebugDisplay;
  102. LocalKeyword m_DBufferMRT1;
  103. LocalKeyword m_DBufferMRT2;
  104. LocalKeyword m_DBufferMRT3;
  105. LocalKeyword m_DecalNormalBlendLow;
  106. LocalKeyword m_DecalNormalBlendMedium;
  107. LocalKeyword m_DecalNormalBlendHigh;
  108. LocalKeyword m_ClusteredRendering;
  109. LocalKeyword m_EditorVisualization;
  110. LocalKeyword m_LocalDetailMulx2;
  111. LocalKeyword m_LocalDetailScaled;
  112. LocalKeyword m_LocalClearCoat;
  113. LocalKeyword m_LocalClearCoatMap;
  114. LocalKeyword m_LensDistortion;
  115. LocalKeyword m_ChromaticAberration;
  116. LocalKeyword m_BloomLQ;
  117. LocalKeyword m_BloomHQ;
  118. LocalKeyword m_BloomLQDirt;
  119. LocalKeyword m_BloomHQDirt;
  120. LocalKeyword m_HdrGrading;
  121. LocalKeyword m_ToneMapACES;
  122. LocalKeyword m_ToneMapNeutral;
  123. LocalKeyword m_FilmGrain;
  124. Shader m_BokehDepthOfField = Shader.Find("Hidden/Universal Render Pipeline/BokehDepthOfField");
  125. Shader m_GaussianDepthOfField = Shader.Find("Hidden/Universal Render Pipeline/GaussianDepthOfField");
  126. Shader m_CameraMotionBlur = Shader.Find("Hidden/Universal Render Pipeline/CameraMotionBlur");
  127. Shader m_PaniniProjection = Shader.Find("Hidden/Universal Render Pipeline/PaniniProjection");
  128. Shader m_Bloom = Shader.Find("Hidden/Universal Render Pipeline/Bloom");
  129. Shader StencilDeferred = Shader.Find("Hidden/Universal Render Pipeline/StencilDeferred");
  130. int m_TotalVariantsInputCount;
  131. int m_TotalVariantsOutputCount;
  132. // Multiple callback may be implemented.
  133. // The first one executed is the one where callbackOrder is returning the smallest number.
  134. public int callbackOrder { get { return 0; } }
  135. LocalKeyword TryGetLocalKeyword(Shader shader, string name)
  136. {
  137. return shader.keywordSpace.FindKeyword(name);
  138. }
  139. void InitializeLocalShaderKeywords(Shader shader)
  140. {
  141. m_MainLightShadows = TryGetLocalKeyword(shader, ShaderKeywordStrings.MainLightShadows);
  142. m_MainLightShadowsCascades = TryGetLocalKeyword(shader, ShaderKeywordStrings.MainLightShadowCascades);
  143. m_MainLightShadowsScreen = TryGetLocalKeyword(shader, ShaderKeywordStrings.MainLightShadowScreen);
  144. m_AdditionalLightsVertex = TryGetLocalKeyword(shader, ShaderKeywordStrings.AdditionalLightsVertex);
  145. m_AdditionalLightsPixel = TryGetLocalKeyword(shader, ShaderKeywordStrings.AdditionalLightsPixel);
  146. m_AdditionalLightShadows = TryGetLocalKeyword(shader, ShaderKeywordStrings.AdditionalLightShadows);
  147. m_ReflectionProbeBlending = TryGetLocalKeyword(shader, ShaderKeywordStrings.ReflectionProbeBlending);
  148. m_ReflectionProbeBoxProjection = TryGetLocalKeyword(shader, ShaderKeywordStrings.ReflectionProbeBoxProjection);
  149. m_CastingPunctualLightShadow = TryGetLocalKeyword(shader, ShaderKeywordStrings.CastingPunctualLightShadow);
  150. m_SoftShadows = TryGetLocalKeyword(shader, ShaderKeywordStrings.SoftShadows);
  151. m_MixedLightingSubtractive = TryGetLocalKeyword(shader, ShaderKeywordStrings.MixedLightingSubtractive);
  152. m_LightmapShadowMixing = TryGetLocalKeyword(shader, ShaderKeywordStrings.LightmapShadowMixing);
  153. m_ShadowsShadowMask = TryGetLocalKeyword(shader, ShaderKeywordStrings.ShadowsShadowMask);
  154. m_Lightmap = TryGetLocalKeyword(shader, ShaderKeywordStrings.LIGHTMAP_ON);
  155. m_DynamicLightmap = TryGetLocalKeyword(shader, ShaderKeywordStrings.DYNAMICLIGHTMAP_ON);
  156. m_DirectionalLightmap = TryGetLocalKeyword(shader, ShaderKeywordStrings.DIRLIGHTMAP_COMBINED);
  157. m_AlphaTestOn = TryGetLocalKeyword(shader, ShaderKeywordStrings._ALPHATEST_ON);
  158. m_DeferredStencil = TryGetLocalKeyword(shader, ShaderKeywordStrings._DEFERRED_STENCIL);
  159. m_GbufferNormalsOct = TryGetLocalKeyword(shader, ShaderKeywordStrings._GBUFFER_NORMALS_OCT);
  160. m_UseDrawProcedural = TryGetLocalKeyword(shader, ShaderKeywordStrings.UseDrawProcedural);
  161. m_ScreenSpaceOcclusion = TryGetLocalKeyword(shader, ShaderKeywordStrings.ScreenSpaceOcclusion);
  162. m_UseFastSRGBLinearConversion = TryGetLocalKeyword(shader, ShaderKeywordStrings.UseFastSRGBLinearConversion);
  163. m_LightLayers = TryGetLocalKeyword(shader, ShaderKeywordStrings.LightLayers);
  164. m_RenderPassEnabled = TryGetLocalKeyword(shader, ShaderKeywordStrings.RenderPassEnabled);
  165. m_DebugDisplay = TryGetLocalKeyword(shader, ShaderKeywordStrings.DEBUG_DISPLAY);
  166. m_DBufferMRT1 = TryGetLocalKeyword(shader, ShaderKeywordStrings.DBufferMRT1);
  167. m_DBufferMRT2 = TryGetLocalKeyword(shader, ShaderKeywordStrings.DBufferMRT2);
  168. m_DBufferMRT3 = TryGetLocalKeyword(shader, ShaderKeywordStrings.DBufferMRT3);
  169. m_DecalNormalBlendLow = TryGetLocalKeyword(shader, ShaderKeywordStrings.DecalNormalBlendLow);
  170. m_DecalNormalBlendMedium = TryGetLocalKeyword(shader, ShaderKeywordStrings.DecalNormalBlendMedium);
  171. m_DecalNormalBlendHigh = TryGetLocalKeyword(shader, ShaderKeywordStrings.DecalNormalBlendHigh);
  172. m_ClusteredRendering = TryGetLocalKeyword(shader, ShaderKeywordStrings.ClusteredRendering);
  173. m_EditorVisualization = TryGetLocalKeyword(shader, ShaderKeywordStrings.EDITOR_VISUALIZATION);
  174. m_LocalDetailMulx2 = TryGetLocalKeyword(shader, ShaderKeywordStrings._DETAIL_MULX2);
  175. m_LocalDetailScaled = TryGetLocalKeyword(shader, ShaderKeywordStrings._DETAIL_SCALED);
  176. m_LocalClearCoat = TryGetLocalKeyword(shader, ShaderKeywordStrings._CLEARCOAT);
  177. m_LocalClearCoatMap = TryGetLocalKeyword(shader, ShaderKeywordStrings._CLEARCOATMAP);
  178. // Post processing
  179. m_LensDistortion = TryGetLocalKeyword(shader, ShaderKeywordStrings.Distortion);
  180. m_ChromaticAberration = TryGetLocalKeyword(shader, ShaderKeywordStrings.ChromaticAberration);
  181. m_BloomLQ = TryGetLocalKeyword(shader, ShaderKeywordStrings.BloomLQ);
  182. m_BloomHQ = TryGetLocalKeyword(shader, ShaderKeywordStrings.BloomHQ);
  183. m_BloomLQDirt = TryGetLocalKeyword(shader, ShaderKeywordStrings.BloomLQDirt);
  184. m_BloomHQDirt = TryGetLocalKeyword(shader, ShaderKeywordStrings.BloomHQDirt);
  185. m_HdrGrading = TryGetLocalKeyword(shader, ShaderKeywordStrings.HDRGrading);
  186. m_ToneMapACES = TryGetLocalKeyword(shader, ShaderKeywordStrings.TonemapACES);
  187. m_ToneMapNeutral = TryGetLocalKeyword(shader, ShaderKeywordStrings.TonemapNeutral);
  188. m_FilmGrain = TryGetLocalKeyword(shader, ShaderKeywordStrings.FilmGrain);
  189. }
  190. bool IsFeatureEnabled(ShaderFeatures featureMask, ShaderFeatures feature)
  191. {
  192. return (featureMask & feature) != 0;
  193. }
  194. bool IsFeatureEnabled(VolumeFeatures featureMask, VolumeFeatures feature)
  195. {
  196. return (featureMask & feature) != 0;
  197. }
  198. bool StripUnusedPass(ShaderFeatures features, ShaderSnippetData snippetData)
  199. {
  200. // Meta pass is needed in the player for Enlighten Precomputed Realtime GI albedo and emission.
  201. if (snippetData.passType == PassType.Meta)
  202. {
  203. if (SupportedRenderingFeatures.active.enlighten == false ||
  204. ((int)SupportedRenderingFeatures.active.lightmapBakeTypes | (int)LightmapBakeType.Realtime) == 0)
  205. return true;
  206. }
  207. if (snippetData.passType == PassType.ShadowCaster)
  208. if (!IsFeatureEnabled(features, ShaderFeatures.MainLightShadows) && !IsFeatureEnabled(features, ShaderFeatures.AdditionalLightShadows))
  209. return true;
  210. // DBuffer
  211. if (snippetData.passName == DecalShaderPassNames.DBufferMesh || snippetData.passName == DecalShaderPassNames.DBufferProjector ||
  212. snippetData.passName == DecalShaderPassNames.DecalMeshForwardEmissive || snippetData.passName == DecalShaderPassNames.DecalProjectorForwardEmissive)
  213. if (!IsFeatureEnabled(features, ShaderFeatures.DBufferMRT1) && !IsFeatureEnabled(features, ShaderFeatures.DBufferMRT2) && !IsFeatureEnabled(features, ShaderFeatures.DBufferMRT3))
  214. return true;
  215. // Decal Screen Space
  216. if (snippetData.passName == DecalShaderPassNames.DecalScreenSpaceMesh || snippetData.passName == DecalShaderPassNames.DecalScreenSpaceProjector)
  217. if (!IsFeatureEnabled(features, ShaderFeatures.DecalScreenSpace))
  218. return true;
  219. // Decal GBuffer
  220. if (snippetData.passName == DecalShaderPassNames.DecalGBufferMesh || snippetData.passName == DecalShaderPassNames.DecalGBufferProjector)
  221. if (!IsFeatureEnabled(features, ShaderFeatures.DecalGBuffer))
  222. return true;
  223. return false;
  224. }
  225. struct StripTool<T> where T : System.Enum
  226. {
  227. T m_Features;
  228. Shader m_Shader;
  229. ShaderKeywordSet m_KeywordSet;
  230. ShaderSnippetData m_SnippetData;
  231. bool m_stripUnusedVariants;
  232. public StripTool(T features, Shader shader, ShaderSnippetData snippetData, in ShaderKeywordSet keywordSet, bool stripUnusedVariants)
  233. {
  234. m_Features = features;
  235. m_Shader = shader;
  236. m_SnippetData = snippetData;
  237. m_KeywordSet = keywordSet;
  238. m_stripUnusedVariants = stripUnusedVariants;
  239. }
  240. bool ContainsKeyword(in LocalKeyword kw)
  241. {
  242. return ShaderUtil.PassHasKeyword(m_Shader, m_SnippetData.pass, kw, m_SnippetData.shaderType);
  243. }
  244. public bool StripMultiCompileKeepOffVariant(in LocalKeyword kw, T feature, in LocalKeyword kw2, T feature2, in LocalKeyword kw3, T feature3)
  245. {
  246. if (StripMultiCompileKeepOffVariant(kw, feature))
  247. return true;
  248. if (StripMultiCompileKeepOffVariant(kw2, feature2))
  249. return true;
  250. if (StripMultiCompileKeepOffVariant(kw3, feature3))
  251. return true;
  252. return false;
  253. }
  254. public bool StripMultiCompile(in LocalKeyword kw, T feature, in LocalKeyword kw2, T feature2, in LocalKeyword kw3, T feature3)
  255. {
  256. if (StripMultiCompileKeepOffVariant(kw, feature, kw2, feature2, kw3, feature3))
  257. return true;
  258. bool containsKeywords = ContainsKeyword(kw) && ContainsKeyword(kw2) && ContainsKeyword(kw3);
  259. bool keywordsDisabled = !m_KeywordSet.IsEnabled(kw) && !m_KeywordSet.IsEnabled(kw2) && !m_KeywordSet.IsEnabled(kw3);
  260. bool hasAnyFeatureEnabled = m_Features.HasFlag(feature) || m_Features.HasFlag(feature2) || m_Features.HasFlag(feature3);
  261. if (m_stripUnusedVariants && containsKeywords && keywordsDisabled && hasAnyFeatureEnabled)
  262. return true;
  263. return false;
  264. }
  265. public bool StripMultiCompileKeepOffVariant(in LocalKeyword kw, T feature, in LocalKeyword kw2, T feature2)
  266. {
  267. if (StripMultiCompileKeepOffVariant(kw, feature))
  268. return true;
  269. if (StripMultiCompileKeepOffVariant(kw2, feature2))
  270. return true;
  271. return false;
  272. }
  273. public bool StripMultiCompile(in LocalKeyword kw, T feature, in LocalKeyword kw2, T feature2)
  274. {
  275. if (StripMultiCompileKeepOffVariant(kw, feature, kw2, feature2))
  276. return true;
  277. bool containsKeywords = ContainsKeyword(kw) && ContainsKeyword(kw2);
  278. bool keywordsDisabled = !m_KeywordSet.IsEnabled(kw) && !m_KeywordSet.IsEnabled(kw2);
  279. bool hasAnyFeatureEnabled = m_Features.HasFlag(feature) || m_Features.HasFlag(feature2);
  280. if (m_stripUnusedVariants && containsKeywords && keywordsDisabled && hasAnyFeatureEnabled)
  281. return true;
  282. return false;
  283. }
  284. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  285. public bool StripMultiCompileKeepOffVariant(in LocalKeyword kw, T feature)
  286. {
  287. return !m_Features.HasFlag(feature) && m_KeywordSet.IsEnabled(kw);
  288. }
  289. public bool StripMultiCompile(in LocalKeyword kw, T feature)
  290. {
  291. if (!m_Features.HasFlag(feature))
  292. {
  293. if (m_KeywordSet.IsEnabled(kw))
  294. return true;
  295. }
  296. else if (m_stripUnusedVariants)
  297. {
  298. if (!m_KeywordSet.IsEnabled(kw) && ContainsKeyword(kw))
  299. return true;
  300. }
  301. return false;
  302. }
  303. }
  304. bool StripUnusedFeatures(ShaderFeatures features, Shader shader, ShaderSnippetData snippetData, ShaderCompilerData compilerData)
  305. {
  306. var globalSettings = UniversalRenderPipelineGlobalSettings.instance;
  307. bool stripDebugDisplayShaders = !Debug.isDebugBuild || (globalSettings == null || globalSettings.stripDebugVariants);
  308. #if XR_MANAGEMENT_4_0_1_OR_NEWER
  309. var buildTargetSettings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(BuildTargetGroup.Standalone);
  310. if (buildTargetSettings != null && buildTargetSettings.AssignedSettings != null && buildTargetSettings.AssignedSettings.activeLoaders.Count > 0)
  311. {
  312. stripDebugDisplayShaders = true;
  313. }
  314. #endif
  315. if (stripDebugDisplayShaders && compilerData.shaderKeywordSet.IsEnabled(m_DebugDisplay))
  316. {
  317. return true;
  318. }
  319. var stripUnusedVariants = UniversalRenderPipelineGlobalSettings.instance?.stripUnusedVariants == true;
  320. var stripTool = new StripTool<ShaderFeatures>(features, shader, snippetData, compilerData.shaderKeywordSet, stripUnusedVariants);
  321. // strip main light shadows, cascade and screen variants
  322. if (IsFeatureEnabled(ShaderFeatures.ShadowsKeepOffVariants, features))
  323. {
  324. if (stripTool.StripMultiCompileKeepOffVariant(
  325. m_MainLightShadows, ShaderFeatures.MainLightShadows,
  326. m_MainLightShadowsCascades, ShaderFeatures.MainLightShadowsCascade,
  327. m_MainLightShadowsScreen, ShaderFeatures.ScreenSpaceShadows))
  328. return true;
  329. }
  330. else
  331. {
  332. if (stripTool.StripMultiCompile(
  333. m_MainLightShadows, ShaderFeatures.MainLightShadows,
  334. m_MainLightShadowsCascades, ShaderFeatures.MainLightShadowsCascade,
  335. m_MainLightShadowsScreen, ShaderFeatures.ScreenSpaceShadows))
  336. return true;
  337. }
  338. // TODO: Strip off variants once we have global soft shadows option for forcing instead as support
  339. if (stripTool.StripMultiCompileKeepOffVariant(m_SoftShadows, ShaderFeatures.SoftShadows))
  340. return true;
  341. // Left for backward compatibility
  342. if (compilerData.shaderKeywordSet.IsEnabled(m_MixedLightingSubtractive) &&
  343. !IsFeatureEnabled(features, ShaderFeatures.MixedLighting))
  344. return true;
  345. if (stripTool.StripMultiCompile(m_UseFastSRGBLinearConversion, ShaderFeatures.UseFastSRGBLinearConversion))
  346. return true;
  347. // Strip here only if mixed lighting is disabled
  348. // No need to check here if actually used by scenes as this taken care by builtin stripper
  349. if ((compilerData.shaderKeywordSet.IsEnabled(m_LightmapShadowMixing) ||
  350. compilerData.shaderKeywordSet.IsEnabled(m_ShadowsShadowMask)) &&
  351. !IsFeatureEnabled(features, ShaderFeatures.MixedLighting))
  352. return true;
  353. if (compilerData.shaderCompilerPlatform == ShaderCompilerPlatform.GLES20)
  354. {
  355. // GLES2 does not support bitwise operations.
  356. if (compilerData.shaderKeywordSet.IsEnabled(m_LightLayers))
  357. return true;
  358. }
  359. else
  360. {
  361. if (stripTool.StripMultiCompile(m_LightLayers, ShaderFeatures.LightLayers))
  362. return true;
  363. }
  364. if (stripTool.StripMultiCompile(m_RenderPassEnabled, ShaderFeatures.RenderPassEnabled))
  365. return true;
  366. // No additional light shadows
  367. if (IsFeatureEnabled(ShaderFeatures.ShadowsKeepOffVariants, features))
  368. {
  369. if (stripTool.StripMultiCompileKeepOffVariant(m_AdditionalLightShadows, ShaderFeatures.AdditionalLightShadows))
  370. return true;
  371. }
  372. else
  373. {
  374. if (stripTool.StripMultiCompile(m_AdditionalLightShadows, ShaderFeatures.AdditionalLightShadows))
  375. return true;
  376. }
  377. if (stripTool.StripMultiCompile(m_ReflectionProbeBlending, ShaderFeatures.ReflectionProbeBlending))
  378. return true;
  379. if (stripTool.StripMultiCompile(m_ReflectionProbeBoxProjection, ShaderFeatures.ReflectionProbeBoxProjection))
  380. return true;
  381. // Shadow caster punctual light strip
  382. if (snippetData.passType == PassType.ShadowCaster && ShaderUtil.PassHasKeyword(shader, snippetData.pass, m_CastingPunctualLightShadow, snippetData.shaderType))
  383. {
  384. if (!IsFeatureEnabled(features, ShaderFeatures.AdditionalLightShadows) && compilerData.shaderKeywordSet.IsEnabled(m_CastingPunctualLightShadow))
  385. return true;
  386. bool mainLightShadows =
  387. !IsFeatureEnabled(features, ShaderFeatures.MainLightShadows) &&
  388. !IsFeatureEnabled(features, ShaderFeatures.MainLightShadowsCascade) &&
  389. !IsFeatureEnabled(features, ShaderFeatures.ScreenSpaceShadows);
  390. if (mainLightShadows && !compilerData.shaderKeywordSet.IsEnabled(m_CastingPunctualLightShadow))
  391. return true;
  392. }
  393. // Additional light are shaded per-vertex or per-pixel.
  394. if (IsFeatureEnabled(ShaderFeatures.AdditionalLightsKeepOffVariants, features))
  395. {
  396. if (stripTool.StripMultiCompileKeepOffVariant(m_AdditionalLightsVertex, ShaderFeatures.VertexLighting,
  397. m_AdditionalLightsPixel, ShaderFeatures.AdditionalLights))
  398. return true;
  399. }
  400. else
  401. {
  402. if (stripTool.StripMultiCompile(m_AdditionalLightsVertex, ShaderFeatures.VertexLighting,
  403. m_AdditionalLightsPixel, ShaderFeatures.AdditionalLights))
  404. return true;
  405. }
  406. if (stripTool.StripMultiCompile(m_ClusteredRendering, ShaderFeatures.ClusteredRendering))
  407. return true;
  408. // Screen Space Occlusion
  409. if (IsFeatureEnabled(features, ShaderFeatures.ScreenSpaceOcclusionAfterOpaque))
  410. {
  411. // SSAO after opaque setting requires off variants
  412. if (stripTool.StripMultiCompileKeepOffVariant(m_ScreenSpaceOcclusion, ShaderFeatures.ScreenSpaceOcclusion))
  413. return true;
  414. }
  415. else
  416. {
  417. if (stripTool.StripMultiCompile(m_ScreenSpaceOcclusion, ShaderFeatures.ScreenSpaceOcclusion))
  418. return true;
  419. }
  420. // Decal DBuffer
  421. if (stripTool.StripMultiCompile(
  422. m_DBufferMRT1, ShaderFeatures.DBufferMRT1,
  423. m_DBufferMRT2, ShaderFeatures.DBufferMRT2,
  424. m_DBufferMRT3, ShaderFeatures.DBufferMRT3))
  425. return true;
  426. // TODO: Test against lightMode tag instead.
  427. if (snippetData.passName == kPassNameGBuffer)
  428. {
  429. if (!IsFeatureEnabled(features, ShaderFeatures.DeferredShading))
  430. return true;
  431. }
  432. // Do not strip accurateGbufferNormals on Mobile Vulkan as some GPUs do not support R8G8B8A8_SNorm, which then force us to use accurateGbufferNormals
  433. if (compilerData.shaderCompilerPlatform != ShaderCompilerPlatform.Vulkan &&
  434. stripTool.StripMultiCompile(m_GbufferNormalsOct, ShaderFeatures.AccurateGbufferNormals))
  435. return true;
  436. if (compilerData.shaderKeywordSet.IsEnabled(m_UseDrawProcedural) &&
  437. !IsFeatureEnabled(features, ShaderFeatures.DrawProcedural))
  438. return true;
  439. // Decal Normal Blend
  440. if (stripTool.StripMultiCompile(
  441. m_DecalNormalBlendLow, ShaderFeatures.DecalNormalBlendLow,
  442. m_DecalNormalBlendMedium, ShaderFeatures.DecalNormalBlendMedium,
  443. m_DecalNormalBlendHigh, ShaderFeatures.DecalNormalBlendHigh))
  444. return true;
  445. return false;
  446. }
  447. bool StripVolumeFeatures(VolumeFeatures features, Shader shader, ShaderSnippetData snippetData, ShaderCompilerData compilerData)
  448. {
  449. var stripUnusedVariants = UniversalRenderPipelineGlobalSettings.instance?.stripUnusedVariants == true;
  450. var stripTool = new StripTool<VolumeFeatures>(features, shader, snippetData, compilerData.shaderKeywordSet, stripUnusedVariants);
  451. if (stripTool.StripMultiCompileKeepOffVariant(m_LensDistortion, VolumeFeatures.LensDistortion))
  452. return true;
  453. if (stripTool.StripMultiCompileKeepOffVariant(m_ChromaticAberration, VolumeFeatures.ChromaticAberration))
  454. return true;
  455. if (stripTool.StripMultiCompileKeepOffVariant(m_BloomLQ, VolumeFeatures.Bloom))
  456. return true;
  457. if (stripTool.StripMultiCompileKeepOffVariant(m_BloomHQ, VolumeFeatures.Bloom))
  458. return true;
  459. if (stripTool.StripMultiCompileKeepOffVariant(m_BloomLQDirt, VolumeFeatures.Bloom))
  460. return true;
  461. if (stripTool.StripMultiCompileKeepOffVariant(m_BloomHQDirt, VolumeFeatures.Bloom))
  462. return true;
  463. if (stripTool.StripMultiCompileKeepOffVariant(m_HdrGrading, VolumeFeatures.ToneMaping))
  464. return true;
  465. if (stripTool.StripMultiCompileKeepOffVariant(m_ToneMapACES, VolumeFeatures.ToneMaping))
  466. return true;
  467. if (stripTool.StripMultiCompileKeepOffVariant(m_ToneMapNeutral, VolumeFeatures.ToneMaping))
  468. return true;
  469. if (stripTool.StripMultiCompileKeepOffVariant(m_FilmGrain, VolumeFeatures.FilmGrain))
  470. return true;
  471. // Strip post processing shaders
  472. if (shader == m_BokehDepthOfField && !IsFeatureEnabled(ShaderBuildPreprocessor.volumeFeatures, VolumeFeatures.DepthOfField))
  473. return true;
  474. if (shader == m_GaussianDepthOfField && !IsFeatureEnabled(ShaderBuildPreprocessor.volumeFeatures, VolumeFeatures.DepthOfField))
  475. return true;
  476. if (shader == m_CameraMotionBlur && !IsFeatureEnabled(ShaderBuildPreprocessor.volumeFeatures, VolumeFeatures.CameraMotionBlur))
  477. return true;
  478. if (shader == m_PaniniProjection && !IsFeatureEnabled(ShaderBuildPreprocessor.volumeFeatures, VolumeFeatures.PaniniProjection))
  479. return true;
  480. if (shader == m_Bloom && !IsFeatureEnabled(ShaderBuildPreprocessor.volumeFeatures, VolumeFeatures.Bloom))
  481. return true;
  482. return false;
  483. }
  484. bool StripUnsupportedVariants(ShaderCompilerData compilerData)
  485. {
  486. // We can strip variants that have directional lightmap enabled but not static nor dynamic lightmap.
  487. if (compilerData.shaderKeywordSet.IsEnabled(m_DirectionalLightmap) &&
  488. !(compilerData.shaderKeywordSet.IsEnabled(m_Lightmap) ||
  489. compilerData.shaderKeywordSet.IsEnabled(m_DynamicLightmap)))
  490. return true;
  491. // As GLES2 has low amount of registers, we strip:
  492. if (compilerData.shaderCompilerPlatform == ShaderCompilerPlatform.GLES20)
  493. {
  494. // VertexID - as GLES2 does not support VertexID that is required for full screen draw procedural pass;
  495. if (compilerData.shaderKeywordSet.IsEnabled(m_UseDrawProcedural))
  496. return true;
  497. // Cascade shadows
  498. if (compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsCascades))
  499. return true;
  500. // Screen space shadows
  501. if (compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsScreen))
  502. return true;
  503. // Detail
  504. if (compilerData.shaderKeywordSet.IsEnabled(m_LocalDetailMulx2) || compilerData.shaderKeywordSet.IsEnabled(m_LocalDetailScaled))
  505. return true;
  506. // Clear Coat
  507. if (compilerData.shaderKeywordSet.IsEnabled(m_LocalClearCoat) || compilerData.shaderKeywordSet.IsEnabled(m_LocalClearCoatMap))
  508. return true;
  509. }
  510. // Editor visualization is only used in scene view debug modes.
  511. if (compilerData.shaderKeywordSet.IsEnabled(m_EditorVisualization))
  512. return true;
  513. return false;
  514. }
  515. bool StripInvalidVariants(ShaderCompilerData compilerData)
  516. {
  517. bool isMainShadowNoCascades = compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadows);
  518. bool isMainShadowCascades = compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsCascades);
  519. bool isMainShadowScreen = compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsScreen);
  520. bool isMainShadow = isMainShadowNoCascades || isMainShadowCascades || isMainShadowScreen;
  521. bool isAdditionalShadow = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightShadows);
  522. if (isAdditionalShadow && !(compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightsPixel) || compilerData.shaderKeywordSet.IsEnabled(m_ClusteredRendering) || compilerData.shaderKeywordSet.IsEnabled(m_DeferredStencil)))
  523. return true;
  524. bool isShadowVariant = isMainShadow || isAdditionalShadow;
  525. if (!isShadowVariant && compilerData.shaderKeywordSet.IsEnabled(m_SoftShadows))
  526. return true;
  527. return false;
  528. }
  529. bool StripUnusedShaders(ShaderFeatures features, Shader shader)
  530. {
  531. if (!IsFeatureEnabled(features, ShaderFeatures.DeferredShading))
  532. {
  533. if (shader == StencilDeferred)
  534. return true;
  535. }
  536. return false;
  537. }
  538. bool StripUnused(ShaderFeatures features, Shader shader, ShaderSnippetData snippetData, ShaderCompilerData compilerData)
  539. {
  540. if (StripUnusedFeatures(features, shader, snippetData, compilerData))
  541. return true;
  542. if (StripInvalidVariants(compilerData))
  543. return true;
  544. if (StripUnsupportedVariants(compilerData))
  545. return true;
  546. if (StripUnusedPass(features, snippetData))
  547. return true;
  548. if (UniversalRenderPipelineGlobalSettings.instance?.stripUnusedVariants == true)
  549. {
  550. if (StripUnusedShaders(features, shader))
  551. return true;
  552. }
  553. // Strip terrain holes
  554. // TODO: checking for the string name here is expensive
  555. // maybe we can rename alpha clip keyword name to be specific to terrain?
  556. if (compilerData.shaderKeywordSet.IsEnabled(m_AlphaTestOn) &&
  557. !IsFeatureEnabled(features, ShaderFeatures.TerrainHoles) &&
  558. shader.name.Contains(kTerrainShaderName))
  559. return true;
  560. return false;
  561. }
  562. void LogShaderVariants(Shader shader, ShaderSnippetData snippetData, ShaderVariantLogLevel logLevel, int prevVariantsCount, int currVariantsCount, double stripTimeMs)
  563. {
  564. if (logLevel == ShaderVariantLogLevel.AllShaders || shader.name.Contains("Universal Render Pipeline"))
  565. {
  566. float percentageCurrent = (float)currVariantsCount / (float)prevVariantsCount * 100f;
  567. float percentageTotal = (float)m_TotalVariantsOutputCount / (float)m_TotalVariantsInputCount * 100f;
  568. string result = string.Format("STRIPPING: {0} ({1} pass) ({2}) -" +
  569. " Remaining shader variants = {3}/{4} = {5}% - Total = {6}/{7} = {8}% TimeMs={9}",
  570. shader.name, snippetData.passName, snippetData.shaderType.ToString(), currVariantsCount,
  571. prevVariantsCount, percentageCurrent, m_TotalVariantsOutputCount, m_TotalVariantsInputCount,
  572. percentageTotal, stripTimeMs);
  573. Debug.Log(result);
  574. }
  575. }
  576. public void OnProcessShader(Shader shader, ShaderSnippetData snippetData, IList<ShaderCompilerData> compilerDataList)
  577. {
  578. #if PROFILE_BUILD
  579. Profiler.BeginSample(k_ProcessShaderTag);
  580. #endif
  581. UniversalRenderPipelineAsset urpAsset = UniversalRenderPipeline.asset;
  582. if (urpAsset == null || compilerDataList == null || compilerDataList.Count == 0)
  583. return;
  584. m_stripTimer.Start();
  585. InitializeLocalShaderKeywords(shader);
  586. int prevVariantCount = compilerDataList.Count;
  587. var inputShaderVariantCount = compilerDataList.Count;
  588. for (int i = 0; i < inputShaderVariantCount;)
  589. {
  590. bool removeInput = true;
  591. foreach (var supportedFeatures in ShaderBuildPreprocessor.supportedFeaturesList)
  592. {
  593. if (!StripUnused(supportedFeatures, shader, snippetData, compilerDataList[i]))
  594. {
  595. removeInput = false;
  596. break;
  597. }
  598. }
  599. if (UniversalRenderPipelineGlobalSettings.instance?.stripUnusedPostProcessingVariants == true)
  600. {
  601. if (!removeInput && StripVolumeFeatures(ShaderBuildPreprocessor.volumeFeatures, shader, snippetData, compilerDataList[i]))
  602. {
  603. removeInput = true;
  604. }
  605. }
  606. // Remove at swap back
  607. if (removeInput)
  608. compilerDataList[i] = compilerDataList[--inputShaderVariantCount];
  609. else
  610. ++i;
  611. }
  612. if (compilerDataList is List<ShaderCompilerData> inputDataList)
  613. inputDataList.RemoveRange(inputShaderVariantCount, inputDataList.Count - inputShaderVariantCount);
  614. else
  615. {
  616. for (int i = compilerDataList.Count - 1; i >= inputShaderVariantCount; --i)
  617. compilerDataList.RemoveAt(i);
  618. }
  619. m_stripTimer.Stop();
  620. double stripTimeMs = m_stripTimer.Elapsed.TotalMilliseconds;
  621. m_stripTimer.Reset();
  622. if (urpAsset.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled)
  623. {
  624. m_TotalVariantsInputCount += prevVariantCount;
  625. m_TotalVariantsOutputCount += compilerDataList.Count;
  626. LogShaderVariants(shader, snippetData, urpAsset.shaderVariantLogLevel, prevVariantCount, compilerDataList.Count, stripTimeMs);
  627. }
  628. #if PROFILE_BUILD
  629. Profiler.EndSample();
  630. #endif
  631. shaderPreprocessed?.Invoke(shader, snippetData, prevVariantCount, stripTimeMs);
  632. }
  633. }
  634. class ShaderBuildPreprocessor : IPreprocessBuildWithReport
  635. #if PROFILE_BUILD
  636. , IPostprocessBuildWithReport
  637. #endif
  638. {
  639. public static List<ShaderFeatures> supportedFeaturesList
  640. {
  641. get
  642. {
  643. if (s_SupportedFeaturesList.Count == 0)
  644. FetchAllSupportedFeatures();
  645. return s_SupportedFeaturesList;
  646. }
  647. }
  648. private static List<ShaderFeatures> s_SupportedFeaturesList = new List<ShaderFeatures>();
  649. public static VolumeFeatures volumeFeatures
  650. {
  651. get
  652. {
  653. if (s_VolumeFeatures == VolumeFeatures.None)
  654. FetchAllSupportedFeaturesFromVolumes();
  655. return s_VolumeFeatures;
  656. }
  657. }
  658. private static VolumeFeatures s_VolumeFeatures;
  659. public int callbackOrder { get { return 0; } }
  660. #if PROFILE_BUILD
  661. public void OnPostprocessBuild(BuildReport report)
  662. {
  663. Profiler.enabled = false;
  664. }
  665. #endif
  666. public void OnPreprocessBuild(BuildReport report)
  667. {
  668. FetchAllSupportedFeatures();
  669. FetchAllSupportedFeaturesFromVolumes();
  670. #if PROFILE_BUILD
  671. Profiler.enableBinaryLog = true;
  672. Profiler.logFile = "profilerlog.raw";
  673. Profiler.enabled = true;
  674. #endif
  675. }
  676. static bool TryGetRenderPipelineAssetsForBuildTarget(BuildTarget buildTarget, List<UniversalRenderPipelineAsset> urps)
  677. {
  678. var qualitySettings = new SerializedObject(QualitySettings.GetQualitySettings());
  679. if (qualitySettings == null)
  680. return false;
  681. var property = qualitySettings.FindProperty("m_QualitySettings");
  682. if (property == null)
  683. return false;
  684. var activeBuildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget);
  685. var activeBuildTargetGroupName = activeBuildTargetGroup.ToString();
  686. for (int i = 0; i < property.arraySize; i++)
  687. {
  688. bool isExcluded = false;
  689. var excludedTargetPlatforms = property.GetArrayElementAtIndex(i).FindPropertyRelative("excludedTargetPlatforms");
  690. if (excludedTargetPlatforms == null)
  691. return false;
  692. foreach (SerializedProperty excludedTargetPlatform in excludedTargetPlatforms)
  693. {
  694. var excludedBuildTargetGroupName = excludedTargetPlatform.stringValue;
  695. if (activeBuildTargetGroupName == excludedBuildTargetGroupName)
  696. {
  697. Debug.Log($"Excluding quality level {QualitySettings.names[i]} from stripping."); // TODO: remove after QA
  698. isExcluded = true;
  699. break;
  700. }
  701. }
  702. if (!isExcluded)
  703. urps.Add(QualitySettings.GetRenderPipelineAssetAt(i) as UniversalRenderPipelineAsset);
  704. }
  705. return true;
  706. }
  707. private static void FetchAllSupportedFeatures()
  708. {
  709. List<UniversalRenderPipelineAsset> urps = new List<UniversalRenderPipelineAsset>();
  710. urps.Add(GraphicsSettings.defaultRenderPipeline as UniversalRenderPipelineAsset);
  711. // TODO: Replace once we have official API for filtering urps per build target
  712. if (!TryGetRenderPipelineAssetsForBuildTarget(EditorUserBuildSettings.activeBuildTarget, urps))
  713. {
  714. // Fallback
  715. Debug.LogWarning("Shader stripping per enabled quality levels failed! Stripping will use all quality levels. Please report a bug!");
  716. for (int i = 0; i < QualitySettings.names.Length; i++)
  717. {
  718. urps.Add(QualitySettings.GetRenderPipelineAssetAt(i) as UniversalRenderPipelineAsset);
  719. }
  720. }
  721. s_SupportedFeaturesList.Clear();
  722. foreach (UniversalRenderPipelineAsset urp in urps)
  723. {
  724. if (urp != null)
  725. {
  726. int rendererCount = urp.m_RendererDataList.Length;
  727. for (int i = 0; i < rendererCount; ++i)
  728. s_SupportedFeaturesList.Add(GetSupportedShaderFeatures(urp, i));
  729. }
  730. }
  731. }
  732. private static void FetchAllSupportedFeaturesFromVolumes()
  733. {
  734. if (UniversalRenderPipelineGlobalSettings.instance?.stripUnusedPostProcessingVariants == false)
  735. return;
  736. s_VolumeFeatures = VolumeFeatures.Calculated;
  737. var guids = AssetDatabase.FindAssets("t:VolumeProfile");
  738. foreach (var guid in guids)
  739. {
  740. var path = AssetDatabase.GUIDToAssetPath(guid);
  741. // We only care what is in assets folder
  742. if (!path.StartsWith("Assets"))
  743. continue;
  744. var asset = AssetDatabase.LoadAssetAtPath<VolumeProfile>(path);
  745. if (asset == null)
  746. continue;
  747. if (asset.Has<LensDistortion>())
  748. s_VolumeFeatures |= VolumeFeatures.LensDistortion;
  749. if (asset.Has<Bloom>())
  750. s_VolumeFeatures |= VolumeFeatures.Bloom;
  751. if (asset.Has<Tonemapping>())
  752. s_VolumeFeatures |= VolumeFeatures.ToneMaping;
  753. if (asset.Has<FilmGrain>())
  754. s_VolumeFeatures |= VolumeFeatures.FilmGrain;
  755. if (asset.Has<DepthOfField>())
  756. s_VolumeFeatures |= VolumeFeatures.DepthOfField;
  757. if (asset.Has<MotionBlur>())
  758. s_VolumeFeatures |= VolumeFeatures.CameraMotionBlur;
  759. if (asset.Has<PaniniProjection>())
  760. s_VolumeFeatures |= VolumeFeatures.PaniniProjection;
  761. if (asset.Has<ChromaticAberration>())
  762. s_VolumeFeatures |= VolumeFeatures.ChromaticAberration;
  763. }
  764. }
  765. private static ShaderFeatures GetSupportedShaderFeatures(UniversalRenderPipelineAsset pipelineAsset, int rendererIndex)
  766. {
  767. ShaderFeatures shaderFeatures;
  768. shaderFeatures = ShaderFeatures.MainLight;
  769. if (pipelineAsset.supportsMainLightShadows)
  770. {
  771. // User can change cascade count at runtime, so we have to include both of them for now
  772. shaderFeatures |= ShaderFeatures.MainLightShadows;
  773. shaderFeatures |= ShaderFeatures.MainLightShadowsCascade;
  774. }
  775. if (pipelineAsset.additionalLightsRenderingMode == LightRenderingMode.PerVertex)
  776. {
  777. shaderFeatures |= ShaderFeatures.VertexLighting;
  778. }
  779. else if (pipelineAsset.additionalLightsRenderingMode == LightRenderingMode.PerPixel)
  780. {
  781. shaderFeatures |= ShaderFeatures.AdditionalLights;
  782. }
  783. bool anyShadows = pipelineAsset.supportsMainLightShadows ||
  784. (shaderFeatures & ShaderFeatures.AdditionalLightShadows) != 0;
  785. if (pipelineAsset.supportsSoftShadows && anyShadows)
  786. shaderFeatures |= ShaderFeatures.SoftShadows;
  787. if (pipelineAsset.supportsMixedLighting)
  788. shaderFeatures |= ShaderFeatures.MixedLighting;
  789. if (pipelineAsset.supportsTerrainHoles)
  790. shaderFeatures |= ShaderFeatures.TerrainHoles;
  791. if (pipelineAsset.useFastSRGBLinearConversion)
  792. shaderFeatures |= ShaderFeatures.UseFastSRGBLinearConversion;
  793. if (pipelineAsset.supportsLightLayers)
  794. shaderFeatures |= ShaderFeatures.LightLayers;
  795. bool hasScreenSpaceShadows = false;
  796. bool hasScreenSpaceOcclusion = false;
  797. bool hasDeferredRenderer = false;
  798. bool accurateGbufferNormals = false;
  799. bool clusteredRendering = false;
  800. bool onlyClusteredRendering = false;
  801. bool usesRenderPass = false;
  802. {
  803. ScriptableRenderer renderer = pipelineAsset.GetRenderer(rendererIndex);
  804. if (renderer is UniversalRenderer)
  805. {
  806. UniversalRenderer universalRenderer = (UniversalRenderer)renderer;
  807. if (universalRenderer.renderingMode == RenderingMode.Deferred)
  808. {
  809. hasDeferredRenderer |= true;
  810. accurateGbufferNormals |= universalRenderer.accurateGbufferNormals;
  811. usesRenderPass |= universalRenderer.useRenderPassEnabled;
  812. }
  813. }
  814. if (!renderer.stripShadowsOffVariants)
  815. shaderFeatures |= ShaderFeatures.ShadowsKeepOffVariants;
  816. if (!renderer.stripAdditionalLightOffVariants)
  817. shaderFeatures |= ShaderFeatures.AdditionalLightsKeepOffVariants;
  818. var rendererClustered = false;
  819. ScriptableRendererData rendererData = pipelineAsset.m_RendererDataList[rendererIndex];
  820. if (rendererData != null)
  821. {
  822. for (int rendererFeatureIndex = 0; rendererFeatureIndex < rendererData.rendererFeatures.Count; rendererFeatureIndex++)
  823. {
  824. ScriptableRendererFeature rendererFeature = rendererData.rendererFeatures[rendererFeatureIndex];
  825. ScreenSpaceShadows ssshadows = rendererFeature as ScreenSpaceShadows;
  826. hasScreenSpaceShadows |= ssshadows != null;
  827. // Check for Screen Space Ambient Occlusion Renderer Feature
  828. ScreenSpaceAmbientOcclusion ssao = rendererFeature as ScreenSpaceAmbientOcclusion;
  829. hasScreenSpaceOcclusion |= ssao != null;
  830. if (ssao?.afterOpaque ?? false)
  831. shaderFeatures |= ShaderFeatures.ScreenSpaceOcclusionAfterOpaque;
  832. // Check for Decal Renderer Feature
  833. DecalRendererFeature decal = rendererFeature as DecalRendererFeature;
  834. if (decal != null)
  835. {
  836. var technique = decal.GetTechnique(renderer);
  837. switch (technique)
  838. {
  839. case DecalTechnique.DBuffer:
  840. shaderFeatures |= GetFromDecalSurfaceData(decal.GetDBufferSettings().surfaceData);
  841. break;
  842. case DecalTechnique.ScreenSpace:
  843. shaderFeatures |= GetFromNormalBlend(decal.GetScreenSpaceSettings().normalBlend);
  844. shaderFeatures |= ShaderFeatures.DecalScreenSpace;
  845. break;
  846. case DecalTechnique.GBuffer:
  847. shaderFeatures |= GetFromNormalBlend(decal.GetScreenSpaceSettings().normalBlend);
  848. shaderFeatures |= ShaderFeatures.DecalGBuffer;
  849. break;
  850. }
  851. }
  852. }
  853. if (rendererData is UniversalRendererData universalRendererData)
  854. {
  855. rendererClustered = universalRendererData.renderingMode == RenderingMode.Forward &&
  856. universalRendererData.clusteredRendering;
  857. #if ENABLE_VR && ENABLE_XR_MODULE
  858. if (universalRendererData.xrSystemData != null)
  859. shaderFeatures |= ShaderFeatures.DrawProcedural;
  860. #endif
  861. }
  862. }
  863. clusteredRendering |= rendererClustered;
  864. onlyClusteredRendering &= rendererClustered;
  865. }
  866. if (hasDeferredRenderer)
  867. shaderFeatures |= ShaderFeatures.DeferredShading;
  868. if (accurateGbufferNormals)
  869. shaderFeatures |= ShaderFeatures.AccurateGbufferNormals;
  870. if (hasScreenSpaceShadows)
  871. shaderFeatures |= ShaderFeatures.ScreenSpaceShadows;
  872. if (hasScreenSpaceOcclusion)
  873. shaderFeatures |= ShaderFeatures.ScreenSpaceOcclusion;
  874. if (usesRenderPass)
  875. shaderFeatures |= ShaderFeatures.RenderPassEnabled;
  876. if (pipelineAsset.reflectionProbeBlending)
  877. shaderFeatures |= ShaderFeatures.ReflectionProbeBlending;
  878. if (pipelineAsset.reflectionProbeBoxProjection)
  879. shaderFeatures |= ShaderFeatures.ReflectionProbeBoxProjection;
  880. if (clusteredRendering)
  881. {
  882. shaderFeatures |= ShaderFeatures.ClusteredRendering;
  883. }
  884. if (onlyClusteredRendering)
  885. {
  886. shaderFeatures &= ~(ShaderFeatures.AdditionalLights | ShaderFeatures.VertexLighting);
  887. }
  888. if (pipelineAsset.additionalLightsRenderingMode == LightRenderingMode.PerPixel || clusteredRendering)
  889. {
  890. if (pipelineAsset.supportsAdditionalLightShadows)
  891. {
  892. shaderFeatures |= ShaderFeatures.AdditionalLightShadows;
  893. }
  894. }
  895. return shaderFeatures;
  896. }
  897. private static ShaderFeatures GetFromDecalSurfaceData(DecalSurfaceData surfaceData)
  898. {
  899. ShaderFeatures shaderFeatures = ShaderFeatures.None;
  900. switch (surfaceData)
  901. {
  902. case DecalSurfaceData.Albedo:
  903. shaderFeatures |= ShaderFeatures.DBufferMRT1;
  904. break;
  905. case DecalSurfaceData.AlbedoNormal:
  906. shaderFeatures |= ShaderFeatures.DBufferMRT2;
  907. break;
  908. case DecalSurfaceData.AlbedoNormalMAOS:
  909. shaderFeatures |= ShaderFeatures.DBufferMRT3;
  910. break;
  911. }
  912. return shaderFeatures;
  913. }
  914. private static ShaderFeatures GetFromNormalBlend(DecalNormalBlend normalBlend)
  915. {
  916. ShaderFeatures shaderFeatures = ShaderFeatures.None;
  917. switch (normalBlend)
  918. {
  919. case DecalNormalBlend.Low:
  920. shaderFeatures |= ShaderFeatures.DecalNormalBlendLow;
  921. break;
  922. case DecalNormalBlend.Medium:
  923. shaderFeatures |= ShaderFeatures.DecalNormalBlendMedium;
  924. break;
  925. case DecalNormalBlend.High:
  926. shaderFeatures |= ShaderFeatures.DecalNormalBlendHigh;
  927. break;
  928. }
  929. return shaderFeatures;
  930. }
  931. }
  932. }