bool StripUnsupportedVariants(ShaderCompilerData compilerData)
        {
            // Dynamic GI is not supported so we can strip variants that have directional lightmap
            // enabled but not baked lightmap.
            if (compilerData.shaderKeywordSet.IsEnabled(m_DirectionalLightmap) &&
                !compilerData.shaderKeywordSet.IsEnabled(m_Lightmap))
            {
                return(true);
            }

            if (compilerData.shaderCompilerPlatform == ShaderCompilerPlatform.GLES20)
            {
                if (compilerData.shaderKeywordSet.IsEnabled(m_CascadeShadows))
                {
                    return(true);
                }
            }

            return(false);
        }
        protected override bool MatchVariant(ShaderCompilerData variantData)
        {
            TierData t;

            if (_data.TryGetValue(variantData.shaderCompilerPlatform, out t))
            {
                switch (variantData.graphicsTier)
                {
                case GraphicsTier.Tier1:
                    return(t.stripTier1);

                case GraphicsTier.Tier2:
                    return(t.stripTier2);

                case GraphicsTier.Tier3:
                    return(t.stripTier3);
                }
            }
            return(false);
        }
Exemplo n.º 3
0
        private bool IsExist(Dictionary <Shader, HashSet <ShaderVariantsInfo> > shaderVariants,
                             Shader shader, ShaderSnippetData snippet, ShaderCompilerData data)
        {
            var keywords        = data.shaderKeywordSet.GetShaderKeywords();
            var compiledKeyword = Convert(shader, keywords);
            var targetInfo      = new ShaderVariantsInfo(shader, snippet.passType, compiledKeyword.ToArray());

            if (compiledKeyword.Count == 0)
            {
                return(true);
            }
            HashSet <ShaderVariantsInfo> variantsHashSet = null;

            if (shaderVariants.TryGetValue(shader, out variantsHashSet))
            {
                bool flag = (variantsHashSet.Contains(targetInfo));
                return(flag);
            }
            return(false);
        }
Exemplo n.º 4
0
        bool StripUnsupportedVariants(ShaderCompilerData compilerData)
        {
            // Dynamic GI is not supported so we can strip variants that have directional lightmap
            // enabled but not baked lightmap.
            if (compilerData.shaderKeywordSet.IsEnabled(m_DirectionalLightmap) &&
                !compilerData.shaderKeywordSet.IsEnabled(m_Lightmap))
                return true;

            if (compilerData.shaderCompilerPlatform == ShaderCompilerPlatform.GLES20)
            {
                if (compilerData.shaderKeywordSet.IsEnabled(m_CascadeShadows))
                    return true;

                // GLES2 does not support VertexID that is required for full screen draw procedural pass;
                if (compilerData.shaderKeywordSet.IsEnabled(m_UseDrawProcedural))
                    return true;
            }

            return false;
        }
Exemplo n.º 5
0
        bool StripUnsupportedVariants(ShaderCompilerData compilerData)
        {
            // Dynamic GI is not supported so we can strip variants that have directional lightmap
            // enabled but not baked lightmap.
            if (compilerData.shaderKeywordSet.IsEnabled(m_DirectionalLightmap) &&
                !compilerData.shaderKeywordSet.IsEnabled(m_Lightmap))
            {
                return(true);
            }

            // As GLES2 has low amount of registers, we strip:
            if (compilerData.shaderCompilerPlatform == ShaderCompilerPlatform.GLES20)
            {
                // VertexID - as GLES2 does not support VertexID that is required for full screen draw procedural pass;
                if (compilerData.shaderKeywordSet.IsEnabled(m_UseDrawProcedural))
                {
                    return(true);
                }

                // Cascade shadows
                if (compilerData.shaderKeywordSet.IsEnabled(m_CascadeShadows))
                {
                    return(true);
                }

                // Detail
                if (compilerData.shaderKeywordSet.IsEnabled(m_LocalDetailMulx2) || compilerData.shaderKeywordSet.IsEnabled(m_LocalDetailScaled))
                {
                    return(true);
                }

                // Clear Coat
                if (compilerData.shaderKeywordSet.IsEnabled(m_LocalClearCoat) || compilerData.shaderKeywordSet.IsEnabled(m_LocalClearCoatMap))
                {
                    return(true);
                }
            }

            return(false);
        }
        public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList <ShaderCompilerData> inputData)
        {
            // TODO: Grab correct configuration/quality asset.
            HDRenderPipelineAsset hdPipelineAsset = GraphicsSettings.renderPipelineAsset as HDRenderPipelineAsset;

            if (hdPipelineAsset == null)
            {
                return;
            }

            // This test will also return if we are not using HDRenderPipelineAsset
            if (hdPipelineAsset == null || !hdPipelineAsset.allowShaderVariantStripping)
            {
                return;
            }

            int inputShaderVariantCount = inputData.Count;

            for (int i = 0; i < inputData.Count; ++i)
            {
                ShaderCompilerData input = inputData[i];

                bool removeInput = false;
                // Call list of strippers
                // Note that all strippers cumulate each other, so be aware of any conflict here
                foreach (BaseShaderPreprocessor material in materialList)
                {
                    if (material.ShadersStripper(hdPipelineAsset, shader, snippet, input))
                    {
                        removeInput = true;
                    }
                }

                if (removeInput)
                {
                    inputData.RemoveAt(i);
                    i--;
                }
            }
        }
Exemplo n.º 7
0
        public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList <ShaderCompilerData> inputData)
        {
            // This test will also return if we are not using HDRenderPipelineAsset
            if (m_CurrentHDRPAsset == null || !m_CurrentHDRPAsset.allowShaderVariantStripping)
            {
                return;
            }

            // Do we have a shader variant stripper function for this shader?
            VariantStrippingFunc stripperFunc = null;

            m_StripperFuncs.TryGetValue(shader.name, out stripperFunc);
            if (stripperFunc == null)
            {
                return;
            }

            int inputShaderVariantCount = inputData.Count;

            ShaderCompilerData workaround = inputData[0];

            for (int i = 0; i < inputData.Count; ++i)
            {
                ShaderCompilerData input = inputData[i];
                if (stripperFunc(m_CurrentHDRPAsset, shader, snippet, input))
                {
                    inputData.RemoveAt(i);
                    i--;
                }
            }

            // Currently if a certain snippet is completely stripped (for example if you remove a whole pass) other passes might get broken
            // To work around that, we make sure that we always have at least one variant.
            // TODO: Remove this one it is fixed
            if (inputData.Count == 0)
            {
                inputData.Add(workaround);
            }
        }
Exemplo n.º 8
0
        bool StripInvalidVariants(ShaderCompilerData compilerData)
        {
            bool isMainShadow       = compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadows);
            bool isAdditionalShadow = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightShadows);
            bool isShadowVariant    = isMainShadow || isAdditionalShadow;

            if (!isMainShadow && compilerData.shaderKeywordSet.IsEnabled(m_CascadeShadows))
            {
                return(true);
            }

            if (!isShadowVariant && compilerData.shaderKeywordSet.IsEnabled(m_SoftShadows))
            {
                return(true);
            }

            if (isAdditionalShadow && !compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightsPixel))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 9
0
        bool StripInvalidVariants(ShaderCompilerData compilerData)
        {
            bool isMainShadowNoCascades = compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadows);
            bool isMainShadowCascades   = compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsCascades);
            bool isMainShadowScreen     = compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsScreen);
            bool isMainShadow           = isMainShadowNoCascades || isMainShadowCascades || isMainShadowScreen;

            bool isAdditionalShadow = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightShadows);

            if (isAdditionalShadow && !(compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightsPixel) || compilerData.shaderKeywordSet.IsEnabled(m_ClusteredRendering) || compilerData.shaderKeywordSet.IsEnabled(m_DeferredStencil)))
            {
                return(true);
            }

            bool isShadowVariant = isMainShadow || isAdditionalShadow;

            if (!isShadowVariant && compilerData.shaderKeywordSet.IsEnabled(m_SoftShadows))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 10
0
    public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList <ShaderCompilerData> inputData)
    {
        bool shouldStripNonShadowmaskVariant = false;

        // We always use shadow-mask
        // Need to check if this is really okay:
        // With no mixed light around, HDRP may set SHADOWS_SHADOWMASK off and not allocate resource needed by shader with SHADOWS_SHADOWMASK turned on
        // However as we test nothing looks broken, let's keep this to make shader compile faster
        // For final build/release, let's not strip SHADOWS_SHADOWMASK off shaders to be on the safe side
        if (shader.name == "HDRP/Lit"
            ||
            shader.name == "HDRP/LayeredLit"
            ||
            shader.name == "HDRP/LitTessellation"
            ||
            shader.name == "HDRP/LayeredLitTessellation")
        {
            bool isGBufferPass             = snippet.passName == "GBuffer";
            bool isTransparentBackfacePass = snippet.passName == "TransparentBackface";
            bool isForwardPass             = snippet.passName == "Forward";
            if (isGBufferPass || isTransparentBackfacePass || isForwardPass)
            {
                shouldStripNonShadowmaskVariant = true;
            }
        }

        for (int i = 0; i < inputData.Count; ++i)
        {
            ShaderCompilerData input = inputData[i];
            if (ShouldStripShader(input, shouldStripNonShadowmaskVariant))
            {
                inputData.RemoveAt(i);
                i--;
            }
        }
    }
Exemplo n.º 11
0
        bool StripDeprecated(ShaderCompilerData compilerData)
        {
            if (compilerData.shaderKeywordSet.IsEnabled(m_DeprecatedVertexLights))
            {
                return(true);
            }

            if (compilerData.shaderKeywordSet.IsEnabled(m_DeprecatedShadowsCascade))
            {
                return(true);
            }

            if (compilerData.shaderKeywordSet.IsEnabled(m_DeprecatedShadowsEnabled))
            {
                return(true);
            }

            if (compilerData.shaderKeywordSet.IsEnabled(m_DeprecatedLocalShadowsEnabled))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 12
0
        public override bool ShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
        {
            // Strip every useless shadow configs
            var shadowInitParams = hdrpAsset.renderPipelineSettings.hdShadowInitParams;

            foreach (var shadowVariant in m_ShadowVariants)
            {
                if (shadowVariant.Key != shadowInitParams.shadowQuality)
                {
                    if (inputData.shaderKeywordSet.IsEnabled(shadowVariant.Value))
                    {
                        return(true);
                    }
                }
            }

            bool isSceneSelectionPass = snippet.passName == "SceneSelectionPass";

            if (isSceneSelectionPass)
            {
                return(true);
            }

            bool isMotionPass = snippet.passName == "Motion Vectors";

            if (!hdrpAsset.renderPipelineSettings.supportMotionVectors && isMotionPass)
            {
                return(true);
            }

            //bool isForwardPass = (snippet.passName == "Forward") || (snippet.passName == "ForwardOnly");

            if (inputData.shaderKeywordSet.IsEnabled(m_Transparent))
            {
                // If we are transparent we use cluster lighting and not tile lighting
                if (inputData.shaderKeywordSet.IsEnabled(m_TileLighting))
                {
                    return(true);
                }
            }
            else // Opaque
            {
                // Note: we can't assume anything regarding tile/cluster for opaque as multiple view could used different settings and it depends on MSAA
            }

            // TODO: If static lighting we can remove meta pass, but how to know that?

            // If we are in a release build, don't compile debug display variant
            // Also don't compile it if not requested by the render pipeline settings
            if ((/*!Debug.isDebugBuild || */ !hdrpAsset.renderPipelineSettings.supportRuntimeDebugDisplay) && inputData.shaderKeywordSet.IsEnabled(m_DebugDisplay))
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_LodFadeCrossFade) && !hdrpAsset.renderPipelineSettings.supportDitheringCrossFade)
            {
                return(true);
            }

            // Decal case

            // If decal support, remove unused variant
            if (hdrpAsset.renderPipelineSettings.supportDecals)
            {
                // Remove the no decal case
                if (inputData.shaderKeywordSet.IsEnabled(m_DecalsOFF))
                {
                    return(true);
                }

                // If decal but with 4RT remove 3RT variant and vice versa
                if (inputData.shaderKeywordSet.IsEnabled(m_Decals3RT) && hdrpAsset.renderPipelineSettings.decalSettings.perChannelMask)
                {
                    return(true);
                }

                if (inputData.shaderKeywordSet.IsEnabled(m_Decals4RT) && !hdrpAsset.renderPipelineSettings.decalSettings.perChannelMask)
                {
                    return(true);
                }
            }
            else
            {
                // If no decal support, remove decal variant
                if (inputData.shaderKeywordSet.IsEnabled(m_Decals3RT) || inputData.shaderKeywordSet.IsEnabled(m_Decals4RT))
                {
                    return(true);
                }
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_LightLayers) && !hdrpAsset.renderPipelineSettings.supportLightLayers)
            {
                return(true);
            }


            if (inputData.shaderKeywordSet.IsEnabled(m_WriteMSAADepth) && !hdrpAsset.renderPipelineSettings.supportMSAA)
            {
                return(true);
            }

            // Note that this is only going to affect the deferred shader and for a debug case, so it won't save much.
            if (inputData.shaderKeywordSet.IsEnabled(m_SubsurfaceScattering) && !hdrpAsset.renderPipelineSettings.supportSubsurfaceScattering)
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 13
0
        public override bool ShouldIncludeVariant(Shader shader, ShaderSnippetData snippet, ShaderCompilerData data)
        {
            var keywords    = data.shaderKeywordSet.ToList(shader);
            var shaderFound = false;

            foreach (var variant in variantCollections)
            {
                if (variant.shader == shader)
                {
                    shaderFound = true;
                    if (variant.keywords.HasSameElements(keywords))
                    {
                        return(true);
                    }

                    if (matchWithoutLocalKeywords && variant.globalKeywords.HasSameElements(keywords))
                    {
                        return(true);
                    }
                }
            }

            return(onlyStripShadersInCollections && !shaderFound);
        }
Exemplo n.º 14
0
        public void OnProcessComputeShader(ComputeShader shader, string kernelName, IList <ShaderCompilerData> inputData)
        {
            if (HDRenderPipeline.currentAsset == null)
            {
                return;
            }

            if (HDRenderPipelineGlobalSettings.Ensure(canCreateNewAsset: false) == null)
            {
                return;
            }

            // Discard any compute shader use for raytracing if none of the RP asset required it
            ComputeShader unused;

            if (!ShaderBuildPreprocessor.playerNeedRaytracing && ShaderBuildPreprocessor.computeShaderCache.TryGetValue(shader.GetInstanceID(), out unused))
            {
                return;
            }

            var exportLog = ShaderBuildPreprocessor.hdrpAssets.Count > 0 &&
                            (HDRenderPipelineGlobalSettings.instance.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled);

            Stopwatch shaderStripingWatch = new Stopwatch();

            shaderStripingWatch.Start();

            using (new ExportComputeShaderStrip(exportLog, "Temp/compute-shader-strip.json", shader, kernelName, inputData, this))
            {
                var inputShaderVariantCount = inputData.Count;
                var hdPipelineAssets        = ShaderBuildPreprocessor.hdrpAssets;

                if (hdPipelineAssets.Count == 0)
                {
                    return;
                }

                uint preStrippingCount = (uint)inputData.Count;

                for (int i = 0; i < inputShaderVariantCount;)
                {
                    ShaderCompilerData input = inputData[i];

                    bool removeInput = true;
                    foreach (var hdAsset in hdPipelineAssets)
                    {
                        if (!StripShader(hdAsset, shader, kernelName, input))
                        {
                            removeInput = false;
                            break;
                        }
                    }

                    if (removeInput)
                    {
                        inputData[i] = inputData[--inputShaderVariantCount];
                    }
                    else
                    {
                        ++i;
                    }
                }

                if (inputData is List <ShaderCompilerData> inputDataList)
                {
                    inputDataList.RemoveRange(inputShaderVariantCount, inputDataList.Count - inputShaderVariantCount);
                }
                else
                {
                    for (int i = inputData.Count - 1; i >= inputShaderVariantCount; --i)
                    {
                        inputData.RemoveAt(i);
                    }
                }

                if (HDRenderPipelineGlobalSettings.instance.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled)
                {
                    foreach (var hdAsset in hdPipelineAssets)
                    {
                        m_TotalVariantsInputCount  += preStrippingCount;
                        m_TotalVariantsOutputCount += (uint)inputData.Count;
                        LogShaderVariants(shader, kernelName, HDRenderPipelineGlobalSettings.instance.shaderVariantLogLevel, preStrippingCount, (uint)inputData.Count);
                    }
                }
            }
        }
Exemplo n.º 15
0
        public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList <ShaderCompilerData> inputData)
        {
            if (HDRenderPipeline.currentAsset == null)
            {
                return;
            }

            if (HDRenderPipelineGlobalSettings.Ensure(canCreateNewAsset: false) == null)
            {
                return;
            }

            var exportLog = ShaderBuildPreprocessor.hdrpAssets.Count > 0 &&
                            (HDRenderPipelineGlobalSettings.instance.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled);

            Stopwatch shaderStripingWatch = new Stopwatch();

            shaderStripingWatch.Start();

            using (new ExportShaderStrip(exportLog, "Temp/shader-strip.json", shader, snippet, inputData, this))
            {
                // TODO: Grab correct configuration/quality asset.
                var hdPipelineAssets = ShaderBuildPreprocessor.hdrpAssets;

                if (hdPipelineAssets.Count == 0)
                {
                    return;
                }

                uint preStrippingCount = (uint)inputData.Count;

                // Test if striping is enabled in any of the found HDRP assets.
                if (hdPipelineAssets.Count == 0 || !hdPipelineAssets.Any(a => a.allowShaderVariantStripping))
                {
                    return;
                }

                var inputShaderVariantCount = inputData.Count;
                for (int i = 0; i < inputShaderVariantCount;)
                {
                    ShaderCompilerData input = inputData[i];

                    // Remove the input by default, until we find a HDRP Asset in the list that needs it.
                    bool removeInput = true;

                    foreach (var hdAsset in hdPipelineAssets)
                    {
                        var strippedByPreprocessor = false;

                        // Call list of strippers
                        // Note that all strippers cumulate each other, so be aware of any conflict here
                        foreach (BaseShaderPreprocessor shaderPreprocessor in shaderProcessorsList)
                        {
                            if (shaderPreprocessor.ShadersStripper(hdAsset, shader, snippet, input))
                            {
                                strippedByPreprocessor = true;
                                break;
                            }
                        }

                        if (!strippedByPreprocessor)
                        {
                            removeInput = false;
                            break;
                        }
                    }

                    if (removeInput)
                    {
                        inputData[i] = inputData[--inputShaderVariantCount];
                    }
                    else
                    {
                        ++i;
                    }
                }

                if (inputData is List <ShaderCompilerData> inputDataList)
                {
                    inputDataList.RemoveRange(inputShaderVariantCount, inputDataList.Count - inputShaderVariantCount);
                }
                else
                {
                    for (int i = inputData.Count - 1; i >= inputShaderVariantCount; --i)
                    {
                        inputData.RemoveAt(i);
                    }
                }

                if (HDRenderPipelineGlobalSettings.instance.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled)
                {
                    foreach (var hdAsset in hdPipelineAssets)
                    {
                        m_TotalVariantsInputCount  += preStrippingCount;
                        m_TotalVariantsOutputCount += (uint)inputData.Count;
                        LogShaderVariants(shader, snippet, HDRenderPipelineGlobalSettings.instance.shaderVariantLogLevel, preStrippingCount, (uint)inputData.Count);
                    }
                }
            }

            shaderStripingWatch.Stop();
            shaderPreprocessed?.Invoke(shader, snippet, inputData.Count, shaderStripingWatch.Elapsed.TotalMilliseconds);
        }
