Singularity/Library/PackageCache/com.unity.render-pipelines..../Runtime/2D/Passes/Utility/LayerUtility.cs

155 lines
5.9 KiB
C#
Raw Normal View History

2024-05-06 14:45:45 -04:00
using Unity.Mathematics;
namespace UnityEngine.Rendering.Universal
{
internal struct LayerBatch
{
public int startLayerID;
public int endLayerValue;
public SortingLayerRange layerRange;
public LightStats lightStats;
private unsafe fixed int renderTargetIds[4];
private unsafe fixed bool renderTargetUsed[4];
public void InitRTIds(int index)
{
for (var i = 0; i < 4; i++)
{
unsafe
{
renderTargetUsed[i] = false;
renderTargetIds[i] = Shader.PropertyToID($"_LightTexture_{index}_{i}");
}
}
}
public RenderTargetIdentifier GetRTId(CommandBuffer cmd, RenderTextureDescriptor desc, int index)
{
unsafe
{
if (!renderTargetUsed[index])
{
cmd.GetTemporaryRT(renderTargetIds[index], desc, FilterMode.Bilinear);
renderTargetUsed[index] = true;
}
return new RenderTargetIdentifier(renderTargetIds[index]);
}
}
public void ReleaseRT(CommandBuffer cmd)
{
for (var i = 0; i < 4; i++)
{
unsafe
{
if (!renderTargetUsed[i])
continue;
cmd.ReleaseTemporaryRT(renderTargetIds[i]);
renderTargetUsed[i] = false;
}
}
}
}
internal static class LayerUtility
{
private static LayerBatch[] s_LayerBatches;
public static uint maxTextureCount { get; private set; }
public static void InitializeBudget(uint maxTextureCount)
{
LayerUtility.maxTextureCount = math.max(4, maxTextureCount);
}
private static bool CanBatchLightsInLayer(int layerIndex1, int layerIndex2, SortingLayer[] sortingLayers, ILight2DCullResult lightCullResult)
{
var layerId1 = sortingLayers[layerIndex1].id;
var layerId2 = sortingLayers[layerIndex2].id;
foreach (var light in lightCullResult.visibleLights)
{
// If the lit layers are different, or if they are lit but this is a shadow casting light then don't batch.
bool lightCastsShadows = (light.lightType != Light2D.LightType.Global && light.shadowsEnabled);
if ((light.IsLitLayer(layerId1) != light.IsLitLayer(layerId2)) || (light.IsLitLayer(layerId1) && lightCastsShadows))
return false;
}
return true;
}
private static int FindUpperBoundInBatch(int startLayerIndex, SortingLayer[] sortingLayers, ILight2DCullResult lightCullResult)
{
// start checking at the next layer
for (var i = startLayerIndex + 1; i < sortingLayers.Length; i++)
{
if (!CanBatchLightsInLayer(startLayerIndex, i, sortingLayers, lightCullResult))
return i - 1;
}
return sortingLayers.Length - 1;
}
private static void InitializeBatchInfos(SortingLayer[] cachedSortingLayers)
{
var count = cachedSortingLayers.Length;
var needInit = s_LayerBatches == null;
if (s_LayerBatches is null)
{
s_LayerBatches = new LayerBatch[count];
}
#if UNITY_EDITOR
// we should fix. Make a non allocating version of this
if (!Application.isPlaying && s_LayerBatches.Length != count)
{
s_LayerBatches = new LayerBatch[count];
needInit = true;
}
#endif
if (needInit)
{
for (var i = 0; i < s_LayerBatches.Length; i++)
{
ref var layerBatch = ref s_LayerBatches[i];
layerBatch.InitRTIds(i);
}
}
}
public static LayerBatch[] CalculateBatches(ILight2DCullResult lightCullResult, out int batchCount)
{
var cachedSortingLayers = Light2DManager.GetCachedSortingLayer();
InitializeBatchInfos(cachedSortingLayers);
batchCount = 0;
for (var i = 0; i < cachedSortingLayers.Length;)
{
var layerToRender = cachedSortingLayers[i].id;
var lightStats = lightCullResult.GetLightStatsByLayer(layerToRender);
ref var layerBatch = ref s_LayerBatches[batchCount++];
// Find the highest layer that share the same set of lights as this layer.
var upperLayerInBatch = FindUpperBoundInBatch(i, cachedSortingLayers, lightCullResult);
// Some renderers override their sorting layer value with short.MinValue or short.MaxValue.
// When drawing the first sorting layer, we should include the range from short.MinValue to layerValue.
// Similarly, when drawing the last sorting layer, include the range from layerValue to short.MaxValue.
var startLayerValue = (short)cachedSortingLayers[i].value;
var lowerBound = (i == 0) ? short.MinValue : startLayerValue;
var endLayerValue = (short)cachedSortingLayers[upperLayerInBatch].value;
var upperBound = (upperLayerInBatch == cachedSortingLayers.Length - 1) ? short.MaxValue : endLayerValue;
// Renderer within this range share the same set of lights so they should be rendered together.
var sortingLayerRange = new SortingLayerRange(lowerBound, upperBound);
layerBatch.startLayerID = layerToRender;
layerBatch.endLayerValue = endLayerValue;
layerBatch.layerRange = sortingLayerRange;
layerBatch.lightStats = lightStats;
i = upperLayerInBatch + 1;
}
return s_LayerBatches;
}
}
}