using System; using Unity.Collections; using System.Collections.Generic; using Unity.Collections.LowLevel.Unsafe; namespace UnityEngine.Rendering.HighDefinition { //Data of VisibleLight that has been processed / evaluated. internal struct HDProcessedVisibleLight { public int dataIndex; public GPULightType gpuLightType; public LightType lightType; public float lightDistanceFade; public float lightVolumetricDistanceFade; public float distanceToCamera; public HDProcessedVisibleLightsBuilder.ShadowMapFlags shadowMapFlags; public bool isBakedShadowMask; } internal struct ShadowIndicesAndVisibleLightData { public HDAdditionalLightDataUpdateInfo additionalLightUpdateInfo; public VisibleLight visibleLight; public int dataIndex; public int lightIndex; public HDShadowRequestSetHandle shadowRequestSetHandle; public int splitCount; public int sortKeyIndex; public ShadowMapUpdateType shadowUpdateType; public BitArray8 isSplitValidMask; public BitArray8 needCacheUpdateMask; public bool HasShadowCacheUpToDate(int splitIndex) => shadowUpdateType == ShadowMapUpdateType.Cached && !needCacheUpdateMask[(uint)splitIndex]; } //Class representing lights in the context of a view. internal partial class HDProcessedVisibleLightsBuilder { #region internal HDRP API [Flags] internal enum ShadowMapFlags { None = 0, WillRenderShadowMap = 1 << 0, WillRenderScreenSpaceShadow = 1 << 1, WillRenderRayTracedShadow = 1 << 2 } //Member lights counts public int sortedLightCounts => m_ProcessVisibleLightCounts[(int)ProcessLightsCountSlots.ProcessedLights]; public int sortedDirectionalLightCounts => m_ProcessVisibleLightCounts[(int)ProcessLightsCountSlots.DirectionalLights]; public int sortedNonDirectionalLightCounts => sortedLightCounts - sortedDirectionalLightCounts; public int bakedShadowsCount => m_ProcessVisibleLightCounts[(int)ProcessLightsCountSlots.BakedShadows]; public int shadowLightCount => m_ProcessVisibleLightCounts[(int)ProcessLightsCountSlots.ShadowLights]; //Indexed by VisibleLights public NativeArray visibleLightBakingOutput => m_VisibleLightBakingOutput; public NativeArray visibleLightShadowCasterMode => m_VisibleLightShadowCasterMode; public NativeArray visibleLightEntityDataIndices => m_VisibleLightEntityDataIndices; public NativeArray processedLightVolumeType => m_ProcessedLightVolumeType; public NativeArray processedEntities => m_ProcessedEntities; public NativeArray shadowCullingSplitBuffer => m_ShadowCullingSplitBuffer; public NativeArray visibleLightsAndIndicesBuffer => m_VisibleLightsAndIndicesBuffer; public NativeList splitVisibleLightsAndIndicesBuffer => m_SplitVisibleLightsAndIndicesBuffer; // Bucketed lights. Those lists are aliasing the splitVisibleLightsAndIndicesBuffer above so they must not be disposed. public UnsafeList dynamicPointVisibleLightsAndIndices; public UnsafeList cachedPointVisibleLightsAndIndices; public UnsafeList dynamicSpotVisibleLightsAndIndices; public UnsafeList cachedSpotVisibleLightsAndIndices; public UnsafeList dynamicAreaRectangleVisibleLightsAndIndices; public UnsafeList cachedAreaRectangleVisibleLightsAndIndices; public UnsafeList dynamicDirectionalVisibleLightsAndIndices; public UnsafeList cachedDirectionalVisibleLightsAndIndices; // Bucketed HDShadowCullingSplit. Those lists are aliasing the shadowCullingSplitBuffer above so they must not be disposed. public UnsafeList dynamicPointHDSplits; public UnsafeList cachedPointHDSplits; public UnsafeList dynamicSpotHDSplits; public UnsafeList cachedSpotHDSplits; public UnsafeList dynamicAreaRectangleHDSplits; public UnsafeList cachedAreaRectangleHDSplits; public UnsafeList dynamicDirectionalHDSplits; public UnsafeList cachedDirectionalHDSplits; //Indexed by sorted lights. public NativeArray sortKeys => m_SortKeys; public NativeArray sortSupportArray => m_SortSupportArray; public NativeArray shadowLightsDataIndices => m_ShadowLightsDataIndices; public NativeBitArray shadowRequestValidityArray => m_ShadowRequestValidityArray; //Resets internal size of processed lights. public void Reset() { m_Size = 0; } //Builds sorted HDProcessedVisibleLight structures. public void Build( HDCamera hdCamera, in CullingResults cullingResult, bool rayTracingState, HDShadowManager shadowManager, in HDShadowInitParameters inShadowInitParameters, in AOVRequestData aovRequestData, in GlobalLightLoopSettings lightLoopSettings, DebugDisplaySettings debugDisplaySettings) { BuildVisibleLightEntities(cullingResult); if (m_Size == 0) return; FilterVisibleLightsByAOV(aovRequestData); StartProcessVisibleLightJob(hdCamera, rayTracingState, cullingResult.visibleLights, lightLoopSettings, debugDisplaySettings); CompleteProcessVisibleLightJob(); SortLightKeys(); ProcessShadows(hdCamera, shadowManager, debugDisplaySettings.data.lightingDebugSettings, inShadowInitParameters, cullingResult); } #endregion #region private definitions private enum ProcessLightsCountSlots { ProcessedLights, DirectionalLights, PunctualLights, AreaLightCounts, ShadowLights, BakedShadows, } private const int ArrayCapacity = 32; private NativeArray m_ProcessVisibleLightCounts; private NativeArray m_VisibleLightEntityDataIndices; private NativeArray m_VisibleLightBakingOutput; private NativeArray m_VisibleLightShadowCasterMode; private NativeArray m_VisibleLightShadows; private NativeArray m_ProcessedLightVolumeType; private NativeArray m_ProcessedEntities; private NativeArray m_ShadowCullingSplitBuffer; private NativeArray m_VisibleLightsAndIndicesBuffer; private NativeList m_SplitVisibleLightsAndIndicesBuffer; private UnsafeList m_PointVisibleLightsAndIndices; private NativeBitArray m_ShadowRequestValidityArray; private int m_Capacity = 0; private int m_Size = 0; private NativeArray m_SortKeys; private NativeArray m_SortSupportArray; private NativeArray m_ShadowLightsDataIndices; private void ResizeArrays(int newCapacity) { m_Capacity = Math.Max(Math.Max(newCapacity, ArrayCapacity), m_Capacity * 2); m_VisibleLightEntityDataIndices.ResizeArray(m_Capacity); m_VisibleLightBakingOutput.ResizeArray(m_Capacity); m_VisibleLightShadowCasterMode.ResizeArray(m_Capacity); m_VisibleLightShadows.ResizeArray(m_Capacity); m_ProcessedLightVolumeType.ResizeArray(m_Capacity); m_ProcessedEntities.ResizeArray(m_Capacity); m_ShadowCullingSplitBuffer.ResizeArray(m_Capacity * HDShadowUtils.k_MaxShadowSplitCount); m_VisibleLightsAndIndicesBuffer.ResizeArray(m_Capacity); m_SortKeys.ResizeArray(m_Capacity); m_ShadowLightsDataIndices.ResizeArray(m_Capacity); if (!m_SplitVisibleLightsAndIndicesBuffer.IsCreated) m_SplitVisibleLightsAndIndicesBuffer = new NativeList(Allocator.Persistent); m_SplitVisibleLightsAndIndicesBuffer.Capacity = m_Capacity; var newLightWillRenderToShadowMapArray = new NativeBitArray(m_Capacity, Allocator.Persistent); if (m_ShadowRequestValidityArray.IsCreated) { int numBitsToCopy = Math.Min(m_ShadowRequestValidityArray.Length, newLightWillRenderToShadowMapArray.Length); newLightWillRenderToShadowMapArray.Copy(0, ref m_ShadowRequestValidityArray, 0, numBitsToCopy); m_ShadowRequestValidityArray.Dispose(); } m_ShadowRequestValidityArray = newLightWillRenderToShadowMapArray; } public void Cleanup() { if (m_SortSupportArray.IsCreated) m_SortSupportArray.Dispose(); if (m_Capacity == 0) return; m_ProcessVisibleLightCounts.Dispose(); m_VisibleLightEntityDataIndices.Dispose(); m_VisibleLightBakingOutput.Dispose(); m_VisibleLightShadowCasterMode.Dispose(); m_VisibleLightShadows.Dispose(); m_ProcessedLightVolumeType.Dispose(); m_ProcessedEntities.Dispose(); m_ShadowCullingSplitBuffer.Dispose(); m_VisibleLightsAndIndicesBuffer.Dispose(); m_SortKeys.Dispose(); m_ShadowLightsDataIndices.Dispose(); m_SplitVisibleLightsAndIndicesBuffer.Dispose(); m_ShadowRequestValidityArray.Dispose(); m_Capacity = 0; m_Size = 0; } #endregion } }