Exemplo n.º 16
0
        protected override bool DoShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
        {
            // CAUTION: Pass Name and Lightmode name must match in master node and .shader.
            // HDRP use LightMode to do drawRenderer and pass name is use here for stripping!

            var globalSettings = HDRenderPipelineGlobalSettings.Ensure();

            // Remove editor only pass
            bool isSceneSelectionPass = snippet.passName == "SceneSelectionPass";
            bool isScenePickingPass   = snippet.passName == "ScenePickingPass";
            bool metaPassUnused       = (snippet.passName == "META") && (SupportedRenderingFeatures.active.enlighten == false ||
                                                                         ((int)SupportedRenderingFeatures.active.lightmapBakeTypes | (int)LightmapBakeType.Realtime) == 0);
            bool editorVisualization = inputData.shaderKeywordSet.IsEnabled(m_EditorVisualization);

            if (isSceneSelectionPass || isScenePickingPass || metaPassUnused || editorVisualization)
            {
                return(true);
            }

            // CAUTION: We can't identify transparent material in the stripped in a general way.
            // Shader Graph don't produce any keyword - However it will only generate the pass that are required, so it already handle transparent (Note that shader Graph still define _SURFACE_TYPE_TRANSPARENT but as a #define)
            // For inspector version of shader, we identify transparent with a shader feature _SURFACE_TYPE_TRANSPARENT.
            // Only our Lit (and inherited) shader use _SURFACE_TYPE_TRANSPARENT, so the specific stripping based on this keyword is in LitShadePreprocessor.
            // Here we can't strip based on opaque or transparent but we will strip based on HDRP Asset configuration.

            bool isMotionPass = snippet.passName == "MotionVectors";

            if (isMotionPass && !hdrpAsset.currentPlatformRenderPipelineSettings.supportMotionVectors)
            {
                return(true);
            }

            bool isDistortionPass = snippet.passName == "DistortionVectors";

            if (isDistortionPass && !hdrpAsset.currentPlatformRenderPipelineSettings.supportDistortion)
            {
                return(true);
            }

            bool isTransparentBackface = snippet.passName == "TransparentBackface";

            if (isTransparentBackface && !hdrpAsset.currentPlatformRenderPipelineSettings.supportTransparentBackface)
            {
                return(true);
            }

            bool isTransparentPrepass = snippet.passName == "TransparentDepthPrepass";

            if (isTransparentPrepass && !hdrpAsset.currentPlatformRenderPipelineSettings.supportTransparentDepthPrepass)
            {
                return(true);
            }

            bool isTransparentPostpass = snippet.passName == "TransparentDepthPostpass";

            if (isTransparentPostpass && !hdrpAsset.currentPlatformRenderPipelineSettings.supportTransparentDepthPostpass)
            {
                return(true);
            }

            bool isRayTracingPrepass = snippet.passName == "RayTracingPrepass";

            if (isRayTracingPrepass && !hdrpAsset.currentPlatformRenderPipelineSettings.supportRayTracing)
            {
                return(true);
            }

            // If requested by the render pipeline settings, or if we are in a release build,
            // don't compile fullscreen debug display variant
            bool isFullScreenDebugPass = snippet.passName == "FullScreenDebug";

            if (isFullScreenDebugPass && (!Debug.isDebugBuild || !globalSettings.supportRuntimeDebugDisplay))
            {
                return(true);
            }

            // Debug Display shader is currently the longest shader to compile, so we allow users to disable it at runtime.
            // We also don't want it in release build.
            // However our AOV API rely on several debug display shader. In case AOV API is requested at runtime (like for the Graphics Compositor)
            // we allow user to make explicit request for it and it bypass other request
            if (!hdrpAsset.currentPlatformRenderPipelineSettings.supportRuntimeAOVAPI)
            {
                if ((!Debug.isDebugBuild || !globalSettings.supportRuntimeDebugDisplay) && inputData.shaderKeywordSet.IsEnabled(m_DebugDisplay))
                {
                    return(true);
                }
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_LodFadeCrossFade) && !hdrpAsset.currentPlatformRenderPipelineSettings.supportDitheringCrossFade)
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_WriteMSAADepth) && (hdrpAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly))
            {
                return(true);
            }

            // Note that this is only going to affect the deferred shader and for a debug case, so it won't save much.
            if (inputData.shaderKeywordSet.IsEnabled(m_SubsurfaceScattering) && !hdrpAsset.currentPlatformRenderPipelineSettings.supportSubsurfaceScattering)
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_Transparent))
            {
                // If transparent we don't need the depth only pass
                bool isDepthOnlyPass = snippet.passName == "DepthForwardOnly";
                if (isDepthOnlyPass)
                {
                    return(true);
                }

                // If transparent we don't need the motion vector pass
                if (isMotionPass)
                {
                    return(true);
                }

                // If we are transparent we use cluster lighting and not tile lighting
                if (inputData.shaderKeywordSet.IsEnabled(m_TileLighting))
                {
                    return(true);
                }
            }
            else // Opaque
            {
                // If opaque, we never need transparent specific passes (even in forward only mode)
                bool isTransparentForwardPass = isTransparentPostpass || isTransparentBackface || isTransparentPrepass || isDistortionPass;
                if (isTransparentForwardPass)
                {
                    return(true);
                }

                // TODO: Should we remove Cluster version if we know MSAA is disabled ? This prevent to manipulate LightLoop Settings (useFPTL option)
                // For now comment following code
                // if (inputData.shaderKeywordSet.IsEnabled(m_ClusterLighting) && !hdrpAsset.currentPlatformRenderPipelineSettings.supportMSAA)
                //    return true;
            }

            // SHADOW

            // Strip every useless shadow configs
            var shadowInitParams = hdrpAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams;

            foreach (var shadowVariant in m_ShadowKeywords.ShadowVariants)
            {
                if (shadowVariant.Key != shadowInitParams.shadowFilteringQuality)
                {
                    if (inputData.shaderKeywordSet.IsEnabled(shadowVariant.Value))
                    {
                        return(true);
                    }
                }
            }

            // Screen space shadow variant is exclusive, either we have a variant with dynamic if that support screen space shadow or not
            // either we have a variant that don't support at all. We can't have both at the same time.
            if (inputData.shaderKeywordSet.IsEnabled(m_ScreenSpaceShadowOFFKeywords) && shadowInitParams.supportScreenSpaceShadows)
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_ScreenSpaceShadowONKeywords) && !shadowInitParams.supportScreenSpaceShadows)
            {
                return(true);
            }

            // DECAL

            // Strip the decal prepass variant when decals are disabled
            if (inputData.shaderKeywordSet.IsEnabled(m_WriteDecalBuffer) &&
                !(hdrpAsset.currentPlatformRenderPipelineSettings.supportDecals && hdrpAsset.currentPlatformRenderPipelineSettings.supportDecalLayers))
            {
                return(true);
            }

            // If decal support, remove unused variant
            if (hdrpAsset.currentPlatformRenderPipelineSettings.supportDecals)
            {
                // Remove the no decal case
                if (inputData.shaderKeywordSet.IsEnabled(m_DecalsOFF))
                {
                    return(true);
                }

                // If decal but with 4RT remove 3RT variant and vice versa for both Material and Decal Material
                if (inputData.shaderKeywordSet.IsEnabled(m_Decals3RT) && hdrpAsset.currentPlatformRenderPipelineSettings.decalSettings.perChannelMask)
                {
                    return(true);
                }

                if (inputData.shaderKeywordSet.IsEnabled(m_Decals4RT) && !hdrpAsset.currentPlatformRenderPipelineSettings.decalSettings.perChannelMask)
                {
                    return(true);
                }

                // Remove the surface gradient blending if not enabled
                if (inputData.shaderKeywordSet.IsEnabled(m_DecalSurfaceGradient) && !hdrpAsset.currentPlatformRenderPipelineSettings.supportSurfaceGradient)
                {
                    return(true);
                }
            }
            else
            {
                // Strip if it is a decal pass
                bool isDBufferMesh = snippet.passName == "DBufferMesh";
                bool isDecalMeshForwardEmissive      = snippet.passName == "DecalMeshForwardEmissive";
                bool isDBufferProjector              = snippet.passName == "DBufferProjector";
                bool isDecalProjectorForwardEmissive = snippet.passName == "DecalProjectorForwardEmissive";
                if (isDBufferMesh || isDecalMeshForwardEmissive || isDBufferProjector || isDecalProjectorForwardEmissive)
                {
                    return(true);
                }

                // If no decal support, remove decal variant
                if (inputData.shaderKeywordSet.IsEnabled(m_Decals3RT) || inputData.shaderKeywordSet.IsEnabled(m_Decals4RT))
                {
                    return(true);
                }

                // Remove the surface gradient blending
                if (inputData.shaderKeywordSet.IsEnabled(m_DecalSurfaceGradient))
                {
                    return(true);
                }
            }

            // Global Illumination
            if (inputData.shaderKeywordSet.IsEnabled(m_ProbeVolumesL1) &&
                (!hdrpAsset.currentPlatformRenderPipelineSettings.supportProbeVolume || !globalSettings.supportProbeVolumes || hdrpAsset.currentPlatformRenderPipelineSettings.probeVolumeSHBands != ProbeVolumeSHBands.SphericalHarmonicsL1))
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_ProbeVolumesL2) &&
                (!hdrpAsset.currentPlatformRenderPipelineSettings.supportProbeVolume || !globalSettings.supportProbeVolumes || hdrpAsset.currentPlatformRenderPipelineSettings.probeVolumeSHBands != ProbeVolumeSHBands.SphericalHarmonicsL2))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 17
