Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Stripping commonly unused shader variants in Unity's built-in render pipeline
//#define SHADER_COMPILATION_LOGGING
//#define SKIP_SHADER_COMPILATION
using System.Collections.Generic;
using UnityEditor.Build;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Rendering;
public class ShaderStripper : IPreprocessShaders
{
private const string LOG_FILE_PATH = "Library/Shader Compilation Results.txt";
private static readonly ShaderKeyword[] SKIPPED_VARIANTS = new ShaderKeyword[]
{
new ShaderKeyword( "DIRECTIONAL_COOKIE" ),
new ShaderKeyword( "POINT_COOKIE" ),
//new ShaderKeyword( "LIGHTPROBE_SH" ), // Apparently used by lightmapping, as well
};
public int callbackOrder { get { return 0; } }
public void OnProcessShader( Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data )
{
// Don't strip essential shaders
string shaderName = shader.name;
if( shaderName.StartsWith( "Hidden/" ) || shaderName.StartsWith( "Unlit/" ) || shaderName.StartsWith( "Legacy Shaders/" ) || shaderName.StartsWith( "Particles/" ) )
return;
#if SHADER_COMPILATION_LOGGING
System.IO.File.AppendAllText( LOG_FILE_PATH, "\n\n\n\n===== " + shader.name + " " + snippet.passName + " " + snippet.passType + " " + snippet.shaderType + "\n" );
#endif
if( snippet.passType == PassType.Deferred || snippet.passType == PassType.LightPrePassBase || snippet.passType == PassType.LightPrePassFinal || snippet.passType == PassType.ScriptableRenderPipeline || snippet.passType == PassType.ScriptableRenderPipelineDefaultUnlit )
{
#if SHADER_COMPILATION_LOGGING
System.IO.File.AppendAllText( LOG_FILE_PATH, "Skipped shader variant because it uses SRP or Deferred shading\n" );
#endif
data.Clear();
}
for( int i = data.Count - 1; i >= 0; --i )
{
bool shouldSkipShaderVariant = false;
foreach( ShaderKeyword keywordToSkip in SKIPPED_VARIANTS )
{
if( data[i].shaderKeywordSet.IsEnabled( keywordToSkip ) )
{
shouldSkipShaderVariant = true;
break;
}
}
if( shouldSkipShaderVariant )
{
data.RemoveAt( i );
continue;
}
#if SHADER_COMPILATION_LOGGING
string keywords = "";
foreach( ShaderKeyword keyword in data[i].shaderKeywordSet.GetShaderKeywords() )
keywords += keyword.GetKeywordName() + " ";
if( keywords.Length == 0 )
keywords = "No keywords defined";
System.IO.File.AppendAllText( LOG_FILE_PATH, "- " + keywords + "\n" );
#endif
}
#if SKIP_SHADER_COMPILATION
for( int i = data.Count - 1; i >= 0; --i )
data.Clear();
#endif
}
}
@yasirkula

This comment has been minimized.

Copy link
Owner Author

@yasirkula yasirkula commented Aug 30, 2020

How To

Simply create a folder called Editor inside your Project window and add this script inside it.

This script is configured for Unity's built-in render pipeline with Forward rendering used (which is the case for most hyper-casual/casual mobile games).

  • Shaders in Hidden, Unlit, Legacy Shaders and Particles categories aren't stripped since they don't really have an impact in build size or shader compilation time (plus, let's not break any internal Unity stuff by mistake)
  • Shader variants for URP/LWRP/HDRP and deferred rendering are stripped (yes, Unity can compile SRP variants even when built-in render pipeline is used)
  • Shader variants that use light cookies are stripped (I've rarely seen them used in Unity games)
  • If you don't use fog, set Edit-Project Settings-Graphics-Fog Modes to Custom and disable all 3 fog modes
  • If your project doesn't really benefit from GPU instancing (i.e. it doesn't render thousands of copies of the same object in a scene), set Edit-Project Settings-Graphics-Instancing Variants to Strip All
  • Since we are using Forward rendering, disable Deferred, Deferred Reflections and Legacy Deferred in Edit-Project Settings-Graphics-Built-in Shader Settings
  • Disable Motion Vectors, Light Halo and Lens Flare in Edit-Project Settings-Graphics-Built-in Shader Settings if they aren't used

If you uncomment the #define SHADER_COMPILATION_LOGGING line, all shader variants that get compiled will be logged to UNITY_PROJECT_PATH/Library/Shader Compilation Results.txt after you build your project.

If you uncomment the #define SKIP_SHADER_COMPILATION line, none of the shaders will be compiled during a build. But they will still be logged to Shader Compilation Results.txt so this can be useful if you just want to see which shader variants will be compiled without actually waiting for them to be compiled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment