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

ShaderBuildPreprocessor.cs 49KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor.Build;
  4. using UnityEditor.Build.Reporting;
  5. using UnityEngine;
  6. using UnityEngine.Rendering.Universal;
  7. using UnityEngine.Rendering;
  8. #if XR_MANAGEMENT_4_0_1_OR_NEWER
  9. using UnityEditor.XR.Management;
  10. using UnityEngine.XR.Management;
  11. #endif
  12. using ShaderPrefilteringData = UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.ShaderPrefilteringData;
  13. using PrefilteringMode = UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.PrefilteringMode;
  14. using PrefilteringModeMainLightShadows = UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.PrefilteringModeMainLightShadows;
  15. using PrefilteringModeAdditionalLights = UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.PrefilteringModeAdditionalLights;
  16. namespace UnityEditor.Rendering.Universal
  17. {
  18. [Flags]
  19. enum ShaderFeatures : long
  20. {
  21. None = 0,
  22. MainLight = (1L << 0),
  23. MainLightShadows = (1L << 1),
  24. AdditionalLightsPixel = (1L << 2),
  25. AdditionalLightShadows = (1L << 3),
  26. AdditionalLightsVertex = (1L << 4),
  27. SoftShadows = (1L << 5),
  28. MixedLighting = (1L << 6),
  29. TerrainHoles = (1L << 7),
  30. DeferredShading = (1L << 8), // DeferredRenderer is in the list of renderer
  31. AccurateGbufferNormals = (1L << 9),
  32. ScreenSpaceOcclusion = (1L << 10),
  33. ScreenSpaceShadows = (1L << 11),
  34. UseFastSRGBLinearConversion = (1L << 12),
  35. LightLayers = (1L << 13),
  36. ReflectionProbeBlending = (1L << 14),
  37. ReflectionProbeBoxProjection = (1L << 15),
  38. DBufferMRT1 = (1L << 16),
  39. DBufferMRT2 = (1L << 17),
  40. DBufferMRT3 = (1L << 18),
  41. DecalScreenSpace = (1L << 19),
  42. DecalGBuffer = (1L << 20),
  43. DecalNormalBlendLow = (1L << 21),
  44. DecalNormalBlendMedium = (1L << 22),
  45. DecalNormalBlendHigh = (1L << 23),
  46. ForwardPlus = (1L << 24),
  47. RenderPassEnabled = (1L << 25),
  48. MainLightShadowsCascade = (1L << 26),
  49. DrawProcedural = (1L << 27),
  50. ScreenSpaceOcclusionAfterOpaque = (1L << 28),
  51. AdditionalLightsKeepOffVariants = (1L << 29),
  52. ShadowsKeepOffVariants = (1L << 30),
  53. UseLegacyLightmaps = (1L << 31),
  54. DecalLayers = (1L << 32),
  55. OpaqueWriteRenderingLayers = (1L << 33),
  56. GBufferWriteRenderingLayers = (1L << 34),
  57. DepthNormalPassRenderingLayers = (1L << 35),
  58. LightCookies = (1L << 36),
  59. LODCrossFade = (1L << 37),
  60. ProbeVolumeL1 = (1L << 38),
  61. ProbeVolumeL2 = (1L << 39),
  62. HdrGrading = (1L << 40),
  63. AutoSHMode = (1L << 41),
  64. AutoSHModePerVertex = (1L << 42),
  65. ExplicitSHMode = (1L << 43),
  66. DataDrivenLensFlare = (1L << 44),
  67. ScreenSpaceLensFlare = (1L << 45),
  68. SoftShadowsLow = (1L << 46),
  69. SoftShadowsMedium = (1L << 47),
  70. SoftShadowsHigh = (1L << 48),
  71. AlphaOutput = (1L << 49),
  72. }
  73. [Flags]
  74. enum VolumeFeatures
  75. {
  76. None = 0,
  77. Calculated = (1 << 0),
  78. LensDistortion = (1 << 1),
  79. //2: Unused for now
  80. ChromaticAberration = (1 << 3),
  81. ToneMapping = (1 << 4),
  82. FilmGrain = (1 << 5),
  83. DepthOfField = (1 << 6),
  84. CameraMotionBlur = (1 << 7),
  85. PaniniProjection = (1 << 8),
  86. BloomLQ = (1 << 9),
  87. BloomLQDirt = (1 << 10),
  88. BloomHQ = (1 << 11),
  89. BloomHQDirt = (1 << 12),
  90. }
  91. /// <summary>
  92. /// Preprocess Build class used to determine the shader features used in the project.
  93. /// Also called when building Asset Bundles.
  94. /// </summary>
  95. class ShaderBuildPreprocessor : IPreprocessBuildWithReport, IPostprocessBuildWithReport
  96. {
  97. // Public
  98. public int callbackOrder => 0;
  99. public static bool s_StripUnusedVariants;
  100. public static bool s_StripDebugDisplayShaders;
  101. public static bool s_StripUnusedPostProcessingVariants;
  102. public static bool s_StripScreenCoordOverrideVariants;
  103. public static bool s_Strip2DPasses;
  104. public static bool s_UseSoftShadowQualityLevelKeywords;
  105. public static bool s_StripXRVariants;
  106. public static List<ShaderFeatures> supportedFeaturesList
  107. {
  108. get
  109. {
  110. // This can happen for example when building AssetBundles.
  111. if (s_SupportedFeaturesList.Count == 0)
  112. GatherShaderFeatures(Debug.isDebugBuild);
  113. return s_SupportedFeaturesList;
  114. }
  115. }
  116. public static VolumeFeatures volumeFeatures
  117. {
  118. get
  119. {
  120. // This can happen for example when building AssetBundles.
  121. if (s_VolumeFeatures == VolumeFeatures.None)
  122. GetSupportedFeaturesFromVolumes();
  123. return s_VolumeFeatures;
  124. }
  125. }
  126. // Private
  127. private static bool s_KeepOffVariantForAdditionalLights;
  128. private static bool s_UseSHPerVertexForSHAuto;
  129. private static VolumeFeatures s_VolumeFeatures;
  130. private static List<ShaderFeatures> s_SupportedFeaturesList = new();
  131. // Helper class to detect XR build targets at build time.
  132. internal sealed class PlatformBuildTimeDetect
  133. {
  134. private static PlatformBuildTimeDetect s_PlatformInfo;
  135. internal bool isStandaloneXR { get; private set; }
  136. internal bool isHololens { get; private set; }
  137. internal bool isQuest { get; private set; }
  138. internal bool isSwitch { get; private set; }
  139. private PlatformBuildTimeDetect()
  140. {
  141. BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
  142. isSwitch = buildTargetGroup == BuildTargetGroup.Switch;
  143. #if XR_MANAGEMENT_4_0_1_OR_NEWER
  144. var buildTargetSettings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(buildTargetGroup);
  145. if (buildTargetSettings != null && buildTargetSettings.AssignedSettings != null && buildTargetSettings.AssignedSettings.activeLoaders.Count > 0)
  146. {
  147. isStandaloneXR = buildTargetGroup == BuildTargetGroup.Standalone;
  148. isHololens = buildTargetGroup == BuildTargetGroup.WSA;
  149. isQuest = buildTargetGroup == BuildTargetGroup.Android;
  150. }
  151. #endif
  152. }
  153. internal static PlatformBuildTimeDetect GetInstance()
  154. {
  155. if (s_PlatformInfo == null)
  156. s_PlatformInfo = new PlatformBuildTimeDetect();
  157. return s_PlatformInfo;
  158. }
  159. internal static void ClearInstance()
  160. {
  161. s_PlatformInfo = null;
  162. }
  163. }
  164. internal struct RendererRequirements
  165. {
  166. public int msaaSampleCount;
  167. public bool isUniversalRenderer;
  168. public bool needsUnusedVariants;
  169. public bool needsProcedural;
  170. public bool needsMainLightShadows;
  171. public bool needsAdditionalLightShadows;
  172. public bool needsSoftShadows;
  173. public bool needsSoftShadowsQualityLevels;
  174. public bool needsShadowsOff;
  175. public bool needsAdditionalLightsOff;
  176. public bool needsGBufferRenderingLayers;
  177. public bool needsGBufferAccurateNormals;
  178. public bool needsRenderPass;
  179. public bool needsReflectionProbeBlending;
  180. public bool needsReflectionProbeBoxProjection;
  181. public bool needsSHVertexForSHAuto;
  182. public RenderingMode renderingMode;
  183. }
  184. // Called before the build is started...
  185. public void OnPreprocessBuild(BuildReport report)
  186. {
  187. #if PROFILE_BUILD
  188. Profiler.enableBinaryLog = true;
  189. Profiler.logFile = "profilerlog.raw";
  190. Profiler.enabled = true;
  191. #endif
  192. bool isDevelopmentBuild = (report.summary.options & BuildOptions.Development) != 0;
  193. GatherShaderFeatures(isDevelopmentBuild);
  194. }
  195. // Called after the build has finished...
  196. public void OnPostprocessBuild(BuildReport report)
  197. {
  198. PlatformBuildTimeDetect.ClearInstance();
  199. #if PROFILE_BUILD
  200. Profiler.enabled = false;
  201. #endif
  202. }
  203. // Gathers all the shader features and updates the prefiltering
  204. // settings for all URP Assets in the quality settings
  205. private static void GatherShaderFeatures(bool isDevelopmentBuild)
  206. {
  207. GetGlobalAndPlatformSettings(isDevelopmentBuild);
  208. GetSupportedFeaturesFromVolumes();
  209. s_Strip2DPasses = true;
  210. s_SupportedFeaturesList.Clear();
  211. using (ListPool<UniversalRenderPipelineAsset>.Get(out List<UniversalRenderPipelineAsset> urpAssets))
  212. {
  213. bool buildingForURP = EditorUserBuildSettings.activeBuildTarget.TryGetRenderPipelineAssets(urpAssets);
  214. if (buildingForURP)
  215. {
  216. // Get Supported features & update data used for Shader Prefiltering and Scriptable Stripping
  217. GetSupportedShaderFeaturesFromAssets(ref urpAssets, ref s_SupportedFeaturesList, s_StripUnusedVariants);
  218. }
  219. }
  220. }
  221. // Retrieves the global and platform settings used in the project...
  222. private static void GetGlobalAndPlatformSettings(bool isDevelopmentBuild)
  223. {
  224. if (GraphicsSettings.TryGetRenderPipelineSettings<ShaderStrippingSetting>(out var shaderStrippingSettings))
  225. s_StripDebugDisplayShaders = !isDevelopmentBuild || shaderStrippingSettings.stripRuntimeDebugShaders;
  226. else
  227. s_StripDebugDisplayShaders = true;
  228. if (GraphicsSettings.TryGetRenderPipelineSettings<URPShaderStrippingSetting>(out var urpShaderStrippingSettings))
  229. {
  230. s_StripUnusedPostProcessingVariants = urpShaderStrippingSettings.stripUnusedPostProcessingVariants;
  231. s_StripUnusedVariants = urpShaderStrippingSettings.stripUnusedVariants;
  232. s_StripScreenCoordOverrideVariants = urpShaderStrippingSettings.stripScreenCoordOverrideVariants;
  233. }
  234. PlatformBuildTimeDetect platformBuildTimeDetect = PlatformBuildTimeDetect.GetInstance();
  235. bool isShaderAPIMobileDefined = GraphicsSettings.HasShaderDefine(BuiltinShaderDefine.SHADER_API_MOBILE);
  236. if (platformBuildTimeDetect.isSwitch || isShaderAPIMobileDefined)
  237. s_UseSHPerVertexForSHAuto = true;
  238. // XR Stripping
  239. #if XR_MANAGEMENT_4_0_1_OR_NEWER
  240. BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
  241. XRGeneralSettings generalSettings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(buildTargetGroup);
  242. s_StripXRVariants = generalSettings == null || generalSettings.Manager == null || generalSettings.Manager.activeLoaders.Count <= 0;
  243. if (platformBuildTimeDetect.isStandaloneXR)
  244. s_StripDebugDisplayShaders = true;
  245. if (platformBuildTimeDetect.isHololens || platformBuildTimeDetect.isQuest)
  246. {
  247. s_KeepOffVariantForAdditionalLights = true;
  248. s_UseSoftShadowQualityLevelKeywords = true;
  249. s_UseSHPerVertexForSHAuto = true;
  250. }
  251. #else
  252. s_UseSoftShadowQualityLevelKeywords = false;
  253. s_StripXRVariants = true;
  254. #endif
  255. }
  256. // Checks each Volume Profile Assets for used features...
  257. private static void GetSupportedFeaturesFromVolumes()
  258. {
  259. if (!s_StripUnusedPostProcessingVariants)
  260. return;
  261. s_VolumeFeatures = VolumeFeatures.Calculated;
  262. string[] guids = AssetDatabase.FindAssets("t:VolumeProfile");
  263. foreach (string guid in guids)
  264. {
  265. string path = AssetDatabase.GUIDToAssetPath(guid);
  266. // We only care what is in assets folder
  267. if (!path.StartsWith("Assets"))
  268. continue;
  269. VolumeProfile asset = AssetDatabase.LoadAssetAtPath<VolumeProfile>(path);
  270. if (asset == null)
  271. continue;
  272. if (asset.Has<LensDistortion>())
  273. s_VolumeFeatures |= VolumeFeatures.LensDistortion;
  274. Bloom bloom;
  275. if (asset.TryGet<Bloom>(out bloom))
  276. {
  277. //strip unused bloom variants. #pragma multi_compile_local_fragment _ _BLOOM_LQ _BLOOM_HQ _BLOOM_LQ_DIRT _BLOOM_HQ_DIRT
  278. if (bloom.highQualityFiltering.value)
  279. {
  280. if (bloom.dirtIntensity.value > 0f && bloom.dirtTexture.value != null)
  281. s_VolumeFeatures |= VolumeFeatures.BloomHQDirt;
  282. else
  283. s_VolumeFeatures |= VolumeFeatures.BloomHQ;
  284. }
  285. else
  286. {
  287. if (bloom.dirtIntensity.value > 0f && bloom.dirtTexture.value != null)
  288. s_VolumeFeatures |= VolumeFeatures.BloomLQDirt;
  289. else
  290. s_VolumeFeatures |= VolumeFeatures.BloomLQ;
  291. }
  292. }
  293. if (asset.Has<Tonemapping>())
  294. s_VolumeFeatures |= VolumeFeatures.ToneMapping;
  295. if (asset.Has<FilmGrain>())
  296. s_VolumeFeatures |= VolumeFeatures.FilmGrain;
  297. if (asset.Has<DepthOfField>())
  298. s_VolumeFeatures |= VolumeFeatures.DepthOfField;
  299. if (asset.Has<MotionBlur>())
  300. s_VolumeFeatures |= VolumeFeatures.CameraMotionBlur;
  301. if (asset.Has<PaniniProjection>())
  302. s_VolumeFeatures |= VolumeFeatures.PaniniProjection;
  303. if (asset.Has<ChromaticAberration>())
  304. s_VolumeFeatures |= VolumeFeatures.ChromaticAberration;
  305. }
  306. }
  307. // Checks each Universal Render Pipeline Asset for features used...
  308. internal static void GetSupportedShaderFeaturesFromAssets(ref List<UniversalRenderPipelineAsset> urpAssets, ref List<ShaderFeatures> rendererFeaturesList, bool stripUnusedVariants)
  309. {
  310. List<ScreenSpaceAmbientOcclusionSettings> ssaoRendererFeatures = new List<ScreenSpaceAmbientOcclusionSettings>(16);
  311. for (int urpAssetIndex = 0; urpAssetIndex < urpAssets.Count; urpAssetIndex++)
  312. {
  313. // Get the asset and check if it's valid
  314. UniversalRenderPipelineAsset urpAsset = urpAssets[urpAssetIndex];
  315. if (urpAsset == null)
  316. continue;
  317. // Check the asset for supported features
  318. ShaderFeatures urpAssetShaderFeatures = GetSupportedShaderFeaturesFromAsset(
  319. ref urpAsset,
  320. ref rendererFeaturesList,
  321. ref ssaoRendererFeatures,
  322. stripUnusedVariants,
  323. out bool containsForwardRenderer,
  324. out bool everyRendererHasSSAO
  325. );
  326. // Creates a struct containing all the prefiltering settings for this asset
  327. ShaderPrefilteringData spd = CreatePrefilteringSettings(
  328. ref urpAssetShaderFeatures,
  329. containsForwardRenderer,
  330. everyRendererHasSSAO,
  331. s_StripXRVariants,
  332. !PlayerSettings.allowHDRDisplaySupport || !urpAsset.supportsHDR,
  333. s_StripDebugDisplayShaders,
  334. s_StripScreenCoordOverrideVariants,
  335. s_StripUnusedVariants,
  336. ref ssaoRendererFeatures
  337. );
  338. // Update the Prefiltering settings for this URP asset
  339. urpAsset.UpdateShaderKeywordPrefiltering(ref spd);
  340. // Mark the asset dirty so it can be serialized once the build is finished
  341. EditorUtility.SetDirty(urpAsset);
  342. // Clean up
  343. ssaoRendererFeatures.Clear();
  344. }
  345. }
  346. // Checks the assigned Universal Pipeline Asset for features used...
  347. internal static ShaderFeatures GetSupportedShaderFeaturesFromAsset(
  348. ref UniversalRenderPipelineAsset urpAsset,
  349. ref List<ShaderFeatures> rendererFeaturesList,
  350. ref List<ScreenSpaceAmbientOcclusionSettings> ssaoRendererFeatures,
  351. bool stripUnusedVariants,
  352. out bool containsForwardRenderer,
  353. out bool everyRendererHasSSAO)
  354. {
  355. ShaderFeatures urpAssetShaderFeatures = ShaderFeatures.MainLight;
  356. // Additional Lights and Shadows...
  357. switch (urpAsset.additionalLightsRenderingMode)
  358. {
  359. case LightRenderingMode.PerVertex:
  360. urpAssetShaderFeatures |= ShaderFeatures.AdditionalLightsVertex;
  361. break;
  362. case LightRenderingMode.PerPixel:
  363. urpAssetShaderFeatures |= ShaderFeatures.AdditionalLightsPixel;
  364. break;
  365. case LightRenderingMode.Disabled:
  366. break;
  367. default:
  368. throw new ArgumentOutOfRangeException();
  369. }
  370. if (urpAsset.lightProbeSystem == LightProbeSystem.ProbeVolumes)
  371. {
  372. if (urpAsset.probeVolumeSHBands == ProbeVolumeSHBands.SphericalHarmonicsL1)
  373. urpAssetShaderFeatures |= ShaderFeatures.ProbeVolumeL1;
  374. if (urpAsset.probeVolumeSHBands == ProbeVolumeSHBands.SphericalHarmonicsL2)
  375. urpAssetShaderFeatures |= ShaderFeatures.ProbeVolumeL2;
  376. }
  377. if (urpAsset.supportsMixedLighting)
  378. urpAssetShaderFeatures |= ShaderFeatures.MixedLighting;
  379. if (urpAsset.supportsTerrainHoles)
  380. urpAssetShaderFeatures |= ShaderFeatures.TerrainHoles;
  381. if (urpAsset.useFastSRGBLinearConversion)
  382. urpAssetShaderFeatures |= ShaderFeatures.UseFastSRGBLinearConversion;
  383. if (urpAsset.useRenderingLayers)
  384. urpAssetShaderFeatures |= ShaderFeatures.LightLayers;
  385. if (urpAsset.supportsLightCookies)
  386. urpAssetShaderFeatures |= ShaderFeatures.LightCookies;
  387. bool hasHDROutput = PlayerSettings.allowHDRDisplaySupport && urpAsset.supportsHDR;
  388. if (urpAsset.colorGradingMode == ColorGradingMode.HighDynamicRange || hasHDROutput)
  389. urpAssetShaderFeatures |= ShaderFeatures.HdrGrading;
  390. if (urpAsset.enableLODCrossFade)
  391. urpAssetShaderFeatures |= ShaderFeatures.LODCrossFade;
  392. if (urpAsset.shEvalMode == ShEvalMode.Auto)
  393. urpAssetShaderFeatures |= ShaderFeatures.AutoSHMode;
  394. if (urpAsset.supportScreenSpaceLensFlare)
  395. urpAssetShaderFeatures |= ShaderFeatures.ScreenSpaceLensFlare;
  396. if (urpAsset.supportDataDrivenLensFlare)
  397. urpAssetShaderFeatures |= ShaderFeatures.DataDrivenLensFlare;
  398. if (urpAsset.gpuResidentDrawerMode != GPUResidentDrawerMode.Disabled)
  399. urpAssetShaderFeatures |= ShaderFeatures.UseLegacyLightmaps;
  400. // URP post-processing and alpha output follows the back-buffer color format requested in the asset.
  401. // Back-buffer alpha format is required. Or a render texture with alpha formats.
  402. // Without any external option we would need to keep all shaders and assume potential alpha output for all projects.
  403. // Therefore we strip the shader based on the asset enabling the alpha output for post-processing.
  404. // Alpha backbuffer is supported for:
  405. // SDR 32-bit, RGBA8, (!urpAsset.supportsHDR)
  406. // HDR 64-bit, RGBA16Float, (urpAsset.supportsHDR && urpAsset.hdrColorBufferPrecision == HDRColorBufferPrecision._64Bits)
  407. if(urpAsset.allowPostProcessAlphaOutput)
  408. urpAssetShaderFeatures |= ShaderFeatures.AlphaOutput;
  409. // Check each renderer & renderer feature
  410. urpAssetShaderFeatures = GetSupportedShaderFeaturesFromRenderers(
  411. ref urpAsset,
  412. ref rendererFeaturesList,
  413. urpAssetShaderFeatures,
  414. ref ssaoRendererFeatures,
  415. stripUnusedVariants,
  416. out containsForwardRenderer,
  417. out everyRendererHasSSAO);
  418. return urpAssetShaderFeatures;
  419. }
  420. // Checks each Universal Renderer in the assigned URP Asset for features used...
  421. internal static ShaderFeatures GetSupportedShaderFeaturesFromRenderers(
  422. ref UniversalRenderPipelineAsset urpAsset,
  423. ref List<ShaderFeatures> rendererFeaturesList,
  424. ShaderFeatures urpAssetShaderFeatures,
  425. ref List<ScreenSpaceAmbientOcclusionSettings> ssaoRendererFeatures,
  426. bool stripUnusedVariants,
  427. out bool containsForwardRenderer,
  428. out bool everyRendererHasSSAO)
  429. {
  430. // Sanity check
  431. if (rendererFeaturesList == null)
  432. rendererFeaturesList = new List<ShaderFeatures>();
  433. // The combined URP Asset features used for Prefiltering
  434. // We start with None instead of URP Asset features as they can change
  435. // when iterating over the renderers, such as when Forward Plus is in use.
  436. ShaderFeatures combinedURPAssetShaderFeatures = ShaderFeatures.None;
  437. containsForwardRenderer = false;
  438. everyRendererHasSSAO = true;
  439. ScriptableRendererData[] rendererDataArray = urpAsset.m_RendererDataList;
  440. for (int rendererIndex = 0; rendererIndex < rendererDataArray.Length; ++rendererIndex)
  441. {
  442. // Get feature requirements from the renderer
  443. ScriptableRenderer renderer = urpAsset.GetRenderer(rendererIndex);
  444. ScriptableRendererData rendererData = rendererDataArray[rendererIndex];
  445. RendererRequirements rendererRequirements = GetRendererRequirements(ref urpAsset, ref renderer, ref rendererData, stripUnusedVariants);
  446. // Get & add Supported features from renderers used for Scriptable Stripping and prefiltering.
  447. ShaderFeatures rendererShaderFeatures = GetSupportedShaderFeaturesFromRenderer(ref rendererRequirements, ref rendererData, ref ssaoRendererFeatures, ref containsForwardRenderer, urpAssetShaderFeatures);
  448. rendererFeaturesList.Add(rendererShaderFeatures);
  449. // Check to see if it's possible to remove the OFF variant for SSAO
  450. everyRendererHasSSAO &= IsFeatureEnabled(rendererShaderFeatures, ShaderFeatures.ScreenSpaceOcclusion);
  451. // Check for completely removing 2D passes
  452. s_Strip2DPasses &= renderer is not Renderer2D;
  453. // Add the features from the renderer to the combined feature set for this URP Asset
  454. combinedURPAssetShaderFeatures |= rendererShaderFeatures;
  455. }
  456. return combinedURPAssetShaderFeatures;
  457. }
  458. internal static bool NeedsProceduralKeyword(ref RendererRequirements rendererRequirements)
  459. {
  460. #if ENABLE_VR && ENABLE_XR_MODULE
  461. var xrResourcesAreValid = GraphicsSettings.GetRenderPipelineSettings<UniversalRenderPipelineRuntimeXRResources>()?.valid ?? false;
  462. return rendererRequirements.isUniversalRenderer && xrResourcesAreValid;
  463. #else
  464. return false;
  465. #endif
  466. }
  467. internal static RendererRequirements GetRendererRequirements(ref UniversalRenderPipelineAsset urpAsset, ref ScriptableRenderer renderer, ref ScriptableRendererData rendererData, bool stripUnusedVariants)
  468. {
  469. UniversalRenderer universalRenderer = renderer as UniversalRenderer;
  470. UniversalRendererData universalRendererData = rendererData as UniversalRendererData;
  471. RendererRequirements rsd = new();
  472. rsd.needsUnusedVariants = !stripUnusedVariants;
  473. rsd.isUniversalRenderer = universalRendererData != null && universalRenderer != null;
  474. rsd.msaaSampleCount = urpAsset.msaaSampleCount;
  475. rsd.renderingMode = rsd.isUniversalRenderer ? universalRendererData.renderingMode : RenderingMode.Forward;
  476. rsd.needsMainLightShadows = urpAsset.supportsMainLightShadows && urpAsset.mainLightRenderingMode == LightRenderingMode.PerPixel;
  477. rsd.needsAdditionalLightShadows = urpAsset.supportsAdditionalLightShadows && (urpAsset.additionalLightsRenderingMode == LightRenderingMode.PerPixel || rsd.renderingMode == RenderingMode.ForwardPlus);
  478. rsd.needsSoftShadows = urpAsset.supportsSoftShadows && (rsd.needsMainLightShadows || rsd.needsAdditionalLightShadows);
  479. rsd.needsSoftShadowsQualityLevels = rsd.needsSoftShadows && s_UseSoftShadowQualityLevelKeywords;
  480. rsd.needsShadowsOff = !renderer.stripShadowsOffVariants;
  481. rsd.needsAdditionalLightsOff = s_KeepOffVariantForAdditionalLights || !renderer.stripAdditionalLightOffVariants;
  482. rsd.needsGBufferRenderingLayers = (rsd.isUniversalRenderer && rsd.renderingMode == RenderingMode.Deferred && urpAsset.useRenderingLayers);
  483. rsd.needsGBufferAccurateNormals = (rsd.isUniversalRenderer && rsd.renderingMode == RenderingMode.Deferred && universalRenderer.accurateGbufferNormals);
  484. rsd.needsRenderPass = (rsd.isUniversalRenderer && rsd.renderingMode == RenderingMode.Deferred);
  485. rsd.needsReflectionProbeBlending = urpAsset.reflectionProbeBlending;
  486. rsd.needsReflectionProbeBoxProjection = urpAsset.reflectionProbeBoxProjection;
  487. rsd.needsProcedural = NeedsProceduralKeyword(ref rsd);
  488. rsd.needsSHVertexForSHAuto = s_UseSHPerVertexForSHAuto;
  489. return rsd;
  490. }
  491. // Checks the assigned Universal renderer for features used...
  492. internal static ShaderFeatures GetSupportedShaderFeaturesFromRenderer(ref RendererRequirements rendererRequirements, ref ScriptableRendererData rendererData, ref List<ScreenSpaceAmbientOcclusionSettings> ssaoRendererFeatures, ref bool containsForwardRenderer, ShaderFeatures urpAssetShaderFeatures)
  493. {
  494. ShaderFeatures shaderFeatures = urpAssetShaderFeatures;
  495. // Procedural...
  496. if (rendererRequirements.needsProcedural)
  497. shaderFeatures |= ShaderFeatures.DrawProcedural;
  498. // Rendering Modes...
  499. switch (rendererRequirements.renderingMode)
  500. {
  501. case RenderingMode.ForwardPlus:
  502. shaderFeatures |= ShaderFeatures.ForwardPlus;
  503. break;
  504. case RenderingMode.Deferred:
  505. shaderFeatures |= ShaderFeatures.DeferredShading;
  506. break;
  507. case RenderingMode.Forward:
  508. default:
  509. containsForwardRenderer = true;
  510. break;
  511. }
  512. // Renderer features...
  513. if (rendererData != null)
  514. {
  515. List<ScriptableRendererFeature> rendererFeatures = rendererData.rendererFeatures;
  516. shaderFeatures |= GetSupportedShaderFeaturesFromRendererFeatures(ref rendererRequirements, ref rendererFeatures, ref ssaoRendererFeatures);
  517. }
  518. // The Off variant for Additional Lights
  519. if (rendererRequirements.needsAdditionalLightsOff)
  520. shaderFeatures |= ShaderFeatures.AdditionalLightsKeepOffVariants;
  521. // Forward+
  522. if (rendererRequirements.renderingMode == RenderingMode.ForwardPlus)
  523. {
  524. shaderFeatures |= ShaderFeatures.AdditionalLightsKeepOffVariants;
  525. shaderFeatures |= ShaderFeatures.ForwardPlus;
  526. shaderFeatures &= ~(ShaderFeatures.AdditionalLightsPixel | ShaderFeatures.AdditionalLightsVertex);
  527. }
  528. // Main & Additional Light Shadows
  529. // Keeps the Off variant for Main and Additional Light shadows
  530. if (rendererRequirements.needsShadowsOff)
  531. shaderFeatures |= ShaderFeatures.ShadowsKeepOffVariants;
  532. if (rendererRequirements.needsMainLightShadows)
  533. {
  534. // Cascade count can be changed at runtime, so include both of them
  535. shaderFeatures |= ShaderFeatures.MainLightShadows;
  536. shaderFeatures |= ShaderFeatures.MainLightShadowsCascade;
  537. }
  538. // Additional Light Shadows
  539. if (rendererRequirements.needsAdditionalLightShadows)
  540. shaderFeatures |= ShaderFeatures.AdditionalLightShadows;
  541. // Soft shadows for Main and Additional Lights
  542. if (rendererRequirements.needsSoftShadows && !rendererRequirements.needsSoftShadowsQualityLevels)
  543. shaderFeatures |= ShaderFeatures.SoftShadows;
  544. if (rendererRequirements.needsSoftShadowsQualityLevels)
  545. {
  546. if (UniversalRenderPipeline.asset?.softShadowQuality == SoftShadowQuality.Low)
  547. shaderFeatures |= ShaderFeatures.SoftShadowsLow;
  548. if (UniversalRenderPipeline.asset?.softShadowQuality == SoftShadowQuality.Medium)
  549. shaderFeatures |= ShaderFeatures.SoftShadowsMedium;
  550. if (UniversalRenderPipeline.asset?.softShadowQuality == SoftShadowQuality.High)
  551. shaderFeatures |= ShaderFeatures.SoftShadowsHigh;
  552. }
  553. // Deferred GBuffer Rendering Layers
  554. if (rendererRequirements.needsGBufferRenderingLayers)
  555. shaderFeatures |= ShaderFeatures.GBufferWriteRenderingLayers;
  556. // Deferred GBuffer Accurate Normals
  557. if (rendererRequirements.needsGBufferAccurateNormals)
  558. shaderFeatures |= ShaderFeatures.AccurateGbufferNormals;
  559. // Deferred GBuffer Native Render Pass
  560. if (rendererRequirements.needsRenderPass)
  561. shaderFeatures |= ShaderFeatures.RenderPassEnabled;
  562. // Reflection Probe Blending
  563. if (rendererRequirements.needsReflectionProbeBlending)
  564. shaderFeatures |= ShaderFeatures.ReflectionProbeBlending;
  565. // Reflection Probe Box Projection
  566. if (rendererRequirements.needsReflectionProbeBoxProjection)
  567. shaderFeatures |= ShaderFeatures.ReflectionProbeBoxProjection;
  568. if (rendererRequirements.needsSHVertexForSHAuto)
  569. shaderFeatures |= ShaderFeatures.AutoSHModePerVertex;
  570. return shaderFeatures;
  571. }
  572. // Checks each Universal Renderer Feature in the assigned renderer...
  573. internal static ShaderFeatures GetSupportedShaderFeaturesFromRendererFeatures(ref RendererRequirements rendererRequirements, ref List<ScriptableRendererFeature> rendererFeatures, ref List<ScreenSpaceAmbientOcclusionSettings> ssaoRendererFeatures)
  574. {
  575. ShaderFeatures shaderFeatures = ShaderFeatures.None;
  576. bool usesRenderingLayers = false;
  577. RenderingLayerUtils.Event renderingLayersEvent = RenderingLayerUtils.Event.Opaque;
  578. bool isDeferredRenderer = (rendererRequirements.renderingMode == RenderingMode.Deferred);
  579. for (int rendererFeatureIndex = 0; rendererFeatureIndex < rendererFeatures.Count; rendererFeatureIndex++)
  580. {
  581. ScriptableRendererFeature rendererFeature = rendererFeatures[rendererFeatureIndex];
  582. // Make sure the renderer feature isn't missing
  583. if (rendererFeature == null)
  584. continue;
  585. // We don't add disabled renderer features if "Strip Unused Variants" is enabled.
  586. if (!rendererRequirements.needsUnusedVariants && !rendererFeature.isActive)
  587. continue;
  588. // Rendering Layers...
  589. if (rendererRequirements.isUniversalRenderer &&
  590. RenderingLayerUtils.RequireRenderingLayers(rendererFeatures,
  591. rendererRequirements.renderingMode,
  592. rendererRequirements.needsGBufferAccurateNormals,
  593. rendererRequirements.msaaSampleCount, out RenderingLayerUtils.Event rendererEvent, out _))
  594. {
  595. usesRenderingLayers = true;
  596. RenderingLayerUtils.CombineRendererEvents(isDeferredRenderer, rendererRequirements.msaaSampleCount, rendererEvent, ref renderingLayersEvent);
  597. }
  598. // Screen Space Shadows...
  599. ScreenSpaceShadows sssFeature = rendererFeature as ScreenSpaceShadows;
  600. if (sssFeature != null)
  601. {
  602. // Add it if it's enabled or if unused variants should not be stripped...
  603. if (sssFeature.isActive || rendererRequirements.needsUnusedVariants)
  604. shaderFeatures |= ShaderFeatures.ScreenSpaceShadows;
  605. continue;
  606. }
  607. // Screen Space Ambient Occlusion (SSAO)...
  608. // Removing the OFF variant requires every renderer to use SSAO. That is checked later.
  609. ScreenSpaceAmbientOcclusion ssaoFeature = rendererFeature as ScreenSpaceAmbientOcclusion;
  610. if (ssaoFeature != null)
  611. {
  612. ScreenSpaceAmbientOcclusionSettings ssaoSettings = ssaoFeature.settings;
  613. ssaoRendererFeatures.Add(ssaoSettings);
  614. // Keep _SCREEN_SPACE_OCCLUSION and the Off variant when stripping of unused variants is disabled
  615. if (rendererRequirements.needsUnusedVariants)
  616. {
  617. shaderFeatures |= ShaderFeatures.ScreenSpaceOcclusion;
  618. shaderFeatures |= ShaderFeatures.ScreenSpaceOcclusionAfterOpaque;
  619. }
  620. // The feature is active (Tested a few lines above) so check for AfterOpaque
  621. else
  622. {
  623. if (ssaoSettings.AfterOpaque)
  624. shaderFeatures |= ShaderFeatures.ScreenSpaceOcclusionAfterOpaque;
  625. else
  626. shaderFeatures |= ShaderFeatures.ScreenSpaceOcclusion;
  627. }
  628. // Otherwise the keyword will not be used
  629. continue;
  630. }
  631. // Decals...
  632. DecalRendererFeature decal = rendererFeature as DecalRendererFeature;
  633. if (decal != null && rendererRequirements.isUniversalRenderer)
  634. {
  635. // Keep all Decals variants when stripping of unused variants is disabled
  636. if (rendererRequirements.needsUnusedVariants)
  637. {
  638. shaderFeatures |= ShaderFeatures.DBufferMRT1;
  639. shaderFeatures |= ShaderFeatures.DBufferMRT2;
  640. shaderFeatures |= ShaderFeatures.DBufferMRT3;
  641. shaderFeatures |= ShaderFeatures.DecalScreenSpace;
  642. shaderFeatures |= ShaderFeatures.DecalNormalBlendLow;
  643. shaderFeatures |= ShaderFeatures.DecalNormalBlendMedium;
  644. shaderFeatures |= ShaderFeatures.DecalNormalBlendHigh;
  645. shaderFeatures |= ShaderFeatures.DecalGBuffer;
  646. shaderFeatures |= ShaderFeatures.DecalLayers;
  647. }
  648. else
  649. {
  650. DecalTechnique technique = decal.GetTechnique(isDeferredRenderer, rendererRequirements.needsGBufferAccurateNormals, false);
  651. switch (technique)
  652. {
  653. case DecalTechnique.DBuffer:
  654. shaderFeatures |= GetFromDecalSurfaceData(decal.GetDBufferSettings().surfaceData);
  655. break;
  656. case DecalTechnique.ScreenSpace:
  657. shaderFeatures |= GetFromNormalBlend(decal.GetScreenSpaceSettings().normalBlend);
  658. shaderFeatures |= ShaderFeatures.DecalScreenSpace;
  659. break;
  660. case DecalTechnique.GBuffer:
  661. shaderFeatures |= GetFromNormalBlend(decal.GetScreenSpaceSettings().normalBlend);
  662. shaderFeatures |= ShaderFeatures.DecalGBuffer;
  663. //data.shaderFeatures |= ShaderFeatures.DecalScreenSpace; // In case deferred is not supported it will fallback to forward
  664. break;
  665. }
  666. if (decal.requiresDecalLayers)
  667. shaderFeatures |= ShaderFeatures.DecalLayers;
  668. }
  669. }
  670. }
  671. // If using rendering layers, enable the appropriate feature
  672. if (usesRenderingLayers)
  673. {
  674. if (rendererRequirements.needsUnusedVariants)
  675. {
  676. shaderFeatures |= ShaderFeatures.GBufferWriteRenderingLayers;
  677. shaderFeatures |= ShaderFeatures.OpaqueWriteRenderingLayers;
  678. shaderFeatures |= ShaderFeatures.DepthNormalPassRenderingLayers;
  679. }
  680. else if (isDeferredRenderer)
  681. {
  682. // Rendering layers in both Depth Normal and GBuffer passes are needed
  683. // as some object might be rendered in forward and others in deferred.
  684. shaderFeatures |= ShaderFeatures.DepthNormalPassRenderingLayers;
  685. shaderFeatures |= ShaderFeatures.GBufferWriteRenderingLayers;
  686. }
  687. else
  688. {
  689. // Check if other passes need the keyword
  690. switch (renderingLayersEvent)
  691. {
  692. case RenderingLayerUtils.Event.DepthNormalPrePass:
  693. shaderFeatures |= ShaderFeatures.DepthNormalPassRenderingLayers;
  694. break;
  695. case RenderingLayerUtils.Event.Opaque:
  696. shaderFeatures |= ShaderFeatures.OpaqueWriteRenderingLayers;
  697. break;
  698. default:
  699. throw new NotImplementedException();
  700. }
  701. }
  702. }
  703. return shaderFeatures;
  704. }
  705. // Retrieves the correct feature used from the Decal Surface Data Settings...
  706. private static ShaderFeatures GetFromDecalSurfaceData(DecalSurfaceData surfaceData)
  707. {
  708. ShaderFeatures shaderFeatures = ShaderFeatures.None;
  709. switch (surfaceData)
  710. {
  711. case DecalSurfaceData.Albedo:
  712. shaderFeatures |= ShaderFeatures.DBufferMRT1;
  713. break;
  714. case DecalSurfaceData.AlbedoNormal:
  715. shaderFeatures |= ShaderFeatures.DBufferMRT2;
  716. break;
  717. case DecalSurfaceData.AlbedoNormalMAOS:
  718. shaderFeatures |= ShaderFeatures.DBufferMRT3;
  719. break;
  720. }
  721. return shaderFeatures;
  722. }
  723. // Retrieves the correct feature used from the Decal Normal Blend Settings...
  724. private static ShaderFeatures GetFromNormalBlend(DecalNormalBlend normalBlend)
  725. {
  726. ShaderFeatures shaderFeatures = ShaderFeatures.None;
  727. switch (normalBlend)
  728. {
  729. case DecalNormalBlend.Low:
  730. shaderFeatures |= ShaderFeatures.DecalNormalBlendLow;
  731. break;
  732. case DecalNormalBlend.Medium:
  733. shaderFeatures |= ShaderFeatures.DecalNormalBlendMedium;
  734. break;
  735. case DecalNormalBlend.High:
  736. shaderFeatures |= ShaderFeatures.DecalNormalBlendHigh;
  737. break;
  738. }
  739. return shaderFeatures;
  740. }
  741. // Creates a struct containing all the prefiltering settings for the asset sent as a parameter
  742. internal static ShaderPrefilteringData CreatePrefilteringSettings(
  743. ref ShaderFeatures shaderFeatures,
  744. bool isAssetUsingForward,
  745. bool everyRendererHasSSAO,
  746. bool stripXR,
  747. bool stripHDR,
  748. bool stripDebug,
  749. bool stripScreenCoord,
  750. bool stripUnusedVariants,
  751. ref List<ScreenSpaceAmbientOcclusionSettings> ssaoRendererFeatures
  752. )
  753. {
  754. bool isAssetUsingForwardPlus = IsFeatureEnabled(shaderFeatures, ShaderFeatures.ForwardPlus);
  755. bool isAssetUsingDeferred = IsFeatureEnabled(shaderFeatures, ShaderFeatures.DeferredShading);
  756. ShaderPrefilteringData spd = new();
  757. spd.stripXRKeywords = stripXR;
  758. spd.stripSoftShadowsQualityLow = !IsFeatureEnabled(shaderFeatures, ShaderFeatures.SoftShadowsLow);
  759. spd.stripSoftShadowsQualityMedium = !IsFeatureEnabled(shaderFeatures, ShaderFeatures.SoftShadowsMedium);
  760. spd.stripSoftShadowsQualityHigh = !IsFeatureEnabled(shaderFeatures, ShaderFeatures.SoftShadowsHigh);
  761. spd.stripHDRKeywords = stripHDR;
  762. spd.stripAlphaOutputKeywords = !IsFeatureEnabled(shaderFeatures, ShaderFeatures.AlphaOutput);
  763. spd.stripDebugDisplay = stripDebug;
  764. spd.stripScreenCoordOverride = stripScreenCoord;
  765. // Rendering Modes
  766. // Check if only Deferred is being used
  767. spd.deferredPrefilteringMode = PrefilteringMode.Remove;
  768. if (isAssetUsingDeferred)
  769. {
  770. // Only Deferred being used...
  771. if (!isAssetUsingForward && !isAssetUsingForwardPlus)
  772. spd.deferredPrefilteringMode = PrefilteringMode.SelectOnly;
  773. else
  774. spd.deferredPrefilteringMode = PrefilteringMode.Select;
  775. }
  776. // Check if only Forward+ is being used
  777. spd.forwardPlusPrefilteringMode = PrefilteringMode.Remove;
  778. if (isAssetUsingForwardPlus)
  779. {
  780. // Only Forward Plus being used...
  781. if (!isAssetUsingForward && !isAssetUsingDeferred)
  782. spd.forwardPlusPrefilteringMode = PrefilteringMode.SelectOnly;
  783. else
  784. spd.forwardPlusPrefilteringMode = PrefilteringMode.Select;
  785. }
  786. // Additional Lights...
  787. spd.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.Remove;
  788. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.AdditionalLightsVertex))
  789. {
  790. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.AdditionalLightsKeepOffVariants))
  791. spd.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.SelectVertexAndOff;
  792. else
  793. spd.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.SelectVertex;
  794. }
  795. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.AdditionalLightsPixel))
  796. {
  797. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.AdditionalLightsKeepOffVariants))
  798. spd.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.SelectPixelAndOff;
  799. else
  800. spd.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.SelectPixel;
  801. }
  802. // Shadows...
  803. // Main Light Shadows...
  804. spd.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.Remove;
  805. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.MainLightShadows))
  806. {
  807. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.MainLightShadowsCascade))
  808. {
  809. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.ShadowsKeepOffVariants))
  810. spd.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.SelectAll;
  811. else
  812. spd.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.SelectMainLightAndCascades;
  813. }
  814. else
  815. {
  816. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.ShadowsKeepOffVariants))
  817. spd.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.SelectMainLightAndOff;
  818. else
  819. spd.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.SelectMainLight;
  820. }
  821. }
  822. // Additional Light Shadows...
  823. spd.additionalLightsShadowsPrefilteringMode = PrefilteringMode.Remove;
  824. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.AdditionalLightShadows))
  825. {
  826. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.ShadowsKeepOffVariants))
  827. spd.additionalLightsShadowsPrefilteringMode = PrefilteringMode.Select;
  828. else
  829. spd.additionalLightsShadowsPrefilteringMode = PrefilteringMode.SelectOnly;
  830. }
  831. // Decals' MRT keywords
  832. spd.stripDBufferMRT1 = !IsFeatureEnabled(shaderFeatures, ShaderFeatures.DBufferMRT1);
  833. spd.stripDBufferMRT2 = !IsFeatureEnabled(shaderFeatures, ShaderFeatures.DBufferMRT2);
  834. spd.stripDBufferMRT3 = !IsFeatureEnabled(shaderFeatures, ShaderFeatures.DBufferMRT3);
  835. // Native Render Pass
  836. spd.stripNativeRenderPass = !IsFeatureEnabled(shaderFeatures, ShaderFeatures.RenderPassEnabled);
  837. // Rendering Layers
  838. spd.stripWriteRenderingLayers =
  839. !IsFeatureEnabled(shaderFeatures, ShaderFeatures.DepthNormalPassRenderingLayers)
  840. && !IsFeatureEnabled(shaderFeatures, ShaderFeatures.GBufferWriteRenderingLayers)
  841. && !IsFeatureEnabled(shaderFeatures, ShaderFeatures.OpaqueWriteRenderingLayers);
  842. // Disable lightmap texture arrays (GPU resident drawer)
  843. spd.useLegacyLightmaps = IsFeatureEnabled(shaderFeatures, ShaderFeatures.UseLegacyLightmaps);
  844. // Screen Space Ambient Occlusion
  845. spd.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.Remove;
  846. if (IsFeatureEnabled(shaderFeatures, ShaderFeatures.ScreenSpaceOcclusion))
  847. {
  848. // Remove the SSAO's OFF variant if Global Settings allow it and every renderer uses it.
  849. if (stripUnusedVariants && everyRendererHasSSAO)
  850. spd.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.SelectOnly;
  851. // Otherwise we keep both
  852. else
  853. spd.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.Select;
  854. }
  855. // SSAO shader keywords
  856. spd.stripSSAODepthNormals = true;
  857. spd.stripSSAOSourceDepthLow = true;
  858. spd.stripSSAOSourceDepthMedium = true;
  859. spd.stripSSAOSourceDepthHigh = true;
  860. spd.stripSSAOBlueNoise = true;
  861. spd.stripSSAOInterleaved = true;
  862. spd.stripSSAOSampleCountLow = true;
  863. spd.stripSSAOSampleCountMedium = true;
  864. spd.stripSSAOSampleCountHigh = true;
  865. for (int i = 0; i < ssaoRendererFeatures.Count; i++)
  866. {
  867. ScreenSpaceAmbientOcclusionSettings ssaoSettings = ssaoRendererFeatures[i];
  868. bool isUsingDepthNormals = ssaoSettings.Source == ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals;
  869. spd.stripSSAODepthNormals &= !isUsingDepthNormals;
  870. spd.stripSSAOSourceDepthLow &= isUsingDepthNormals || ssaoSettings.NormalSamples != ScreenSpaceAmbientOcclusionSettings.NormalQuality.Low;
  871. spd.stripSSAOSourceDepthMedium &= isUsingDepthNormals || ssaoSettings.NormalSamples != ScreenSpaceAmbientOcclusionSettings.NormalQuality.Medium;
  872. spd.stripSSAOSourceDepthHigh &= isUsingDepthNormals || ssaoSettings.NormalSamples != ScreenSpaceAmbientOcclusionSettings.NormalQuality.High;
  873. spd.stripSSAOBlueNoise &= ssaoSettings.AOMethod != ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise;
  874. spd.stripSSAOInterleaved &= ssaoSettings.AOMethod != ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.InterleavedGradient;
  875. spd.stripSSAOSampleCountLow &= ssaoSettings.Samples != ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Low;
  876. spd.stripSSAOSampleCountMedium &= ssaoSettings.Samples != ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Medium;
  877. spd.stripSSAOSampleCountHigh &= ssaoSettings.Samples != ScreenSpaceAmbientOcclusionSettings.AOSampleOption.High;
  878. }
  879. return spd;
  880. }
  881. // Checks whether a ShaderFeature is enabled or not
  882. internal static bool IsFeatureEnabled(ShaderFeatures featureMask, ShaderFeatures feature)
  883. {
  884. return (featureMask & feature) != 0;
  885. }
  886. }
  887. }