0
        // Modify this function to add more stripping clauses
        internal bool StripShader(HDRenderPipelineAsset hdAsset, ComputeShader shader, string kernelName, ShaderCompilerData inputData)
        {
            // Strip every useless shadow configs
            var shadowInitParams = hdAsset.currentPlatformRenderPipelineSettings.hdShadowInitParams;

            foreach (var shadowVariant in m_ShadowKeywords.ShadowVariants)
            {
                if (shadowVariant.Key != shadowInitParams.shadowFilteringQuality)
                {
                    if (inputData.shaderKeywordSet.IsEnabled(shadowVariant.Value))
                    {
                        return(true);
                    }
                }
            }

            // Screen space shadow variant is exclusive, either we have a variant with dynamic if that support screen space shadow or not
            // either we have a variant that don't support at all. We can't have both at the same time.
            if (inputData.shaderKeywordSet.IsEnabled(m_ScreenSpaceShadowOFFKeywords) && shadowInitParams.supportScreenSpaceShadows)
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_MSAA) && (hdAsset.currentPlatformRenderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly))
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_ScreenSpaceShadowONKeywords) && !shadowInitParams.supportScreenSpaceShadows)
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_EnableAlpha) && !hdAsset.currentPlatformRenderPipelineSettings.SupportsAlpha())
            {
                return(true);
            }

            // Global Illumination
            if (inputData.shaderKeywordSet.IsEnabled(m_ProbeVolumesL1) &&
                (!hdAsset.currentPlatformRenderPipelineSettings.supportProbeVolume || hdAsset.currentPlatformRenderPipelineSettings.probeVolumeSHBands != ProbeVolumeSHBands.SphericalHarmonicsL1))
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_ProbeVolumesL2) &&
                (!hdAsset.currentPlatformRenderPipelineSettings.supportProbeVolume || hdAsset.currentPlatformRenderPipelineSettings.probeVolumeSHBands != ProbeVolumeSHBands.SphericalHarmonicsL2))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 18
0
        bool StripUnused(ShaderFeatures features, Shader shader, ShaderSnippetData snippetData, ShaderCompilerData compilerData)
        {
            if (StripUnusedFeatures(features, shader, snippetData, compilerData))
            {
                return(true);
            }

            if (StripInvalidVariants(compilerData))
            {
                return(true);
            }

            if (StripUnsupportedVariants(compilerData))
            {
                return(true);
            }

            if (StripUnusedPass(features, snippetData))
            {
                return(true);
            }

            // Strip terrain holes
            // TODO: checking for the string name here is expensive
            // maybe we can rename alpha clip keyword name to be specific to terrain?
            if (compilerData.shaderKeywordSet.IsEnabled(m_AlphaTestOn) &&
                !IsFeatureEnabled(features, ShaderFeatures.TerrainHoles) &&
                shader.name.Contains(kTerrainShaderName))
            {
                return(true);
            }

            // TODO: Test against lightMode tag instead.
            if (snippetData.passName == kPassNameGBuffer)
            {
                if (!IsFeatureEnabled(features, ShaderFeatures.DeferredShading))
                {
                    return(true);
                }

                // Do not strip accurateGbufferNormals on Mobile Vulkan as some GPUs do not support R8G8B8A8_SNorm, which then force us to use accurateGbufferNormals
                if (!IsFeatureEnabled(features, ShaderFeatures.DeferredWithAccurateGbufferNormals) && compilerData.shaderKeywordSet.IsEnabled(m_GbufferNormalsOct) && compilerData.shaderCompilerPlatform != ShaderCompilerPlatform.Vulkan)
                {
                    return(true);
                }
                if (!IsFeatureEnabled(features, ShaderFeatures.DeferredWithoutAccurateGbufferNormals) && !compilerData.shaderKeywordSet.IsEnabled(m_GbufferNormalsOct))
                {
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 19
0
        public override bool ShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
        {
            // Strip every useless shadow configs
            var shadowInitParams = hdrpAsset.renderPipelineSettings.hdShadowInitParams;

            foreach (var shadowVariant in m_ShadowVariants)
            {
                if (shadowVariant.Key != shadowInitParams.shadowQuality)
                {
                    if (inputData.shaderKeywordSet.IsEnabled(shadowVariant.Value))
                    {
                        return(true);
                    }
                }
            }

            // CAUTION: Pass Name and Lightmode name must match in master node and .shader.
            // HDRP use LightMode to do drawRenderer and pass name is use here for stripping!

            // Remove editor only pass
            bool isSceneSelectionPass = snippet.passName == "SceneSelectionPass";

            if (isSceneSelectionPass)
            {
                return(true);
            }

            // CAUTION: We can't identify transparent material in the stripped in a general way.
            // Shader Graph don't produce any keyword - However it will only generate the pass that are required, so it already handle transparent (Note that shader Graph still define _SURFACE_TYPE_TRANSPARENT but as a #define)
            // For inspector version of shader, we identify transparent with a shader feature _SURFACE_TYPE_TRANSPARENT.
            // Only our Lit (and inherited) shader use _SURFACE_TYPE_TRANSPARENT, so the specific stripping based on this keyword is in LitShadePreprocessor.
            // Here we can't strip based on opaque or transparent but we will strip based on HDRP Asset configuration.

            bool isMotionPass          = snippet.passName == "MotionVectors";
            bool isTransparentPrepass  = snippet.passName == "TransparentDepthPrepass";
            bool isTransparentPostpass = snippet.passName == "TransparentDepthPostpass";
            bool isTransparentBackface = snippet.passName == "TransparentBackface";
            bool isDistortionPass      = snippet.passName == "DistortionVectors";

            if (isMotionPass && !hdrpAsset.renderPipelineSettings.supportMotionVectors)
            {
                return(true);
            }

            if (isDistortionPass && !hdrpAsset.renderPipelineSettings.supportDistortion)
            {
                return(true);
            }

            if (isTransparentBackface && !hdrpAsset.renderPipelineSettings.supportTransparentBackface)
            {
                return(true);
            }

            if (isTransparentPrepass && !hdrpAsset.renderPipelineSettings.supportTransparentDepthPrepass)
            {
                return(true);
            }

            if (isTransparentPostpass && !hdrpAsset.renderPipelineSettings.supportTransparentDepthPostpass)
            {
                return(true);
            }

            // If we are in a release build, don't compile debug display variant
            // Also don't compile it if not requested by the render pipeline settings
            if ((/*!Debug.isDebugBuild || */ !hdrpAsset.renderPipelineSettings.supportRuntimeDebugDisplay) && inputData.shaderKeywordSet.IsEnabled(m_DebugDisplay))
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_LodFadeCrossFade) && !hdrpAsset.renderPipelineSettings.supportDitheringCrossFade)
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_WriteMSAADepth) && !hdrpAsset.renderPipelineSettings.supportMSAA)
            {
                return(true);
            }

            // Note that this is only going to affect the deferred shader and for a debug case, so it won't save much.
            if (inputData.shaderKeywordSet.IsEnabled(m_SubsurfaceScattering) && !hdrpAsset.renderPipelineSettings.supportSubsurfaceScattering)
            {
                return(true);
            }

            // DECAL

            // Identify when we compile a decal shader
            bool isDecal3RTPass = false;
            bool isDecal4RTPass = false;
            bool isDecalPass    = false;

            if (snippet.passName.Contains("DBufferMesh") || snippet.passName.Contains("DBufferProjector"))
            {
                isDecalPass = true;

                // All decal pass name:
                // "ShaderGraph_DBufferMesh3RT" "ShaderGraph_DBufferProjector3RT" "DBufferMesh_3RT"
                // "DBufferProjector_M" "DBufferProjector_AO" "DBufferProjector_MAO" "DBufferProjector_S" "DBufferProjector_MS" "DBufferProjector_AOS" "DBufferProjector_MAOS"
                // "DBufferMesh_M" "DBufferMesh_AO" "DBufferMesh_MAO" "DBufferMesh_S" "DBufferMesh_MS" "DBufferMesh_AOS""DBufferMesh_MAOS"

                // Caution: As mention in Decal.shader DBufferProjector_S is also DBufferProjector_3RT so this pass is both 4RT and 3RT
                // there is a multi-compile to handle this pass, so it will be correctly removed by testing m_Decals3RT or m_Decals4RT
                if (snippet.passName != "DBufferProjector_S")
                {
                    isDecal3RTPass = snippet.passName.Contains("3RT");
                    isDecal4RTPass = !isDecal3RTPass;
                }
            }

            // If decal support, remove unused variant
            if (hdrpAsset.renderPipelineSettings.supportDecals)
            {
                // Remove the no decal case
                if (inputData.shaderKeywordSet.IsEnabled(m_DecalsOFF))
                {
                    return(true);
                }

                // If decal but with 4RT remove 3RT variant and vice versa
                if ((inputData.shaderKeywordSet.IsEnabled(m_Decals3RT) || isDecal3RTPass) && hdrpAsset.renderPipelineSettings.decalSettings.perChannelMask)
                {
                    return(true);
                }

                if ((inputData.shaderKeywordSet.IsEnabled(m_Decals4RT) || isDecal4RTPass) && !hdrpAsset.renderPipelineSettings.decalSettings.perChannelMask)
                {
                    return(true);
                }
            }
            else
            {
                if (isDecalPass)
                {
                    return(true);
                }

                // If no decal support, remove decal variant
                if (inputData.shaderKeywordSet.IsEnabled(m_Decals3RT) || inputData.shaderKeywordSet.IsEnabled(m_Decals4RT))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 20
0
        public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList <ShaderCompilerData> inputData)
        {
            // TODO: Grab correct configuration/quality asset.
            var hdPipelineAssets = ShaderBuildPreprocessor.hdrpAssets;

            if (hdPipelineAssets.Count == 0)
            {
                return;
            }

            uint preStrippingCount = (uint)inputData.Count;

            // Test if striping is enabled in any of the found HDRP assets.
            if (hdPipelineAssets.Count == 0 || !hdPipelineAssets.Any(a => a.allowShaderVariantStripping))
            {
                return;
            }

            int inputShaderVariantCount = inputData.Count;

            for (int i = 0; i < inputShaderVariantCount;)
            {
                ShaderCompilerData input = inputData[i];

                // Remove the input by default, until we find a HDRP Asset in the list that needs it.
                bool removeInput = true;

                foreach (var hdAsset in hdPipelineAssets)
                {
                    var strippedByPreprocessor = false;

                    // Call list of strippers
                    // Note that all strippers cumulate each other, so be aware of any conflict here
                    foreach (BaseShaderPreprocessor shaderPreprocessor in shaderProcessorsList)
                    {
                        if (shaderPreprocessor.ShadersStripper(hdAsset, shader, snippet, input))
                        {
                            strippedByPreprocessor = true;
                            break;
                        }
                    }

                    if (!strippedByPreprocessor)
                    {
                        removeInput = false;
                        break;
                    }
                }

                if (removeInput)
                {
                    inputData[i] = inputData[--inputShaderVariantCount];
                }
                else
                {
                    ++i;
                }
            }

            if (inputData is List <ShaderCompilerData> inputDataList)
            {
                inputDataList.RemoveRange(inputShaderVariantCount, inputDataList.Count - inputShaderVariantCount);
            }
            else
            {
                for (int i = inputData.Count - 1; i >= inputShaderVariantCount; --i)
                {
                    inputData.RemoveAt(i);
                }
            }

            foreach (var hdAsset in hdPipelineAssets)
            {
                if (hdAsset.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled)
                {
                    m_TotalVariantsInputCount  += preStrippingCount;
                    m_TotalVariantsOutputCount += (uint)inputData.Count;
                    LogShaderVariants(shader, snippet, hdAsset.shaderVariantLogLevel, preStrippingCount, (uint)inputData.Count);
                }
            }
        }
Exemplo n.º 21
0
        bool StripUnusedFeatures(ShaderFeatures features, Shader shader, ShaderSnippetData snippetData, ShaderCompilerData compilerData)
        {
            // strip main light shadows, cascade and screen variants
            if (!IsFeatureEnabled(features, ShaderFeatures.MainLightShadows))
            {
                if (compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadows))
                {
                    return(true);
                }

                if (compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsCascades))
                {
                    return(true);
                }

                if (compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsScreen))
                {
                    return(true);
                }

                if (snippetData.passType == PassType.ShadowCaster && !compilerData.shaderKeywordSet.IsEnabled(m_CastingPunctualLightShadow))
                {
                    return(true);
                }
            }

            if (!IsFeatureEnabled(features, ShaderFeatures.SoftShadows) &&
                compilerData.shaderKeywordSet.IsEnabled(m_SoftShadows))
            {
                return(true);
            }

            // Left for backward compatibility
            if (compilerData.shaderKeywordSet.IsEnabled(m_MixedLightingSubtractive) &&
                !IsFeatureEnabled(features, ShaderFeatures.MixedLighting))
            {
                return(true);
            }

            if (compilerData.shaderKeywordSet.IsEnabled(m_UseFastSRGBLinearConversion) &&
                !IsFeatureEnabled(features, ShaderFeatures.UseFastSRGBLinearConversion))
            {
                return(true);
            }

            // Strip here only if mixed lighting is disabled
            // No need to check here if actually used by scenes as this taken care by builtin stripper
            if ((compilerData.shaderKeywordSet.IsEnabled(m_LightmapShadowMixing) ||
                 compilerData.shaderKeywordSet.IsEnabled(m_ShadowsShadowMask)) &&
                !IsFeatureEnabled(features, ShaderFeatures.MixedLighting))
            {
                return(true);
            }

            if (compilerData.shaderKeywordSet.IsEnabled(m_LightLayers) &&
                !IsFeatureEnabled(features, ShaderFeatures.LightLayers))
            {
                return(true);
            }

            // No additional light shadows
            bool isAdditionalLightShadow = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightShadows);

            if (!IsFeatureEnabled(features, ShaderFeatures.AdditionalLightShadows) && isAdditionalLightShadow)
            {
                return(true);
            }

            bool isPunctualLightShadowCasterPass = (snippetData.passType == PassType.ShadowCaster) && compilerData.shaderKeywordSet.IsEnabled(m_CastingPunctualLightShadow);

            if (!IsFeatureEnabled(features, ShaderFeatures.AdditionalLightShadows) && isPunctualLightShadowCasterPass)
            {
                return(true);
            }

            bool isDeferredShadow = compilerData.shaderKeywordSet.IsEnabled(m_DeferredLightShadows);

            if (!IsFeatureEnabled(features, ShaderFeatures.AdditionalLightShadows) && isDeferredShadow)
            {
                return(true);
            }

            // Additional light are shaded per-vertex or per-pixel.
            bool isFeaturePerPixelLightingEnabled  = IsFeatureEnabled(features, ShaderFeatures.AdditionalLights);
            bool isFeaturePerVertexLightingEnabled = IsFeatureEnabled(features, ShaderFeatures.VertexLighting);
            bool isAdditionalLightPerPixel         = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightsPixel);
            bool isAdditionalLightPerVertex        = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightsVertex);

            // Strip if Per-Pixel lighting is NOT used in the project and the
            // Per-Pixel (_ADDITIONAL_LIGHTS) or additional shadows (_ADDITIONAL_LIGHT_SHADOWS)
            // variants are enabled in the shader.
            if (!isFeaturePerPixelLightingEnabled && (isAdditionalLightPerPixel || isAdditionalLightShadow))
            {
                return(true);
            }

            // Strip if Per-Vertex lighting is NOT used in the project and the
            // Per-Vertex (_ADDITIONAL_LIGHTS_VERTEX) variant is enabled in the shader.
            if (!isFeaturePerVertexLightingEnabled && isAdditionalLightPerVertex)
            {
                return(true);
            }

            // Screen Space Shadows
            if (!IsFeatureEnabled(features, ShaderFeatures.ScreenSpaceShadows) &&
                compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadowsScreen))
            {
                return(true);
            }

            // Screen Space Occlusion
            if (!IsFeatureEnabled(features, ShaderFeatures.ScreenSpaceOcclusion) &&
                compilerData.shaderKeywordSet.IsEnabled(m_ScreenSpaceOcclusion))
            {
                return(true);
            }

            return(false);
        }
        public override bool ShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
        {
            bool isGBufferPass = snippet.passName == "GBuffer";
            //bool isForwardPass = snippet.passName == "Forward";
            bool isDepthOnlyPass          = snippet.passName == "DepthOnly";
            bool isTransparentForwardPass = snippet.passName == "TransparentDepthPostpass" || snippet.passName == "TransparentBackface" || snippet.passName == "TransparentDepthPrepass";

            // When using forward only, we never need GBuffer pass (only Forward)
            if (hdrpAsset.renderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && isGBufferPass)
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_Transparent))
            {
                // If transparent, we never need GBuffer pass.
                if (isGBufferPass)
                {
                    return(true);
                }
            }
            else // Opaque
            {
                // If opaque, we never need transparent specific passes (even in forward only mode)
                if (isTransparentForwardPass)
                {
                    return(true);
                }

                // TODO: This check is disabled currently as it doesn't work. We have issue with lit VFX from VFX graph not working correctly, mean we are too agressive on
                // removal. Need to check why.
                // When we are in deferred (i.e !hdrpAsset.renderPipelineSettings.supportOnlyForward), we only support tile lighting
                //if (!hdrpAsset.renderPipelineSettings.supportOnlyForward && inputData.shaderKeywordSet.IsEnabled(m_ClusterLighting))
                //    return true;

                if (isDepthOnlyPass)
                {
                    // When we are full forward, we don't have depth prepass without writeNormalBuffer
                    if (hdrpAsset.renderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && !inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer))
                    {
                        return(true);
                    }
                }

                // TODO: add an option to say we are using only the deferred shader variant (for Lit)
                //if (0)
                {
                    // If opaque and not forward only, then we only need the forward debug pass.
                    //if (isForwardPass && !inputData.shaderKeywordSet.IsEnabled(m_DebugDisplay))
                    //    return true;
                }
            }

            // TODO: Tests for later
            // We need to find a way to strip useless shader features for passes/shader stages that don't need them (example, vertex shaders won't ever need SSS Feature flag)
            // This causes several problems:
            // - Runtime code that "finds" shader variants based on feature flags might not find them anymore... thus fall backing to the "let's give a score to variant" code path that may find the wrong variant.
            // - Another issue is that if a feature is declared without a "_" fall-back, if we strip the other variants, none may be left to use! This needs to be changed on our side.
            //if (snippet.shaderType == ShaderType.Vertex && inputData.shaderKeywordSet.IsEnabled(m_FeatureSSS))
            //    return true;

            return(false);
        }
Exemplo n.º 23
0
        public override bool ShouldStripVariant(Shader shader, ShaderSnippetData snippet, ShaderCompilerData data)
        {
            var shaderPath = AssetDatabase.GetAssetPath(shader);

            return(paths.Any(x => x.IsMatch(shaderPath)));
        }
Exemplo n.º 24
0
        bool StripUnused(ShaderFeatures features, Shader shader, ShaderSnippetData snippetData, ShaderCompilerData compilerData)
        {
            if (StripUnusedShader(features, shader, compilerData))
            {
                return(true);
            }

            if (StripUnusedPass(features, snippetData))
            {
                return(true);
            }

            if (StripUnusedFeatures(features, shader, compilerData))
            {
                return(true);
            }

            if (StripUnsupportedVariants(compilerData))
            {
                return(true);
            }

            if (StripInvalidVariants(compilerData))
            {
                return(true);
            }

            if (StripDeprecated(compilerData))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 25
0
        protected override bool DoShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
        {
            // If ray tracing is disabled, strip all ray tracing shaders
            if (hdrpAsset.currentPlatformRenderPipelineSettings.supportRayTracing == false)
            {
                // If transparent we don't need the depth only pass
                if (snippet.passName == "IndirectDXR" ||
                    snippet.passName == "ForwardDXR" ||
                    snippet.passName == "VisibilityDXR" ||
                    snippet.passName == "PathTracingDXR" ||
                    snippet.passName == "GBufferDXR" ||
                    snippet.passName == "SubSurfaceDXR")
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 26
0
        public void OnProcessComputeShader(ComputeShader shader, string kernelName, IList <ShaderCompilerData> inputData)
        {
            if (HDRenderPipeline.currentAsset == null)
            {
                return;
            }

            var exportLog = ShaderBuildPreprocessor.hdrpAssets.Count > 0 &&
                            ShaderBuildPreprocessor.hdrpAssets.Any(hdrpAsset => hdrpAsset.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled);

            Stopwatch shaderStripingWatch = new Stopwatch();

            shaderStripingWatch.Start();

            using (new ExportComputeShaderStrip(exportLog, "Temp/compute-shader-strip.json", shader, kernelName, inputData, this))
            {
                var inputShaderVariantCount = inputData.Count;
                var hdPipelineAssets        = ShaderBuildPreprocessor.hdrpAssets;

                if (hdPipelineAssets.Count == 0)
                {
                    return;
                }

                uint preStrippingCount = (uint)inputData.Count;

                for (int i = 0; i < inputShaderVariantCount;)
                {
                    ShaderCompilerData input = inputData[i];

                    bool removeInput = true;
                    foreach (var hdAsset in hdPipelineAssets)
                    {
                        if (!StripShader(hdAsset, shader, kernelName, input))
                        {
                            removeInput = false;
                            break;
                        }
                    }

                    if (removeInput)
                    {
                        inputData[i] = inputData[--inputShaderVariantCount];
                    }
                    else
                    {
                        ++i;
                    }
                }

                if (inputData is List <ShaderCompilerData> inputDataList)
                {
                    inputDataList.RemoveRange(inputShaderVariantCount, inputDataList.Count - inputShaderVariantCount);
                }
                else
                {
                    for (int i = inputData.Count - 1; i >= inputShaderVariantCount; --i)
                    {
                        inputData.RemoveAt(i);
                    }
                }

                foreach (var hdAsset in hdPipelineAssets)
                {
                    if (hdAsset.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled)
                    {
                        m_TotalVariantsInputCount  += preStrippingCount;
                        m_TotalVariantsOutputCount += (uint)inputData.Count;
                        LogShaderVariants(shader, kernelName, hdAsset.shaderVariantLogLevel, preStrippingCount, (uint)inputData.Count);
                    }
                }
            }
        }
Exemplo n.º 27
0
        bool StripUnusedFeatures(ShaderFeatures features, Shader shader, ShaderCompilerData compilerData)
        {
            // strip main light shadows and cascade variants
            if (!CoreUtils.HasFlag(features, ShaderFeatures.MainLightShadows))
            {
                if (compilerData.shaderKeywordSet.IsEnabled(m_MainLightShadows))
                {
                    return(true);
                }

                if (compilerData.shaderKeywordSet.IsEnabled(m_CascadeShadows))
                {
                    return(true);
                }
            }

            bool isAdditionalLightPerVertex = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightsVertex);
            bool isAdditionalLightPerPixel  = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightsPixel);
            bool isAdditionalLightShadow    = compilerData.shaderKeywordSet.IsEnabled(m_AdditionalLightShadows);

            // Additional light are shaded per-vertex. Strip additional lights per-pixel and shadow variants
            if (CoreUtils.HasFlag(features, ShaderFeatures.VertexLighting) &&
                (isAdditionalLightPerPixel || isAdditionalLightShadow))
            {
                return(true);
            }

            // No additional lights
            if (!CoreUtils.HasFlag(features, ShaderFeatures.AdditionalLights) &&
                (isAdditionalLightPerPixel || isAdditionalLightPerVertex || isAdditionalLightShadow))
            {
                return(true);
            }

            // No additional light shadows
            if (!CoreUtils.HasFlag(features, ShaderFeatures.AdditionalLightShadows) && isAdditionalLightShadow)
            {
                return(true);
            }

            if (!CoreUtils.HasFlag(features, ShaderFeatures.SoftShadows) &&
                compilerData.shaderKeywordSet.IsEnabled(m_SoftShadows))
            {
                return(true);
            }

            if (compilerData.shaderKeywordSet.IsEnabled(m_MixedLightingSubtractive) &&
                !CoreUtils.HasFlag(features, ShaderFeatures.MixedLighting))
            {
                return(true);
            }

            bool isBuiltInTerrainLit = shader.name.Contains("Universal Render Pipeline/Terrain/Lit");

            if (isBuiltInTerrainLit && compilerData.shaderKeywordSet.IsEnabled(m_AlphaTestOn) &&
                !CoreUtils.HasFlag(features, ShaderFeatures.TerrainHoles))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 28
0
 public override bool ShouldStripVariant(Shader shader, ShaderSnippetData snippet, ShaderCompilerData data)
 {
     return(!ShouldIncludeVariant(shader, snippet, data));
 }
Exemplo n.º 29
0
        public override bool ShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
        {
            bool isGBufferPass            = snippet.passName == "GBuffer";
            bool isForwardPass            = snippet.passName == "Forward";
            bool isDepthOnlyPass          = snippet.passName == "DepthOnly";
            bool isTransparentPrepass     = snippet.passName == "TransparentDepthPrepass";
            bool isTransparentPostpass    = snippet.passName == "TransparentDepthPostpass";
            bool isTransparentBackface    = snippet.passName == "TransparentBackface";
            bool isDistortionPass         = snippet.passName == "DistortionVectors";
            bool isTransparentForwardPass = isTransparentPostpass || isTransparentBackface || isTransparentPrepass;

            // Using Contains to include the Tessellation variants
            bool isBuiltInLit = shader.name.Contains("HDRenderPipeline/Lit") && shader.name.Contains("HDRenderPipeline/LayeredLit") && shader.name.Contains("HDRenderPipeline/TerrainLit");

            if (isDistortionPass && !hdrpAsset.renderPipelineSettings.supportDistortion)
            {
                return(true);
            }

            if (isTransparentBackface && !hdrpAsset.renderPipelineSettings.supportTransparentBackface)
            {
                return(true);
            }

            if (isTransparentPrepass && !hdrpAsset.renderPipelineSettings.supportTransparentDepthPrepass)
            {
                return(true);
            }

            if (isTransparentPostpass && !hdrpAsset.renderPipelineSettings.supportTransparentDepthPostpass)
            {
                return(true);
            }

            // When using forward only, we never need GBuffer pass (only Forward)
            if (hdrpAsset.renderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && isGBufferPass)
            {
                return(true);
            }

            if (isBuiltInLit)
            {
                if (inputData.shaderKeywordSet.IsEnabled(m_Transparent))
                {
                    // If transparent, we never need GBuffer pass.
                    if (isGBufferPass)
                    {
                        return(true);
                    }

                    // If transparent we don't need the depth only pass
                    if (isDepthOnlyPass)
                    {
                        return(true);
                    }
                }
                else // Opaque
                {
                    // If opaque, we never need transparent specific passes (even in forward only mode)
                    if (isTransparentForwardPass)
                    {
                        return(true);
                    }

                    if (hdrpAsset.renderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.DeferredOnly)
                    {
                        // When we are in deferred, we only support tile lighting
                        if (inputData.shaderKeywordSet.IsEnabled(m_ClusterLighting))
                        {
                            return(true);
                        }

                        // If we use deferred only, MSAA is not supported.
                        if (inputData.shaderKeywordSet.IsEnabled(m_WriteMSAADepth))
                        {
                            return(true);
                        }

                        if (isForwardPass && !inputData.shaderKeywordSet.IsEnabled(m_DebugDisplay))
                        {
                            return(true);
                        }

                        if (inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer))
                        {
                            return(true);
                        }
                    }

                    if (isDepthOnlyPass)
                    {
                        // When we are full forward, we don't have depth prepass without writeNormalBuffer
                        if (hdrpAsset.renderPipelineSettings.supportedLitShaderMode == RenderPipelineSettings.SupportedLitShaderMode.ForwardOnly && !inputData.shaderKeywordSet.IsEnabled(m_WriteNormalBuffer))
                        {
                            return(true);
                        }
                    }
                }
            }



            // TODO: Tests for later
            // We need to find a way to strip useless shader features for passes/shader stages that don't need them (example, vertex shaders won't ever need SSS Feature flag)
            // This causes several problems:
            // - Runtime code that "finds" shader variants based on feature flags might not find them anymore... thus fall backing to the "let's give a score to variant" code path that may find the wrong variant.
            // - Another issue is that if a feature is declared without a "_" fall-back, if we strip the other variants, none may be left to use! This needs to be changed on our side.
            //if (snippet.shaderType == ShaderType.Vertex && inputData.shaderKeywordSet.IsEnabled(m_FeatureSSS))
            //    return true;

            return(false);
        }
Exemplo n.º 30
0
        // NOTE: All these keyword should be automatically stripped so there's no need to handle them ourselves.
        // LIGHTMAP_ON, DIRLIGHTMAP_COMBINED, DYNAMICLIGHTMAP_ON, LIGHTMAP_SHADOW_MIXING, SHADOWS_SHADOWMASK
        // FOG_LINEAR, FOG_EXP, FOG_EXP2
        // STEREO_INSTANCING_ON, STEREO_MULTIVIEW_ON, STEREO_CUBEMAP_RENDER_ON, UNITY_SINGLE_PASS_STEREO
        // INSTANCING_ON

        // Several pass are common to all shader, let's share code here
        // This remove variant (return true) for:
        // - Scene Selection
        // - Motion vectors
        // - Tile pass for Transparent (not compatible)
        // -
        protected bool CommonShaderStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
        {
            bool isSceneSelectionPass = snippet.passName == "SceneSelectionPass";

            if (isSceneSelectionPass)
            {
                return(true);
            }

            bool isMotionPass = snippet.passName == "Motion Vectors";

            if (!hdrpAsset.renderPipelineSettings.supportMotionVectors && isMotionPass)
            {
                return(true);
            }

            //bool isForwardPass = (snippet.passName == "Forward") || (snippet.passName == "ForwardOnly");

            if (inputData.shaderKeywordSet.IsEnabled(m_Transparent))
            {
                // If we are transparent we use cluster lighting and not tile lighting
                if (inputData.shaderKeywordSet.IsEnabled(m_TileLighting))
                {
                    return(true);
                }
            }
            else // Opaque
            {
                // Note: we can't assume anything regarding tile/cluster for opaque as multiple view could used different settings and it depends on MSAA
            }

            // TODO: If static lighting we can remove meta pass, but how to know that?

            // If we are in a release build, don't compile debug display variant
            // Also don't compile it if not requested by the render pipeline settings
            if ((/*!Debug.isDebugBuild || */ !hdrpAsset.renderPipelineSettings.supportRuntimeDebugDisplay) && inputData.shaderKeywordSet.IsEnabled(m_DebugDisplay))
            {
                return(true);
            }

            if (inputData.shaderKeywordSet.IsEnabled(m_LodFadeCrossFade) && !hdrpAsset.renderPipelineSettings.supportDitheringCrossFade)
            {
                return(true);
            }

            return(false);
        }