You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
6.7 KiB
169 lines
6.7 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using UnityEditor.Build;
|
|
using UnityEditor.Build.Reporting;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.HighDefinition;
|
|
|
|
using ShaderPrefilteringData = UnityEngine.Rendering.HighDefinition.HDRenderPipelineAsset.ShaderPrefilteringData;
|
|
|
|
namespace UnityEditor.Rendering.HighDefinition
|
|
{
|
|
// Shader features that can be used to configure shader prefiltering.
|
|
// Prefiltering can apply complex rules that cannot be properly defined during scriptable stripping.
|
|
[Flags]
|
|
enum ShaderFeatures : long
|
|
{
|
|
None = 0,
|
|
UseLegacyLightmaps = (1L << 0),
|
|
}
|
|
|
|
class HDRPPreprocessBuild : IPreprocessBuildWithReport, IPostprocessBuildWithReport
|
|
{
|
|
public int callbackOrder => 0;
|
|
|
|
private static HDRPBuildData m_BuildData = null;
|
|
private static List<ShaderFeatures> s_SupportedFeaturesList = new();
|
|
|
|
public void OnPreprocessBuild(BuildReport report)
|
|
{
|
|
m_BuildData?.Dispose();
|
|
bool isDevelopmentBuild = (report.summary.options & BuildOptions.Development) != 0;
|
|
m_BuildData = new HDRPBuildData(EditorUserBuildSettings.activeBuildTarget, isDevelopmentBuild);
|
|
|
|
if (m_BuildData.buildingPlayerForHDRenderPipeline)
|
|
{
|
|
// Now that we know that we are on HDRP we need to make sure everything is correct, otherwise we break the build.
|
|
if (!HDRPBuildDataValidator.IsProjectValidForBuilding(report, out var message))
|
|
throw new BuildFailedException(message);
|
|
|
|
ConfigureMinimumMaxLoDValueForAllQualitySettings();
|
|
|
|
LogIncludedAssets(m_BuildData.renderPipelineAssets);
|
|
|
|
GatherShaderFeatures();
|
|
}
|
|
}
|
|
|
|
internal static void LogIncludedAssets(List<HDRenderPipelineAsset> assetsList)
|
|
{
|
|
using (GenericPool<StringBuilder>.Get(out var assetsIncluded))
|
|
{
|
|
assetsIncluded.Clear();
|
|
|
|
assetsIncluded.Append($"{assetsList.Count} HDRP assets included in build");
|
|
|
|
foreach (var hdrpAsset in assetsList)
|
|
{
|
|
assetsIncluded.AppendLine($"- {hdrpAsset.name} - {AssetDatabase.GetAssetPath(hdrpAsset)}");
|
|
}
|
|
|
|
Debug.Log(assetsIncluded);
|
|
}
|
|
}
|
|
|
|
internal static void ConfigureMinimumMaxLoDValueForAllQualitySettings()
|
|
{
|
|
int GetMinimumMaxLoDValue(HDRenderPipelineAsset asset)
|
|
{
|
|
int minimumMaxLoD = int.MaxValue;
|
|
|
|
if (asset != null)
|
|
{
|
|
var maxLoDs = asset.currentPlatformRenderPipelineSettings.maximumLODLevel;
|
|
var schema = ScalableSettingSchema.GetSchemaOrNull(maxLoDs.schemaId);
|
|
for (int lod = 0; lod < schema.levelCount; ++lod)
|
|
{
|
|
if (maxLoDs.TryGet(lod, out int maxLoD))
|
|
minimumMaxLoD = Mathf.Min(minimumMaxLoD, maxLoD);
|
|
}
|
|
}
|
|
|
|
return minimumMaxLoD != int.MaxValue ? minimumMaxLoD : 0;
|
|
}
|
|
|
|
var defaultRenderPipeline = GraphicsSettings.defaultRenderPipeline as HDRenderPipelineAsset;
|
|
|
|
// Update all quality levels with the right max lod so that meshes can be stripped.
|
|
// We don't take lod bias into account because it can be overridden per camera.
|
|
QualitySettings.ForEach((tier, name) =>
|
|
{
|
|
if (QualitySettings.renderPipeline is not HDRenderPipelineAsset renderPipeline)
|
|
renderPipeline = defaultRenderPipeline;
|
|
|
|
QualitySettings.maximumLODLevel = GetMinimumMaxLoDValue(renderPipeline);
|
|
});
|
|
}
|
|
|
|
private static void GatherShaderFeatures()
|
|
{
|
|
s_SupportedFeaturesList.Clear();
|
|
using (ListPool<HDRenderPipelineAsset>.Get(out List<HDRenderPipelineAsset> hdrpAssets))
|
|
{
|
|
bool buildingForHDRP = EditorUserBuildSettings.activeBuildTarget.TryGetRenderPipelineAssets(hdrpAssets);
|
|
if (buildingForHDRP)
|
|
{
|
|
// Get Supported features & update data used for Shader Prefiltering and Scriptable Stripping
|
|
GetSupportedShaderFeaturesFromAssets(ref hdrpAssets, ref s_SupportedFeaturesList);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void GetSupportedShaderFeaturesFromAssets(ref List<HDRenderPipelineAsset> hdrpAssets, ref List<ShaderFeatures> rendererFeaturesList)
|
|
{
|
|
for (int hdrpAssetIndex = 0; hdrpAssetIndex < hdrpAssets.Count; hdrpAssetIndex++)
|
|
{
|
|
// Get the asset and check if it's valid
|
|
HDRenderPipelineAsset hdrpAsset = hdrpAssets[hdrpAssetIndex];
|
|
if (hdrpAsset == null)
|
|
continue;
|
|
|
|
// Check the asset for supported features
|
|
ShaderFeatures hdrpAssetShaderFeatures = GetSupportedShaderFeaturesFromAsset(ref hdrpAsset);
|
|
|
|
// Creates a struct containing all the prefiltering settings for this asset
|
|
ShaderPrefilteringData spd = CreatePrefilteringSettings(ref hdrpAssetShaderFeatures);
|
|
|
|
// Update the Prefiltering settings for this URP asset
|
|
hdrpAsset.UpdateShaderKeywordPrefiltering(ref spd);
|
|
|
|
// Mark the asset dirty so it can be serialized once the build is finished
|
|
EditorUtility.SetDirty(hdrpAsset);
|
|
}
|
|
}
|
|
|
|
private static ShaderFeatures GetSupportedShaderFeaturesFromAsset(ref HDRenderPipelineAsset hdrpAsset)
|
|
{
|
|
ShaderFeatures hdrpAssetShaderFeatures = ShaderFeatures.None;
|
|
|
|
if (hdrpAsset.gpuResidentDrawerMode != GPUResidentDrawerMode.Disabled)
|
|
hdrpAssetShaderFeatures |= ShaderFeatures.UseLegacyLightmaps;
|
|
|
|
return hdrpAssetShaderFeatures;
|
|
}
|
|
|
|
private static ShaderPrefilteringData CreatePrefilteringSettings(ref ShaderFeatures shaderFeatures)
|
|
{
|
|
ShaderPrefilteringData spd = new();
|
|
|
|
spd.useLegacyLightmaps = IsFeatureEnabled(shaderFeatures, ShaderFeatures.UseLegacyLightmaps);
|
|
|
|
return spd;
|
|
}
|
|
|
|
// Checks whether a ShaderFeature is enabled or not
|
|
private static bool IsFeatureEnabled(ShaderFeatures featureMask, ShaderFeatures feature)
|
|
{
|
|
return (featureMask & feature) != 0;
|
|
}
|
|
|
|
public void OnPostprocessBuild(BuildReport report)
|
|
{
|
|
// Clean up the build data once we have finishing building
|
|
m_BuildData?.Dispose();
|
|
m_BuildData = null;
|
|
}
|
|
}
|
|
}
|