123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- using System;
- using System.Collections.Generic;
- using Unity.Collections;
- using Unity.Collections.LowLevel.Unsafe;
- using Unity.Mathematics;
- using UnityEngine.Rendering.RenderGraphModule;
-
- namespace UnityEngine.Rendering
- {
- [GenerateHLSL]
- internal enum OcclusionCullingCommonConfig
- {
- MaxOccluderMips = 8,
- MaxOccluderSilhouettePlanes = 6,
- MaxSubviewsPerView = 6,
- DebugPyramidOffset = 4, // TODO: rename
- }
-
- [GenerateHLSL(needAccessors = false)]
- internal enum OcclusionTestDebugFlag
- {
- AlwaysPass = (1 << 0),
- CountVisible = (1 << 1),
- }
-
- internal struct OcclusionTestComputeShader
- {
- public ComputeShader cs;
- public LocalKeyword occlusionDebugKeyword;
-
- public void Init(ComputeShader cs)
- {
- this.cs = cs;
- this.occlusionDebugKeyword = new LocalKeyword(cs, "OCCLUSION_DEBUG");
- }
- }
-
- internal struct SilhouettePlaneCache : IDisposable
- {
- private struct Slot
- {
- public bool isActive;
- public int viewInstanceID;
- public int planeCount; // planeIndex = slotIndex * kMaxSilhouettePlanes
- public int lastUsedFrameIndex;
-
- public Slot(int viewInstanceID, int planeCount, int frameIndex)
- {
- this.isActive = true;
- this.viewInstanceID = viewInstanceID;
- this.planeCount = planeCount;
- this.lastUsedFrameIndex = frameIndex;
- }
- }
-
- private const int kMaxSilhouettePlanes = (int)OcclusionCullingCommonConfig.MaxOccluderSilhouettePlanes;
-
- private NativeParallelHashMap<int, int> m_SubviewIDToIndexMap;
- private NativeList<int> m_SlotFreeList;
- private NativeList<Slot> m_Slots;
- private NativeList<Plane> m_PlaneStorage;
-
- public void Init()
- {
- m_SubviewIDToIndexMap = new NativeParallelHashMap<int, int>(16, Allocator.Persistent);
- m_SlotFreeList = new NativeList<int>(16, Allocator.Persistent);
- m_Slots = new NativeList<Slot>(16, Allocator.Persistent);
- m_PlaneStorage = new NativeList<Plane>(16 * kMaxSilhouettePlanes, Allocator.Persistent);
- }
-
- public void Dispose()
- {
- m_SubviewIDToIndexMap.Dispose();
- m_SlotFreeList.Dispose();
- m_Slots.Dispose();
- m_PlaneStorage.Dispose();
- }
-
- public void Update(int viewInstanceID, NativeArray<Plane> planes, int frameIndex)
- {
- int planeCount = Math.Min(planes.Length, kMaxSilhouettePlanes);
-
- if (!m_SubviewIDToIndexMap.TryGetValue(viewInstanceID, out int slotIndex))
- {
- if (m_SlotFreeList.Length > 0)
- {
- // take a free slot from the free list
- slotIndex = m_SlotFreeList[m_SlotFreeList.Length - 1];
- m_SlotFreeList.Length = m_SlotFreeList.Length - 1;
- }
- else
- {
- // ensure we have capacity for a few more
- if (m_Slots.Length == m_Slots.Capacity)
- {
- int newCapacity = m_Slots.Length + 8;
- m_Slots.SetCapacity(newCapacity);
- m_PlaneStorage.SetCapacity(newCapacity * kMaxSilhouettePlanes);
- }
-
- // use the next slot in storage
- slotIndex = m_Slots.Length;
- int newSlotCount = slotIndex + 1;
- m_Slots.ResizeUninitialized(newSlotCount);
- m_PlaneStorage.ResizeUninitialized(newSlotCount * kMaxSilhouettePlanes);
- }
-
- // associate with this view ID
- m_SubviewIDToIndexMap.Add(viewInstanceID, slotIndex);
- }
-
- m_Slots[slotIndex] = new Slot(viewInstanceID, planeCount, frameIndex);
- m_PlaneStorage.AsArray().GetSubArray(slotIndex * kMaxSilhouettePlanes, planeCount).CopyFrom(planes);
- }
-
- public void FreeUnusedSlots(int frameIndex, int maximumAge)
- {
- for (int slotIndex = 0; slotIndex < m_Slots.Length; ++slotIndex)
- {
- var slot = m_Slots[slotIndex];
- if (!slot.isActive)
- continue;
-
- if ((frameIndex - slot.lastUsedFrameIndex) > maximumAge)
- {
- slot.isActive = false;
- m_Slots[slotIndex] = slot;
- m_SubviewIDToIndexMap.Remove(slot.viewInstanceID);
- m_SlotFreeList.Add(slotIndex);
- }
- }
- }
-
- public NativeArray<Plane> GetSubArray(int viewInstanceID)
- {
- int planeOffset = 0;
- int planeCount = 0;
- if (m_SubviewIDToIndexMap.TryGetValue(viewInstanceID, out int slotIndex))
- {
- planeOffset = slotIndex * kMaxSilhouettePlanes;
- planeCount = m_Slots[slotIndex].planeCount;
- }
- return m_PlaneStorage.AsArray().GetSubArray(planeOffset, planeCount);
- }
- }
-
- internal class OcclusionCullingCommon : IDisposable
- {
- private struct OccluderContextSlot
- {
- public bool valid;
- public int lastUsedFrameIndex;
- public int viewInstanceID;
- }
-
- private static readonly int s_MaxContextGCFrame = 8; // Allow a few frames for alternate frame shadow updates before cleanup
-
- private Material m_DebugOcclusionTestMaterial;
- private Material m_OccluderDebugViewMaterial;
-
- private ComputeShader m_OcclusionDebugCS;
- private int m_ClearOcclusionDebugKernel;
-
- private ComputeShader m_OccluderDepthPyramidCS;
- private int m_OccluderDepthDownscaleKernel;
- private int m_FrameIndex = 0;
-
- private SilhouettePlaneCache m_SilhouettePlaneCache;
-
- private NativeParallelHashMap<int, int> m_ViewIDToIndexMap;
- private List<OccluderContext> m_OccluderContextData;
- private NativeList<OccluderContextSlot> m_OccluderContextSlots;
- private NativeList<int> m_FreeOccluderContexts;
-
- private NativeArray<OcclusionCullingCommonShaderVariables> m_CommonShaderVariables;
- private ComputeBuffer m_CommonConstantBuffer;
- private NativeArray<OcclusionCullingDebugShaderVariables> m_DebugShaderVariables;
- private ComputeBuffer m_DebugConstantBuffer;
-
- private ProfilingSampler m_ProfilingSamplerUpdateOccluders;
- private ProfilingSampler m_ProfilingSamplerOcclusionTestOverlay;
- private ProfilingSampler m_ProfilingSamplerOccluderOverlay;
-
- internal void Init(GPUResidentDrawerResources resources)
- {
- m_DebugOcclusionTestMaterial = CoreUtils.CreateEngineMaterial(resources.debugOcclusionTestPS);
- m_OccluderDebugViewMaterial = CoreUtils.CreateEngineMaterial(resources.debugOccluderPS);
-
- m_OcclusionDebugCS = resources.occlusionCullingDebugKernels;
- m_ClearOcclusionDebugKernel = m_OcclusionDebugCS.FindKernel("ClearOcclusionDebug");
-
- m_OccluderDepthPyramidCS = resources.occluderDepthPyramidKernels;
- m_OccluderDepthDownscaleKernel = m_OccluderDepthPyramidCS.FindKernel("OccluderDepthDownscale");
-
- m_SilhouettePlaneCache.Init();
-
- m_ViewIDToIndexMap = new NativeParallelHashMap<int, int>(64, Allocator.Persistent);
- m_OccluderContextData = new List<OccluderContext>();
- m_OccluderContextSlots = new NativeList<OccluderContextSlot>(64, Allocator.Persistent);
- m_FreeOccluderContexts = new NativeList<int>(64, Allocator.Persistent);
-
- m_ProfilingSamplerUpdateOccluders = new ProfilingSampler("UpdateOccluders");
- m_ProfilingSamplerOcclusionTestOverlay = new ProfilingSampler("OcclusionTestOverlay");
- m_ProfilingSamplerOccluderOverlay = new ProfilingSampler("OccluderOverlay");
-
- m_CommonShaderVariables = new NativeArray<OcclusionCullingCommonShaderVariables>(1, Allocator.Persistent);
- m_CommonConstantBuffer = new ComputeBuffer(1, UnsafeUtility.SizeOf<OcclusionCullingCommonShaderVariables>(), ComputeBufferType.Constant);
- m_DebugShaderVariables = new NativeArray<OcclusionCullingDebugShaderVariables>(1, Allocator.Persistent);
- m_DebugConstantBuffer = new ComputeBuffer(1, UnsafeUtility.SizeOf<OcclusionCullingDebugShaderVariables>(), ComputeBufferType.Constant);
- }
-
- private static class ShaderIDs
- {
- public static readonly int OcclusionCullingCommonShaderVariables = Shader.PropertyToID("OcclusionCullingCommonShaderVariables");
- public static readonly int _OccluderDepthPyramid = Shader.PropertyToID("_OccluderDepthPyramid");
- public static readonly int _OcclusionDebugOverlay = Shader.PropertyToID("_OcclusionDebugOverlay");
-
- public static readonly int OcclusionCullingDebugShaderVariables = Shader.PropertyToID("OcclusionCullingDebugShaderVariables");
- }
-
- internal static bool UseOcclusionDebug(in OccluderContext occluderCtx)
- {
- return occluderCtx.occlusionDebugOverlaySize != 0;
- }
-
- internal void PrepareCulling(ComputeCommandBuffer cmd, in OccluderContext occluderCtx, in OcclusionCullingSettings settings, in InstanceOcclusionTestSubviewSettings subviewSettings, in OcclusionTestComputeShader shader, bool useOcclusionDebug)
- {
- OccluderContext.SetKeyword(cmd, shader.cs, shader.occlusionDebugKeyword, useOcclusionDebug);
-
- var debugStats = GPUResidentDrawer.GetDebugStats();
-
- m_CommonShaderVariables[0] = new OcclusionCullingCommonShaderVariables(
- in occluderCtx,
- subviewSettings,
- debugStats?.occlusionOverlayCountVisible ?? false,
- debugStats?.overrideOcclusionTestToAlwaysPass ?? false);
- cmd.SetBufferData(m_CommonConstantBuffer, m_CommonShaderVariables);
-
- cmd.SetComputeConstantBufferParam(shader.cs, ShaderIDs.OcclusionCullingCommonShaderVariables, m_CommonConstantBuffer, 0, m_CommonConstantBuffer.stride);
-
- DispatchDebugClear(cmd, settings.viewInstanceID);
- }
-
- internal static void SetDepthPyramid(ComputeCommandBuffer cmd, in OcclusionTestComputeShader shader, int kernel, in OccluderHandles occluderHandles)
- {
- cmd.SetComputeTextureParam(shader.cs, kernel, ShaderIDs._OccluderDepthPyramid, occluderHandles.occluderDepthPyramid);
- }
-
- internal static void SetDebugPyramid(ComputeCommandBuffer cmd, in OcclusionTestComputeShader shader, int kernel, in OccluderHandles occluderHandles)
- {
- cmd.SetComputeBufferParam(shader.cs, kernel, ShaderIDs._OcclusionDebugOverlay, occluderHandles.occlusionDebugOverlay);
- }
-
- private class OcclusionTestOverlaySetupPassData
- {
- public OcclusionCullingDebugShaderVariables cb;
- }
-
- private class OcclusionTestOverlayPassData
- {
- public BufferHandle debugPyramid;
- }
-
- public void RenderDebugOcclusionTestOverlay(RenderGraph renderGraph, DebugDisplayGPUResidentDrawer debugSettings, int viewInstanceID, TextureHandle colorBuffer)
- {
- if (debugSettings == null)
- return;
- if (!debugSettings.occlusionTestOverlayEnable)
- return;
-
- OcclusionCullingDebugOutput debugOutput = GetOcclusionTestDebugOutput(viewInstanceID);
- if (debugOutput.occlusionDebugOverlay == null)
- return;
-
- using (var builder = renderGraph.AddComputePass<OcclusionTestOverlaySetupPassData>("OcclusionTestOverlay", out var passData, m_ProfilingSamplerOcclusionTestOverlay))
- {
- builder.AllowPassCulling(false);
-
- passData.cb = debugOutput.cb;
-
- builder.SetRenderFunc(
- (OcclusionTestOverlaySetupPassData data, ComputeGraphContext ctx) =>
- {
- var occ = GPUResidentDrawer.instance.batcher.occlusionCullingCommon;
-
- occ.m_DebugShaderVariables[0] = data.cb;
- ctx.cmd.SetBufferData(occ.m_DebugConstantBuffer, occ.m_DebugShaderVariables);
-
- occ.m_DebugOcclusionTestMaterial.SetConstantBuffer(
- ShaderIDs.OcclusionCullingDebugShaderVariables,
- occ.m_DebugConstantBuffer,
- 0,
- occ.m_DebugConstantBuffer.stride);
- });
- }
-
- using (var builder = renderGraph.AddRasterRenderPass<OcclusionTestOverlayPassData>("OcclusionTestOverlay", out var passData, m_ProfilingSamplerOcclusionTestOverlay))
- {
- builder.AllowGlobalStateModification(true);
-
- passData.debugPyramid = renderGraph.ImportBuffer(debugOutput.occlusionDebugOverlay);
-
- builder.SetRenderAttachment(colorBuffer, 0);
- builder.UseBuffer(passData.debugPyramid);
-
- builder.SetRenderFunc(
- (OcclusionTestOverlayPassData data, RasterGraphContext ctx) =>
- {
- ctx.cmd.SetGlobalBuffer(ShaderIDs._OcclusionDebugOverlay, data.debugPyramid);
- CoreUtils.DrawFullScreen(ctx.cmd, m_DebugOcclusionTestMaterial);
- });
- }
- }
-
- private struct DebugOccluderViewData
- {
- public int passIndex;
- public Rect viewport;
- public bool valid;
- }
-
- class OccluderOverlayPassData
- {
- public Material debugMaterial;
- public RTHandle occluderTexture;
- public Rect viewport;
- public int passIndex;
- public Vector2 validRange;
- }
-
- public void RenderDebugOccluderOverlay(RenderGraph renderGraph, DebugDisplayGPUResidentDrawer debugSettings, Vector2 screenPos, float maxHeight, TextureHandle colorBuffer)
- {
- if (debugSettings == null)
- return;
- if (!debugSettings.occluderDebugViewEnable)
- return;
-
- if (!debugSettings.GetOccluderViewInstanceID(out var viewInstanceID))
- return;
-
- var occluderTexture = GetOcclusionTestDebugOutput(viewInstanceID).occluderDepthPyramid;
- if (occluderTexture == null)
- return;
-
- Material debugMaterial = m_OccluderDebugViewMaterial;
- int passIndex = debugMaterial.FindPass("DebugOccluder");
-
- Vector2 outputSize = occluderTexture.referenceSize;
- float scaleFactor = maxHeight / outputSize.y;
- outputSize *= scaleFactor;
- Rect viewport = new Rect(screenPos.x, screenPos.y, outputSize.x, outputSize.y);
-
- using (var builder = renderGraph.AddRasterRenderPass<OccluderOverlayPassData>("OccluderOverlay", out var passData, m_ProfilingSamplerOccluderOverlay))
- {
- builder.AllowGlobalStateModification(true);
-
- builder.SetRenderAttachment(colorBuffer, 0);
-
- passData.debugMaterial = debugMaterial;
- passData.occluderTexture = occluderTexture;
- passData.viewport = viewport;
- passData.passIndex = passIndex;
- passData.validRange = debugSettings.occluderDebugViewRange;
-
- builder.SetRenderFunc(
- (OccluderOverlayPassData data, RasterGraphContext ctx) =>
- {
- var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock();
-
- mpb.SetTexture("_OccluderTexture", data.occluderTexture);
- mpb.SetVector("_ValidRange", data.validRange);
-
- ctx.cmd.SetViewport(data.viewport);
- ctx.cmd.DrawProcedural(Matrix4x4.identity, data.debugMaterial, data.passIndex, MeshTopology.Triangles, 3, 1, mpb);
- });
- }
- }
-
- private void DispatchDebugClear(ComputeCommandBuffer cmd, int viewInstanceID)
- {
- if (!m_ViewIDToIndexMap.TryGetValue(viewInstanceID, out var contextIndex))
- return;
-
- OccluderContext occluderCtx = m_OccluderContextData[contextIndex];
-
- if (UseOcclusionDebug(in occluderCtx) && occluderCtx.debugNeedsClear)
- {
- var cs = m_OcclusionDebugCS;
- int kernel = m_ClearOcclusionDebugKernel;
-
- cmd.SetComputeConstantBufferParam(cs, ShaderIDs.OcclusionCullingCommonShaderVariables, m_CommonConstantBuffer, 0, m_CommonConstantBuffer.stride);
-
- cmd.SetComputeBufferParam(cs, kernel, ShaderIDs._OcclusionDebugOverlay, occluderCtx.occlusionDebugOverlay);
-
- Vector2Int mip0Size = occluderCtx.occluderMipBounds[0].size;
- cmd.DispatchCompute(cs, kernel, (mip0Size.x + 7) / 8, (mip0Size.y + 7) / 8, occluderCtx.subviewCount);
-
- // mark as cleared in the dictionary
- occluderCtx.debugNeedsClear = false;
- m_OccluderContextData[contextIndex] = occluderCtx;
- }
- }
-
- private OccluderHandles PrepareOccluders(RenderGraph renderGraph, in OccluderParameters occluderParams)
- {
- OccluderHandles occluderHandles = new OccluderHandles();
- if (occluderParams.depthTexture.IsValid())
- {
- if (!m_ViewIDToIndexMap.TryGetValue(occluderParams.viewInstanceID, out var contextIndex))
- contextIndex = NewContext(occluderParams.viewInstanceID);
-
- OccluderContext ctx = m_OccluderContextData[contextIndex];
- ctx.PrepareOccluders(occluderParams);
- occluderHandles = ctx.Import(renderGraph);
- m_OccluderContextData[contextIndex] = ctx;
- }
- else
- {
- DeleteContext(occluderParams.viewInstanceID);
- }
- return occluderHandles;
- }
-
- private void CreateFarDepthPyramid(ComputeCommandBuffer cmd, in OccluderParameters occluderParams, ReadOnlySpan<OccluderSubviewUpdate> occluderSubviewUpdates, in OccluderHandles occluderHandles)
- {
- if (!m_ViewIDToIndexMap.TryGetValue(occluderParams.viewInstanceID, out var contextIndex))
- return;
-
- var silhouettePlanes = m_SilhouettePlaneCache.GetSubArray(occluderParams.viewInstanceID);
-
- OccluderContext ctx = m_OccluderContextData[contextIndex];
- ctx.CreateFarDepthPyramid(cmd, occluderParams, occluderSubviewUpdates, occluderHandles, silhouettePlanes, m_OccluderDepthPyramidCS, m_OccluderDepthDownscaleKernel);
- ctx.version++;
- m_OccluderContextData[contextIndex] = ctx;
-
- var slot = m_OccluderContextSlots[contextIndex];
- slot.lastUsedFrameIndex = m_FrameIndex;
- m_OccluderContextSlots[contextIndex] = slot;
- }
-
- private class UpdateOccludersPassData
- {
- public OccluderParameters occluderParams;
- public List<OccluderSubviewUpdate> occluderSubviewUpdates;
- public OccluderHandles occluderHandles;
- }
-
- public bool UpdateInstanceOccluders(RenderGraph renderGraph, in OccluderParameters occluderParams, ReadOnlySpan<OccluderSubviewUpdate> occluderSubviewUpdates)
- {
- var occluderHandles = PrepareOccluders(renderGraph, occluderParams);
- if (!occluderHandles.occluderDepthPyramid.IsValid())
- return false;
-
- using (var builder = renderGraph.AddComputePass<UpdateOccludersPassData>("Update Occluders", out var passData, m_ProfilingSamplerUpdateOccluders))
- {
- builder.AllowGlobalStateModification(true);
-
- passData.occluderParams = occluderParams;
- if (passData.occluderSubviewUpdates is null)
- passData.occluderSubviewUpdates = new List<OccluderSubviewUpdate>();
- else
- passData.occluderSubviewUpdates.Clear();
- for (int i = 0; i < occluderSubviewUpdates.Length; ++i)
- passData.occluderSubviewUpdates.Add(occluderSubviewUpdates[i]);
- passData.occluderHandles = occluderHandles;
-
- builder.UseTexture(passData.occluderParams.depthTexture);
- passData.occluderHandles.UseForOccluderUpdate(builder);
-
- builder.SetRenderFunc(
- (UpdateOccludersPassData data, ComputeGraphContext context) =>
- {
- Span<OccluderSubviewUpdate> occluderSubviewUpdates = stackalloc OccluderSubviewUpdate[data.occluderSubviewUpdates.Count];
- int subviewMask = 0;
- for (int i = 0; i < data.occluderSubviewUpdates.Count; ++i)
- {
- occluderSubviewUpdates[i] = data.occluderSubviewUpdates[i];
- subviewMask |= 1 << data.occluderSubviewUpdates[i].subviewIndex;
- }
-
- var batcher = GPUResidentDrawer.instance.batcher;
- batcher.occlusionCullingCommon.CreateFarDepthPyramid(context.cmd, in data.occluderParams, occluderSubviewUpdates, in data.occluderHandles);
- batcher.instanceCullingBatcher.InstanceOccludersUpdated(data.occluderParams.viewInstanceID, subviewMask);
- });
- }
-
- return true;
- }
-
- internal void UpdateSilhouettePlanes(int viewInstanceID, NativeArray<Plane> planes)
- {
- m_SilhouettePlaneCache.Update(viewInstanceID, planes, m_FrameIndex);
- }
-
- internal OcclusionCullingDebugOutput GetOcclusionTestDebugOutput(int viewInstanceID)
- {
- if (m_ViewIDToIndexMap.TryGetValue(viewInstanceID, out var contextIndex) && m_OccluderContextSlots[contextIndex].valid)
- return m_OccluderContextData[contextIndex].GetDebugOutput();
- return new OcclusionCullingDebugOutput();
- }
-
- public void UpdateOccluderStats(DebugRendererBatcherStats debugStats)
- {
- debugStats.occluderStats.Clear();
- foreach (var pair in m_ViewIDToIndexMap)
- {
- if (pair.Value < m_OccluderContextSlots.Length && m_OccluderContextSlots[pair.Value].valid)
- {
- debugStats.occluderStats.Add(new DebugOccluderStats
- {
- viewInstanceID = pair.Key,
- subviewCount = m_OccluderContextData[pair.Value].subviewCount,
- occluderMipLayoutSize = m_OccluderContextData[pair.Value].occluderMipLayoutSize,
- });
- }
- }
- }
-
- internal bool HasOccluderContext(int viewInstanceID)
- {
- return m_ViewIDToIndexMap.ContainsKey(viewInstanceID);
- }
-
- internal bool GetOccluderContext(int viewInstanceID, out OccluderContext occluderContext)
- {
- if (m_ViewIDToIndexMap.TryGetValue(viewInstanceID, out var contextIndex) && m_OccluderContextSlots[contextIndex].valid)
- {
- occluderContext = m_OccluderContextData[contextIndex];
- return true;
- }
-
- occluderContext = new OccluderContext();
- return false;
- }
-
- internal void UpdateFrame()
- {
- for (int i = 0; i < m_OccluderContextData.Count; ++i)
- {
- if (!m_OccluderContextSlots[i].valid)
- continue;
-
- OccluderContext occluderCtx = m_OccluderContextData[i];
- var slot = m_OccluderContextSlots[i];
- //Garbage collect unused contexts for a long time:
- if ((m_FrameIndex - slot.lastUsedFrameIndex) >= s_MaxContextGCFrame)
- {
- DeleteContext(slot.viewInstanceID);
- continue;
- }
-
- occluderCtx.debugNeedsClear = true;
- m_OccluderContextData[i] = occluderCtx;
- }
- m_SilhouettePlaneCache.FreeUnusedSlots(m_FrameIndex, s_MaxContextGCFrame);
- ++m_FrameIndex;
- }
-
- private int NewContext(int viewInstanceID)
- {
- int newSlot = -1;
- var newCtxSlot = new OccluderContextSlot { valid = true, viewInstanceID = viewInstanceID, lastUsedFrameIndex = m_FrameIndex };
- var newCtx = new OccluderContext() {};
- if (m_FreeOccluderContexts.Length > 0)
- {
- newSlot = m_FreeOccluderContexts[m_FreeOccluderContexts.Length - 1];
- m_FreeOccluderContexts.RemoveAt(m_FreeOccluderContexts.Length - 1);
- m_OccluderContextData[newSlot] = newCtx;
- m_OccluderContextSlots[newSlot] = newCtxSlot;
- }
- else
- {
- newSlot = m_OccluderContextData.Count;
- m_OccluderContextData.Add(newCtx);
- m_OccluderContextSlots.Add(newCtxSlot);
- }
-
- m_ViewIDToIndexMap.Add(viewInstanceID, newSlot);
- return newSlot;
- }
-
- private void DeleteContext(int viewInstanceID)
- {
- if (!m_ViewIDToIndexMap.TryGetValue(viewInstanceID, out var contextIndex) || !m_OccluderContextSlots[contextIndex].valid)
- return;
-
- m_OccluderContextData[contextIndex].Dispose();
- m_OccluderContextSlots[contextIndex] = new OccluderContextSlot { valid = false };
- m_FreeOccluderContexts.Add(contextIndex);
- m_ViewIDToIndexMap.Remove(viewInstanceID);
- }
-
- public void Dispose()
- {
- CoreUtils.Destroy(m_DebugOcclusionTestMaterial);
- CoreUtils.Destroy(m_OccluderDebugViewMaterial);
-
- for (int i = 0; i < m_OccluderContextData.Count; ++i)
- {
- if (m_OccluderContextSlots[i].valid)
- m_OccluderContextData[i].Dispose();
- }
-
- m_SilhouettePlaneCache.Dispose();
-
- m_ViewIDToIndexMap.Dispose();
- m_FreeOccluderContexts.Dispose();
- m_OccluderContextData.Clear();
- m_OccluderContextSlots.Dispose();
-
- m_CommonShaderVariables.Dispose();
- m_CommonConstantBuffer.Release();
- m_DebugShaderVariables.Dispose();
- m_DebugConstantBuffer.Release();
- }
- }
- }
|