Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added support to combine RTSSS and RTGI (1248733).
- Added IES Profile support for Point, Spot and Rectangular-Area lights
- Added support for multiple mapping modes in AxF.
- Added compute shader stripping.

### Fixed
- Fix when rescale probe all direction below zero (1219246)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@ public CommonShaderPreprocessor() { }

protected override bool DoShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet, ShaderCompilerData inputData)
{
// TODO: We need to perform compute shader stripping as soon as it is possible. Most egregious case would be the shadow filtering quality for Deferred.compute

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

foreach (var shadowVariant in m_ShadowVariants)
foreach (var shadowVariant in m_ShadowKeywords.ShadowVariants)
{
if (shadowVariant.Key != shadowInitParams.shadowFilteringQuality)
if (inputData.shaderKeywordSet.IsEnabled(shadowVariant.Value))
Expand Down Expand Up @@ -136,6 +134,181 @@ protected override bool DoShadersStripper(HDRenderPipelineAsset hdrpAsset, Shade
}
}

class HDRPPreprocessComputeShaders : IPreprocessComputeShaders
{
struct ExportComputeShaderStrip : System.IDisposable
{
bool m_ExportLog;
string m_OutFile;
ComputeShader m_Shader;
string m_KernelName;
IList<ShaderCompilerData> m_InputData;
HDRPPreprocessComputeShaders m_PreProcess;

public ExportComputeShaderStrip(
bool exportLog,
string outFile,
ComputeShader shader,
string kernelName,
IList<ShaderCompilerData> inputData,
HDRPPreprocessComputeShaders preProcess
)
{
m_ExportLog = exportLog;
m_OutFile = outFile;
m_Shader = shader;
m_KernelName = kernelName;
m_InputData = inputData;
m_PreProcess = preProcess;

if (m_ExportLog)
{
System.IO.File.AppendAllText(
m_OutFile,
$"{{ \"Compute shader\": \"{m_Shader.name}\", \"kernel\": \"{m_KernelName}\", \"variantIn\": {m_InputData.Count} }}\r\n"
);
}
}

public void Dispose()
{
if (m_ExportLog)
{
try
{
System.IO.File.AppendAllText(
m_OutFile,
$"{{ \"shader\": \"{m_Shader?.name}\", \"kernel\": \"{m_KernelName}\", \"variantOut\": \"{m_InputData.Count}\", \"totalVariantIn\": \"{m_PreProcess?.m_TotalVariantsInputCount}\", \"totalVariantOut\": \"{m_PreProcess?.m_TotalVariantsOutputCount}\" }}\r\n"
);
}
catch (System.Exception e)
{
Debug.LogException(e);
}
}
}
}

uint m_TotalVariantsInputCount;
uint m_TotalVariantsOutputCount;

protected ShadowKeywords m_ShadowKeywords = new ShadowKeywords();
protected ShaderKeyword m_EnableAlpha = new ShaderKeyword("ENABLE_ALPHA");
protected ShaderKeyword m_MSAA = new ShaderKeyword("ENABLE_MSAA");

public int callbackOrder { get { return 0; } }

void LogShaderVariants(ComputeShader shader, string kernelName, ShaderVariantLogLevel logLevel, uint prevVariantsCount, uint currVariantsCount)
{
// We cannot yet differentiate whether a compute shader is HDRP specific or not.
if (logLevel == ShaderVariantLogLevel.AllShaders || logLevel == ShaderVariantLogLevel.OnlyHDRPShaders)
{
float percentageCurrent = ((float)currVariantsCount / prevVariantsCount) * 100.0f;
float percentageTotal = ((float)m_TotalVariantsOutputCount / m_TotalVariantsInputCount) * 100.0f;

string result = string.Format("STRIPPING: {0} (kernel: {1}) -" +
" Remaining shader variants = {2}/{3} = {4}% - Total = {5}/{6} = {7}%",
shader.name, kernelName, currVariantsCount,
prevVariantsCount, percentageCurrent, m_TotalVariantsOutputCount, m_TotalVariantsInputCount,
percentageTotal);
Debug.Log(result);
}
}

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

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

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

return false;
}

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);
}
}
}
}
}

class HDRPreprocessShaders : IPreprocessShaders
{
// Track list of materials asking for specific preprocessor step
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@

namespace UnityEditor.Rendering.HighDefinition
{
internal class ShadowKeywords
{
ShaderKeyword ShadowLow;
ShaderKeyword ShadowMedium;
ShaderKeyword ShadowHigh;

public Dictionary<HDShadowFilteringQuality, ShaderKeyword> ShadowVariants;

public ShadowKeywords()
{
ShadowLow = new ShaderKeyword("SHADOW_LOW");
ShadowMedium = new ShaderKeyword("SHADOW_MEDIUM");
ShadowHigh = new ShaderKeyword("SHADOW_HIGH");

ShadowVariants = new Dictionary<HDShadowFilteringQuality, ShaderKeyword>
{
{HDShadowFilteringQuality.Low, ShadowLow},
{HDShadowFilteringQuality.Medium, ShadowMedium},
{HDShadowFilteringQuality.High, ShadowHigh},
};
}
}

abstract class BaseShaderPreprocessor
{
// Common keyword list
Expand All @@ -26,6 +49,7 @@ abstract class BaseShaderPreprocessor
protected ShaderKeyword m_WriteNormalBuffer;
protected ShaderKeyword m_WriteMSAADepth;
protected ShaderKeyword m_SubsurfaceScattering;
protected ShadowKeywords m_ShadowKeywords;

protected Dictionary<HDShadowFilteringQuality, ShaderKeyword> m_ShadowVariants;

Expand All @@ -48,19 +72,10 @@ public BaseShaderPreprocessor()
m_Decals3RT = new ShaderKeyword("DECALS_3RT");
m_Decals4RT = new ShaderKeyword("DECALS_4RT");
m_LightLayers = new ShaderKeyword("LIGHT_LAYERS");
m_ShadowLow = new ShaderKeyword("SHADOW_LOW");
m_ShadowMedium = new ShaderKeyword("SHADOW_MEDIUM");
m_ShadowHigh = new ShaderKeyword("SHADOW_HIGH");
m_WriteNormalBuffer = new ShaderKeyword("WRITE_NORMAL_BUFFER");
m_WriteMSAADepth = new ShaderKeyword("WRITE_MSAA_DEPTH");
m_SubsurfaceScattering = new ShaderKeyword("OUTPUT_SPLIT_LIGHTING");

m_ShadowVariants = new Dictionary<HDShadowFilteringQuality, ShaderKeyword>
{
{HDShadowFilteringQuality.Low, m_ShadowLow},
{HDShadowFilteringQuality.Medium, m_ShadowMedium},
{HDShadowFilteringQuality.High, m_ShadowHigh},
};
m_ShadowKeywords = new ShadowKeywords();
}

public bool ShadersStripper(HDRenderPipelineAsset hdrpAsset, Shader shader, ShaderSnippetData snippet,
Expand Down