This commit is contained in:
2024-09-20 20:30:10 +02:00
commit 4fabf1a6fd
29169 changed files with 1706941 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
using System.Diagnostics.CodeAnalysis;
using UnityEngine;
namespace UnityEditor.Rendering
{
/// <summary>
/// Interface to be implemented for a type of shader that it's variants can be stripped
/// </summary>
/// <typeparam name="TShader">The shader <see cref="Shader"/> or <see cref="ComputeShader"/></typeparam>
/// <typeparam name="TShaderVariant">The type of variant for the given type of shader can either be <see cref="ShaderSnippetData"/> or <see cref="string"/></typeparam>
public interface IVariantStripper<TShader, TShaderVariant>
where TShader : UnityEngine.Object
{
/// <summary>
/// Returns if the stripper is active
/// </summary>
bool active { get; }
/// <summary>
/// Specifies if a <see cref="TShader"/> variant can be stripped
/// </summary>
/// <param name="shader">The <see cref="TShader"/></param>
/// <param name="shaderVariant"><see cref="TShaderVariant"/></param>
/// <param name="shaderCompilerData">The variant</param>
/// <returns>true if the variant is not used and can be stripped</returns>
bool CanRemoveVariant([DisallowNull] TShader shader, [DisallowNull] TShaderVariant shaderVariant, ShaderCompilerData shaderCompilerData);
}
/// <summary>
/// Interface to allow an <see cref="IVariantStripper{TShader, TShaderVariant}"/> to skip a shader variant for processing
/// </summary>
/// <typeparam name="TShader">The shader <see cref="Shader"/> or <see cref="ComputeShader"/></typeparam>
/// <typeparam name="TShaderVariant">The type of variant for the given type of shader can either be <see cref="ShaderSnippetData"/> or <see cref="string"/></typeparam>
public interface IVariantStripperSkipper<TShader, TShaderVariant>
where TShader : UnityEngine.Object
{
/// <summary>
/// Returns if the <see cref="TShader"/> for the current <see cref="TShaderVariant"/> is skipped for stripping
/// </summary>
/// <param name="shader">The shader</param>
/// <param name="shaderVariant">The variant</param>
/// <returns>true, if the shader can be skipped</returns>
bool SkipShader([DisallowNull] TShader shader, [DisallowNull] TShaderVariant shaderVariant);
}
/// <summary>
/// Interface to allow an <see cref="IVariantStripper{TShader, TShaderVariant}"/> to have a callback before and after the processing of variants
/// </summary>
/// <typeparam name="TShader">The shader <see cref="Shader"/> or <see cref="ComputeShader"/></typeparam>
/// <typeparam name="TShaderVariant">The type of variant for the given type of shader can either be <see cref="ShaderSnippetData"/> or <see cref="string"/></typeparam>
public interface IVariantStripperScope<TShader, TShaderVariant>
where TShader : UnityEngine.Object
{
/// <summary>
/// Callback that will be executed before parsing variants
/// </summary>
/// <param name="shader">The shader</param>
void BeforeShaderStripping(TShader shader);
/// <summary>
/// Callback that will be executed after parsing variants
/// </summary>
/// <param name="shader">The shader</param>
void AfterShaderStripping(TShader shader);
}
#region Shader Helpers
/// <summary>
/// Helper interface to create a <see cref="IVariantStripper{TShader, TShaderVariant}"/> targeting <see cref="Shader"/>
/// </summary>
public interface IShaderVariantStripper : IVariantStripper<Shader, ShaderSnippetData> { }
/// <summary>
/// Helper interface to create a <see cref="IVariantStripperSkipper{TShader, TShaderVariant}"/> targeting <see cref="Shader"/>
/// </summary>
public interface IShaderVariantStripperSkipper : IVariantStripperSkipper<Shader, ShaderSnippetData> { }
/// <summary>
/// Helper interface to create a <see cref="IVariantStripperScope{TShader, TShaderVariant}"/> targeting <see cref="Shader"/>
/// </summary>
public interface IShaderVariantStripperScope : IVariantStripperScope<Shader, ShaderSnippetData> { }
#endregion
#region Compute Shader Helpers
/// <summary>
/// Helper interface to create a <see cref="IVariantStripper{TShader, TShaderVariant}"/> targeting <see cref="ComputeShader"/>
/// </summary>
public interface IComputeShaderVariantStripper : IVariantStripper<ComputeShader, string> { }
/// <summary>
/// Helper interface to create a <see cref="IVariantStripperSkipper{TShader, TShaderVariant}"/> targeting <see cref="ComputeShader"/>
/// </summary>
public interface IComputeShaderVariantStripperSkipper : IVariantStripperSkipper<ComputeShader, string> { }
/// <summary>
/// Helper interface to create a <see cref="IVariantStripperScope{TShader, TShaderVariant}"/> targeting <see cref="ComputeShader"/>
/// </summary>
public interface IComputeShaderVariantStripperScope : IVariantStripperScope<ComputeShader, string> { }
#endregion
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea71340347cd4764d9e89cc6758729eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using System.Diagnostics.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
/// <summary>
/// Collection of extensions for <see cref="Shader"/>
/// </summary>
static class ShaderExtensions
{
private static readonly ShaderTagId s_RenderPipelineShaderTagId = new ShaderTagId("RenderPipeline");
/// <summary>
/// Tries to find the "RenderPipeline" on the shader by the given <see cref="ShaderSnippetData"/>
/// </summary>
/// <param name="shader"><see cref="Shader"/> The shader to look for the tag</param>
/// <param name="snippetData"><see cref="ShaderSnippetData"/></param>
/// <param name="renderPipelineTag"><see cref="string"/> containing the value of the tag "RenderPipeline"</param>
/// <returns>true if the tag is found and has a value</returns>
public static bool TryGetRenderPipelineTag([DisallowNull] this Shader shader, ShaderSnippetData snippetData, [NotNullWhen(true)] out string renderPipelineTag)
{
renderPipelineTag = string.Empty;
var shaderData = ShaderUtil.GetShaderData(shader);
if (shaderData == null)
return false;
int subshaderIndex = (int)snippetData.pass.SubshaderIndex;
if (subshaderIndex < 0 || subshaderIndex >= shader.subshaderCount)
return false;
var subShader = shaderData.GetSerializedSubshader(subshaderIndex);
if (subShader == null)
return false;
var shaderTag = subShader.FindTagValue(s_RenderPipelineShaderTagId);
if (string.IsNullOrEmpty(shaderTag.name))
return false;
renderPipelineTag = shaderTag.name;
return true;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 75fb0572c16138347964c56f32c1ac45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,184 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using UnityEditor.Build;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
abstract class ShaderPreprocessor<TShader, TShaderVariant>
where TShader : UnityEngine.Object
{
IVariantStripper<TShader, TShaderVariant>[] m_Strippers = null;
protected virtual IVariantStripper<TShader, TShaderVariant>[] strippers
{
get => m_Strippers ??= FetchShaderStrippers();
private set => m_Strippers = value;
}
Lazy<string> m_GlobalRenderPipeline = new (FetchGlobalRenderPipelineShaderTag);
string globalRenderPipeline => m_GlobalRenderPipeline.Value;
IVariantStripperScope<TShader, TShaderVariant>[] m_Scopes = null;
protected virtual IVariantStripperScope<TShader, TShaderVariant>[] scopes => m_Scopes ??= strippers.OfType<IVariantStripperScope<TShader, TShaderVariant>>().ToArray();
protected ShaderPreprocessor() { }
protected ShaderPreprocessor(IVariantStripper<TShader, TShaderVariant>[] strippers)
{
this.strippers = strippers ?? throw new ArgumentNullException(nameof(strippers));
}
private static string FetchGlobalRenderPipelineShaderTag()
{
// We can not rely on Shader.globalRenderPipeline as if there wasn't a Camera.Render the variable won't be initialized.
// Therefore, we fetch the RenderPipeline assets that are included by the Quality Settings and or Graphics Settings
string globalRenderPipelineTag = string.Empty;
using (ListPool<RenderPipelineAsset>.Get(out List<RenderPipelineAsset> rpAssets))
{
if (EditorUserBuildSettings.activeBuildTarget.TryGetRenderPipelineAssets<RenderPipelineAsset>(rpAssets))
{
// As all the RP assets must be from the same pipeline we can simply obtain the shader tag from the first one
var asset = rpAssets.FirstOrDefault();
if (asset != null)
globalRenderPipelineTag = asset.renderPipelineShaderTag;
}
}
return globalRenderPipelineTag;
}
bool TryGetShaderVariantRenderPipelineTag([DisallowNull] TShader shader, TShaderVariant shaderVariant, out string renderPipelineTag)
{
var inputShader = (Shader)Convert.ChangeType(shader, typeof(Shader));
var snippetData = (ShaderSnippetData)Convert.ChangeType(shaderVariant, typeof(ShaderSnippetData));
return inputShader.TryGetRenderPipelineTag(snippetData, out renderPipelineTag);
}
private static IVariantStripper<TShader, TShaderVariant>[] FetchShaderStrippers()
{
var validStrippers = new List<IVariantStripper<TShader, TShaderVariant>>();
// Gather all the implementations of IVariantStripper and add them as the strippers
foreach (var stripper in TypeCache.GetTypesDerivedFrom<IVariantStripper<TShader, TShaderVariant>>())
{
if (stripper.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null) !=
null)
{
var stripperInstance =
Activator.CreateInstance(stripper) as IVariantStripper<TShader, TShaderVariant>;
if (stripperInstance.active)
validStrippers.Add(stripperInstance);
}
}
return validStrippers.ToArray();
}
bool CanRemoveVariant([DisallowNull] TShader shader, TShaderVariant shaderVariant, ShaderCompilerData shaderCompilerData)
{
return strippers
.Where(s => s is not IVariantStripperSkipper<TShader, TShaderVariant> skipper || !skipper.SkipShader(shader, shaderVariant))
.All(s => s.CanRemoveVariant(shader, shaderVariant, shaderCompilerData));
}
/// <summary>
/// Strips the given <see cref="TShader"/>
/// </summary>
/// <param name="shader">The <see cref="T" /> that might be stripped.</param>
/// <param name="shaderVariant">The <see cref="TShaderVariant" /></param>
/// <param name="compilerDataList">A list of <see cref="ShaderCompilerData" /></param>
[CollectionAccess(CollectionAccessType.ModifyExistingContent)]
[MustUseReturnValue]
protected bool TryStripShaderVariants([DisallowNull] TShader shader, TShaderVariant shaderVariant, IList<ShaderCompilerData> compilerDataList, [NotNullWhen(false)] out Exception error)
{
if (shader == null)
{
error = new ArgumentNullException(nameof(shader));
return false;
}
if (compilerDataList == null)
{
error = new ArgumentNullException(nameof(compilerDataList));
return false;
}
var beforeStrippingInputShaderVariantCount = compilerDataList.Count;
var afterStrippingShaderVariantCount = beforeStrippingInputShaderVariantCount;
string renderPipelineTag = string.Empty;
if (typeof(TShader) == typeof(Shader) && typeof(TShaderVariant) == typeof(ShaderSnippetData))
{
if (TryGetShaderVariantRenderPipelineTag(shader, shaderVariant, out renderPipelineTag))
{
if (!renderPipelineTag.Equals(globalRenderPipeline, StringComparison.OrdinalIgnoreCase))
afterStrippingShaderVariantCount = 0;
}
}
bool strippersAvailable = strippers.Any();
double stripTimeMs = 0.0;
using (TimedScope.FromRef(ref stripTimeMs))
{
if (strippersAvailable)
{
for (int i = 0; i < scopes.Length; ++i)
scopes[i].BeforeShaderStripping(shader);
// Go through all the shader variants
for (var i = 0; i < afterStrippingShaderVariantCount;)
{
// Remove at swap back
if (CanRemoveVariant(shader, shaderVariant, compilerDataList[i]))
compilerDataList[i] = compilerDataList[--afterStrippingShaderVariantCount];
else
++i;
}
}
// Remove the shader variants that will be at the back
if (!compilerDataList.TryRemoveElementsInRange(afterStrippingShaderVariantCount, compilerDataList.Count - afterStrippingShaderVariantCount, out error))
return false;
if (strippersAvailable)
{
for (int i = 0; i < scopes.Length; ++i)
scopes[i].AfterShaderStripping(shader);
}
}
ShaderStripping.reporter.OnShaderProcessed(shader, shaderVariant, renderPipelineTag, (uint)beforeStrippingInputShaderVariantCount, (uint)compilerDataList.Count, stripTimeMs);
ShaderStrippingWatcher.OnShaderProcessed(shader, shaderVariant, (uint)compilerDataList.Count, stripTimeMs);
error = null;
return true;
}
}
class ShaderVariantStripper : ShaderPreprocessor<Shader, ShaderSnippetData>, IPreprocessShaders
{
public int callbackOrder => 0;
public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> inputData)
{
if (!TryStripShaderVariants(shader, snippet, inputData, out var error))
Debug.LogError(error);
}
}
class ComputeShaderVariantStripper : ShaderPreprocessor<ComputeShader, string>, IPreprocessComputeShaders
{
public int callbackOrder => 0;
public void OnProcessComputeShader(ComputeShader shader, string kernelName, IList<ShaderCompilerData> inputData)
{
if (!TryStripShaderVariants(shader, kernelName, inputData, out var error))
Debug.LogError(error);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 18a67dd5ad5b87049bc0ed384b818caa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,370 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering
{
[Serializable]
class VariantCounter
{
public uint inputVariants;
public uint outputVariants;
public override string ToString() => $"Total={outputVariants}/{inputVariants}({outputVariants / (float)inputVariants * 100f:0.00}%)";
}
[Serializable]
class ShaderVariantInfo : VariantCounter
{
public string variantName;
public double stripTimeMs;
public override string ToString() => $"{variantName} - {base.ToString()} - Time={stripTimeMs}ms";
}
[Serializable]
class ShaderStrippingInfo : VariantCounter, ISerializationCallbackReceiver
{
public string name;
private Dictionary<string, (VariantCounter count, List<ShaderVariantInfo> variantInfos)> m_VariantsByPipeline = new();
public void AddVariant(string pipeline, ShaderVariantInfo variant)
{
if (!m_VariantsByPipeline.TryGetValue(pipeline, out var list))
{
list.count = new VariantCounter();
list.variantInfos = new List<ShaderVariantInfo>();
m_VariantsByPipeline.Add(pipeline, list);
}
list.count.inputVariants += variant.inputVariants;
list.count.outputVariants += variant.outputVariants;
inputVariants += variant.inputVariants;
outputVariants += variant.outputVariants;
list.variantInfos.Add(variant);
}
public override string ToString() => $"{name} - {base.ToString()}";
public void Log(ShaderVariantLogLevel logLevel)
{
IEnumerable<ShaderVariantInfo> variantsToLog = null;
switch (logLevel)
{
case ShaderVariantLogLevel.AllShaders:
{
variantsToLog = m_VariantsByPipeline.SelectMany(i => i.Value.variantInfos);
break;
}
case ShaderVariantLogLevel.OnlySRPShaders:
{
variantsToLog = m_VariantsByPipeline
.Where(i => !string.IsNullOrEmpty(i.Key))
.SelectMany(i => i.Value.variantInfos);
break;
}
}
if (variantsToLog != null && variantsToLog.Any())
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($"{this}");
foreach (var variant in variantsToLog)
{
sb.AppendLine($"- {variant}");
}
Debug.Log(sb.ToString());
}
}
[Serializable]
class PipelineVariants : VariantCounter
{
public string pipeline;
public ShaderVariantInfo[] variants;
}
[SerializeField] private PipelineVariants[] pipelines;
public void OnBeforeSerialize()
{
pipelines = m_VariantsByPipeline
.Select(pipeline => new PipelineVariants()
{
pipeline = pipeline.Key,
variants = pipeline.Value.variantInfos.ToArray(),
inputVariants = pipeline.Value.count.inputVariants,
outputVariants = pipeline.Value.count.outputVariants,
})
.ToArray();
}
public void OnAfterDeserialize()
{
pipelines = null;
}
}
/// <summary>
/// This class works as an scope of the <see cref="ShaderStrippingReport"/> hooking into the
/// <see cref="IPreprocessBuildWithReport"/> that are being called at the begin of the build and
/// to <see cref="IPostprocessBuildWithReport"/> that are the ones called after the build is finished
/// </summary>
class ShaderStrippingReportScope : IPostprocessBuildWithReport, IPreprocessBuildWithReport
{
internal static bool s_DefaultExport = false; // This variable is used by reflection by unit tests
public int callbackOrder => 0;
public void OnPreprocessBuild(BuildReport report)
{
ShaderVariantLogLevel logStrippedVariants = ShaderVariantLogLevel.Disabled;
bool exportStrippedVariants = s_DefaultExport;
// Check the current pipeline and check the shader variant settings
if (RenderPipelineManager.currentPipeline != null && RenderPipelineManager.currentPipeline.defaultSettings is IShaderVariantSettings shaderVariantSettings)
{
logStrippedVariants = shaderVariantSettings.shaderVariantLogLevel;
exportStrippedVariants = shaderVariantSettings.exportShaderVariants;
}
ShaderStripping.reporter = (logStrippedVariants == ShaderVariantLogLevel.Disabled && exportStrippedVariants == false) ?
new ShaderStrippingReportEmpty() : new ShaderStrippingReport(logStrippedVariants, exportStrippedVariants);
}
public void OnPostprocessBuild(BuildReport report)
{
ShaderStripping.reporter.DumpReport();
ShaderStripping.reporter = null;
}
}
/// <summary>
/// This class is instantiated as the reporter if the logging and exporting is disabled
/// this avoid tracking all the variants, allocating memory, and doing work that is not need
/// </summary>
class ShaderStrippingReportEmpty : IShaderStrippingReport
{
public void OnShaderProcessed<TShader, TShaderVariant>([DisallowNull] TShader shader, TShaderVariant shaderVariant, string pipeline, uint variantsIn, uint variantsOut, double stripTimeMs)
where TShader : UnityEngine.Object
{ }
public void DumpReport() { }
}
/// <summary>
/// This class is instantiated as the reporter if the reporter is null because we are building asset bundles
/// </summary>
class ShaderStrippingReportLogger : IShaderStrippingReport
{
private bool m_IsLogEnabled = false;
public ShaderStrippingReportLogger()
{
// Check the current pipeline and check the shader variant settings
if (RenderPipelineManager.currentPipeline != null && RenderPipelineManager.currentPipeline.defaultSettings is IShaderVariantSettings shaderVariantSettings)
{
m_IsLogEnabled = shaderVariantSettings.shaderVariantLogLevel != ShaderVariantLogLevel.Disabled;
}
}
public void OnShaderProcessed<TShader, TShaderVariant>([DisallowNull] TShader shader, TShaderVariant shaderVariant, string pipeline, uint variantsIn, uint variantsOut, double stripTimeMs)
where TShader : UnityEngine.Object
{
if (!m_IsLogEnabled)
return;
if (!ShaderStrippingReport.TryGetVariantName(shader, shaderVariant, out string variantName))
return;
Debug.Log($"Shader={shader.name}{variantName} Pipeline={pipeline} Total={variantsIn}/{variantsOut}({variantsOut / (float)variantsIn * 100f:0.00}%) Time={stripTimeMs}ms");
}
public void DumpReport()
{
// Just logs variants into the console
}
}
/// <summary>
/// Class to gather all the information about stripping in SRP packages
/// </summary>
class ShaderStrippingReport : IShaderStrippingReport
{
private readonly ShaderVariantLogLevel m_LogStrippedVariants;
private readonly bool m_ExportStrippedVariants;
// Shader
private readonly List<ShaderStrippingInfo> m_ShaderInfos = new();
private readonly VariantCounter m_ShaderVariantCounter = new();
// Compute Shader
private readonly List<ShaderStrippingInfo> m_ComputeShaderInfos = new();
private readonly VariantCounter m_ComputeShaderVariantCounter = new();
public ShaderStrippingReport(ShaderVariantLogLevel logLevel, bool export)
{
m_LogStrippedVariants = logLevel;
m_ExportStrippedVariants = export;
}
public void OnShaderProcessed<TShader, TShaderVariant>([DisallowNull] TShader shader, TShaderVariant shaderVariant, string pipeline, uint variantsIn, uint variantsOut, double stripTimeMs)
where TShader : UnityEngine.Object
{
if (!TryGetVariantName(shader, shaderVariant, out string variantName))
throw new NotImplementedException($"Report is not enabled for {typeof(TShader)} and {typeof(TShaderVariant)}");
var lastShaderStrippingInfo = FindLastShaderStrippingInfo(shader);
if (typeof(TShader) == typeof(Shader))
{
m_ShaderVariantCounter.inputVariants += variantsIn;
m_ShaderVariantCounter.outputVariants += variantsOut;
}
else if (typeof(TShader) == typeof(ComputeShader))
{
m_ComputeShaderVariantCounter.inputVariants += variantsIn;
m_ComputeShaderVariantCounter.outputVariants += variantsOut;
}
lastShaderStrippingInfo.AddVariant(pipeline, new ShaderVariantInfo()
{
inputVariants = variantsIn,
outputVariants = variantsOut,
stripTimeMs = stripTimeMs,
variantName = variantName
});
}
internal static string k_ShaderOutputPath = "Temp/shader-stripping.json";
internal static string k_ComputeShaderOutputPath = "Temp/compute-shader-stripping.json";
public void DumpReport()
{
if (m_LogStrippedVariants != ShaderVariantLogLevel.Disabled)
{
Debug.Log($"Shader Stripping - {m_ShaderVariantCounter}");
foreach (var info in m_ShaderInfos)
{
info.Log(m_LogStrippedVariants);
}
Debug.Log($"Compute Shader Stripping - {m_ComputeShaderVariantCounter}");
foreach (var info in m_ComputeShaderInfos)
{
info.Log(m_LogStrippedVariants);
}
}
if (m_ExportStrippedVariants)
{
ExportShaderStrippingInfo(k_ShaderOutputPath, m_ShaderVariantCounter, m_ShaderInfos);
ExportShaderStrippingInfo(k_ComputeShaderOutputPath, m_ComputeShaderVariantCounter, m_ComputeShaderInfos);
}
}
[CanBeNull] private ShaderStrippingInfo m_LastShaderStrippingInfo = null;
private ShaderStrippingInfo FindLastShaderStrippingInfo<TShader>([DisallowNull] TShader shader)
where TShader : UnityEngine.Object
{
if (m_LastShaderStrippingInfo != null && m_LastShaderStrippingInfo.name.Equals(shader.name))
return m_LastShaderStrippingInfo;
// We are reporting a new shader variant, need to create a new one
m_LastShaderStrippingInfo = new ShaderStrippingInfo()
{
name = shader.name
};
// The compiler will strip the branch that we are not using
if (typeof(TShader) == typeof(Shader))
{
m_ShaderInfos.Add(m_LastShaderStrippingInfo);
}
else if (typeof(TShader) == typeof(ComputeShader))
{
m_ComputeShaderInfos.Add(m_LastShaderStrippingInfo);
}
return m_LastShaderStrippingInfo;
}
[MustUseReturnValue]
internal static bool TryGetVariantName<TShader, TShaderVariant>([DisallowNull] TShader shader, TShaderVariant shaderVariant, out string variantName)
where TShader : UnityEngine.Object
{
variantName = string.Empty;
if (typeof(TShader) == typeof(Shader) && typeof(TShaderVariant) == typeof(ShaderSnippetData))
{
var snippetData = (ShaderSnippetData)Convert.ChangeType(shaderVariant, typeof(ShaderSnippetData));
string passName = string.IsNullOrEmpty(snippetData.passName) ? $"Pass {snippetData.pass.PassIndex}" : snippetData.passName;
variantName = $"{passName} ({snippetData.passType}) (SubShader: {snippetData.pass.SubshaderIndex}) (ShaderType: {snippetData.shaderType.ToString()})";
}
else if (typeof(TShader) == typeof(ComputeShader) && typeof(TShaderVariant) == typeof(string))
{
variantName = $"Kernel: {shaderVariant}";
}
else
{
return false;
}
return true;
}
[Serializable]
class Export
{
public uint totalVariantsIn;
public uint totalVariantsOut;
public ShaderStrippingInfo[] shaders;
}
void ExportShaderStrippingInfo(string path, VariantCounter variantCounter, List<ShaderStrippingInfo> shaders)
{
try
{
var export = new Export()
{
totalVariantsIn = variantCounter.inputVariants,
totalVariantsOut = variantCounter.outputVariants,
shaders = shaders.ToArray()
};
File.WriteAllText(path, JsonUtility.ToJson(export, true));
}
catch (Exception e)
{
Debug.LogException(e);
}
}
}
interface IShaderStrippingReport
{
void OnShaderProcessed<TShader, TShaderVariant>([DisallowNull] TShader shader,
TShaderVariant shaderVariant, string pipeline, uint variantsIn, uint variantsOut, double stripTimeMs)
where TShader : UnityEngine.Object;
void DumpReport();
}
static class ShaderStripping
{
private static IShaderStrippingReport m_Reporter;
public static IShaderStrippingReport reporter
{
get => m_Reporter ??= new ShaderStrippingReportLogger();
internal set => m_Reporter = value;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67c13e47786db8b46939b64891774a02
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System;
using UnityEngine;
namespace UnityEditor.Rendering
{
/// <summary>
/// Notifies when shader variants have been stripped
/// </summary>
public static class ShaderStrippingWatcher
{
/// <summary>
/// Callback when a shader has been stripped
/// </summary>
/// <param name="shader">The shader</param>
/// <param name="shaderVariant">The variant</param>
/// <param name="variantsOut">The output variants after the stripping process</param>
/// <param name="stripTimeMs">The total amount of time to strip the variants</param>
/// <typeparam name="TShader">The shader</typeparam>
/// <typeparam name="TShaderVariant">The variant</typeparam>
public delegate void OnShaderStrippedCallbackHandler<TShader, TShaderVariant>(TShader shader, TShaderVariant shaderVariant, uint variantsOut, double stripTimeMs)
where TShader : UnityEngine.Object;
/// <summary>
/// Callback for <see cref="Shader"/>
/// </summary>
public static event OnShaderStrippedCallbackHandler<Shader, ShaderSnippetData> shaderProcessed;
/// <summary>
/// Callback for <see cref="ComputeShader"/>
/// </summary>
public static event OnShaderStrippedCallbackHandler<ComputeShader, string> computeShaderProcessed;
internal static void OnShaderProcessed<TShader, TShaderVariant>(TShader shader, TShaderVariant shaderVariant, uint variantsOut, double stripTimeMs)
where TShader : UnityEngine.Object
{
if (typeof(TShader) == typeof(Shader))
{
shaderProcessed?.Invoke((Shader)Convert.ChangeType(shader, typeof(Shader)), (ShaderSnippetData)Convert.ChangeType(shaderVariant, typeof(ShaderSnippetData)), variantsOut, stripTimeMs);
}
else if (typeof(TShader) == typeof(ComputeShader))
{
computeShaderProcessed?.Invoke((ComputeShader)Convert.ChangeType(shader, typeof(ComputeShader)), shaderVariant.ToString(), variantsOut, stripTimeMs);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8d750ffecefc4ea42b84efa0eaa7095a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: