애니메이터

Stripping commonly unused shader variants in Unity's built-in render pipeline 본문

Game Engine/Unity3D

Stripping commonly unused shader variants in Unity's built-in render pipeline

욤마핫 2023. 4. 17. 22:26

From Github

//#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
	}
}

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.

 

쉐이더 최적화에 대한 설명 - 자세히

Shader Variant Stripping — Get Rid of That Performance Waste! | TheGamedev.Guru

 

Shader Variant Stripping — Get Rid of That Performance Waste!

Discover the true cost you're paying for the sneaky "shader variants" that Unity creates by default and how to stop paying for it.

thegamedev.guru

 

Improvements to shader build time and runtime memory usage

Official - Improvements to shader build time and runtime memory usage - Unity Forum

 

Official - Improvements to shader build time and runtime memory usage

Greetings from the Shaders team! We would like to share the news on some immediate improvements coming up, which aim to resolve the current pain...

forum.unity.com

Dynamic shader variant loading

Official - Dynamic shader variant loading - Unity Forum

 

Official - Dynamic shader variant loading

Greetings from the Shaders team! Unity 2023.1.0a11 brings dynamic shader variant loading. This feature allows you to manage the runtime memory usage...

forum.unity.com