From e5ca56fd105a994b19d34194d0d10a062e82b8ca Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Thu, 29 Jul 2021 15:11:00 +0200 Subject: [PATCH 1/3] Display approx MB cost in vmem --- .../Lighting/ProbeVolume/ProbeBrickIndex.cs | 3 ++ .../Lighting/ProbeVolume/ProbeBrickPool.cs | 28 ++++++++++++++++--- .../ProbeVolume/ProbeIndexOfIndices.cs | 3 +- .../ProbeVolume/ProbeReferenceVolume.cs | 16 ++++++++++- .../RenderPipeline/HDRenderPipelineUI.cs | 10 +++++++ 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickIndex.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickIndex.cs index 51968df97ed..1d6b22f7e22 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickIndex.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickIndex.cs @@ -23,6 +23,7 @@ internal class ProbeBrickIndex ComputeBuffer m_PhysicalIndexBuffer; int[] m_PhysicalIndexBufferData; + internal int estimatedVMemCost { get; private set; } [DebuggerDisplay("Brick [{position}, {subdivisionLevel}]")] [Serializable] @@ -103,6 +104,8 @@ internal ProbeBrickIndex(ProbeVolumeTextureMemoryBudget memoryBudget) m_PhysicalIndexBuffer = new ComputeBuffer(physicalBufferSize, sizeof(int), ComputeBufferType.Structured); m_NextFreeChunk = 0; + estimatedVMemCost = physicalBufferSize * sizeof(int); + // Should be done by a compute shader Clear(); Profiler.EndSample(); diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickPool.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickPool.cs index a642c8544ed..b67e94d86f3 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickPool.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickPool.cs @@ -59,6 +59,8 @@ internal void Cleanup() internal const int kBrickProbeCountPerDim = kBrickCellCount + 1; internal const int kBrickProbeCountTotal = kBrickProbeCountPerDim * kBrickProbeCountPerDim * kBrickProbeCountPerDim; + internal int estimatedVMemCost { get; private set; } + const int kMaxPoolWidth = 1 << 11; // 2048 texels is a d3d11 limit for tex3d in all dimensions int m_AllocationSize; @@ -79,8 +81,10 @@ internal ProbeBrickPool(int allocationSize, ProbeVolumeTextureMemoryBudget memor int width, height, depth; DerivePoolSizeFromBudget(allocationSize, memoryBudget, out width, out height, out depth); + int estimatedCost = 0; + m_Pool = CreateDataLocation(width * height * depth, false, ProbeVolumeSHBands.SphericalHarmonicsL2, out estimatedCost); + estimatedVMemCost = estimatedCost; - m_Pool = CreateDataLocation(width * height * depth, false, ProbeVolumeSHBands.SphericalHarmonicsL2); Profiler.EndSample(); } @@ -90,7 +94,9 @@ internal void EnsureTextureValidity() if (m_Pool.TexL0_L1rx == null) { m_Pool.Cleanup(); - m_Pool = CreateDataLocation(m_Pool.width * m_Pool.height * m_Pool.depth, false, ProbeVolumeSHBands.SphericalHarmonicsL2); + int estimatedCost = 0; + m_Pool = CreateDataLocation(m_Pool.width * m_Pool.height * m_Pool.depth, false, ProbeVolumeSHBands.SphericalHarmonicsL2, out estimatedCost); + estimatedVMemCost = estimatedCost; } } @@ -213,26 +219,40 @@ static Vector3Int ProbeCountToDataLocSize(int numProbes) return new Vector3Int(width, height, depth); } - public static DataLocation CreateDataLocation(int numProbes, bool compressed, ProbeVolumeSHBands bands) + public static DataLocation CreateDataLocation(int numProbes, bool compressed, ProbeVolumeSHBands bands, out int allocatedBytes) { Vector3Int locSize = ProbeCountToDataLocSize(numProbes); int width = locSize.x; int height = locSize.y; int depth = locSize.z; + int texelCount = width * height * depth; + DataLocation loc; - loc.TexL0_L1rx = new Texture3D(width, height, depth, compressed ? GraphicsFormat.RGB_BC6H_UFloat : GraphicsFormat.R16G16B16A16_SFloat, TextureCreationFlags.None, 1); + allocatedBytes = 0; + loc.TexL0_L1rx = new Texture3D(width, height, depth, GraphicsFormat.R16G16B16A16_SFloat, TextureCreationFlags.None, 1); + allocatedBytes += texelCount * 8; loc.TexL1_G_ry = new Texture3D(width, height, depth, compressed ? GraphicsFormat.RGBA_BC7_UNorm : GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.None, 1); + allocatedBytes += texelCount * (compressed ? 1 : 4); + loc.TexL1_B_rz = new Texture3D(width, height, depth, compressed ? GraphicsFormat.RGBA_BC7_UNorm : GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.None, 1); + allocatedBytes += texelCount * (compressed ? 1 : 4); if (bands == ProbeVolumeSHBands.SphericalHarmonicsL2) { loc.TexL2_0 = new Texture3D(width, height, depth, compressed ? GraphicsFormat.RGBA_BC7_UNorm : GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.None, 1); + allocatedBytes += texelCount * (compressed ? 1 : 4); + loc.TexL2_1 = new Texture3D(width, height, depth, compressed ? GraphicsFormat.RGBA_BC7_UNorm : GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.None, 1); + allocatedBytes += texelCount * (compressed ? 1 : 4); + loc.TexL2_2 = new Texture3D(width, height, depth, compressed ? GraphicsFormat.RGBA_BC7_UNorm : GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.None, 1); + allocatedBytes += texelCount * (compressed ? 1 : 4); + loc.TexL2_3 = new Texture3D(width, height, depth, compressed ? GraphicsFormat.RGBA_BC7_UNorm : GraphicsFormat.R8G8B8A8_UNorm, TextureCreationFlags.None, 1); + allocatedBytes += texelCount * (compressed ? 1 : 4); } else { diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeIndexOfIndices.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeIndexOfIndices.cs index 3ef50048ec1..2433acf4c93 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeIndexOfIndices.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeIndexOfIndices.cs @@ -12,6 +12,7 @@ namespace UnityEngine.Experimental.Rendering internal class ProbeCellIndices { const int kUintPerEntry = 3; + internal int estimatedVMemCost { get; private set; } internal struct IndexMetaData { @@ -20,7 +21,6 @@ internal struct IndexMetaData internal int firstChunkIndex; internal int minSubdiv; - internal void Pack(out uint[] vals) { vals = new uint[kUintPerEntry]; @@ -86,6 +86,7 @@ internal ProbeCellIndices(Vector3Int cellMin, Vector3Int cellMax, int cellSizeIn m_IndexOfIndicesBuffer = new ComputeBuffer(flatCellCount, kUintPerEntry * sizeof(uint)); m_IndexOfIndicesData = new uint[bufferSize]; m_NeedUpdateComputeBuffer = false; + estimatedVMemCost = flatCellCount * kUintPerEntry * sizeof(uint); } internal int GetFlatIdxForCell(Vector3Int cellPosition) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs index 80642bb4607..21123463ff7 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs @@ -623,6 +623,7 @@ public void Initialize(in ProbeVolumeSystemParameters parameters) #endif } + /// /// Cleanup the Probe Volume system. /// public void Cleanup() @@ -638,6 +639,18 @@ public void Cleanup() m_IsInitialized = false; } + /// + /// Get approximate video memory impact, in bytes, of the system. + /// + /// An approximation of the video memory impact, in bytes, of the system + public int GetVMemCost() + { + if (!m_ProbeReferenceVolumeInit) + return 0; + + return m_Pool.estimatedVMemCost + m_Index.estimatedVMemCost + m_CellIndices.estimatedVMemCost; + } + void RemoveCell(Cell cell) { if (cell.loaded) @@ -905,7 +918,8 @@ void LoadPendingCells(bool loadAll = false) var path = sortInfo.sourceAsset; bool compressed = false; - var dataLocation = ProbeBrickPool.CreateDataLocation(cell.sh.Length, compressed, ProbeVolumeSHBands.SphericalHarmonicsL2); + int allocatedBytes = 0; + var dataLocation = ProbeBrickPool.CreateDataLocation(cell.sh.Length, compressed, ProbeVolumeSHBands.SphericalHarmonicsL2, out allocatedBytes); ProbeBrickPool.FillDataLocation(ref dataLocation, cell.sh, ProbeVolumeSHBands.SphericalHarmonicsL2); cell.flatIdxInCellIndices = m_CellIndices.GetFlatIdxForCell(cell.position); diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs index 3bb5e0ccb82..3988c338294 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs @@ -219,6 +219,16 @@ static void Drawer_SectionProbeVolume(SerializedHDRenderPipelineAsset serialized EditorGUILayout.PropertyField(serialized.renderPipelineSettings.supportProbeVolume, Styles.supportProbeVolumeContent); EditorGUILayout.PropertyField(serialized.renderPipelineSettings.probeVolumeTextureSize, Styles.probeVolumeMemoryBudget); EditorGUILayout.PropertyField(serialized.renderPipelineSettings.probeVolumeSHBands, Styles.probeVolumeSHBands); + + int estimatedVMemCost = ProbeReferenceVolume.instance.GetVMemCost(); + if (estimatedVMemCost == 0) + { + EditorGUILayout.HelpBox($"Estimated GPU Memory cost 0.\nProbe reference volume is not used in the scene and resources haven't been allocated yet.", MessageType.Info, wide: true); + } + else + { + EditorGUILayout.HelpBox($"Estimated GPU Memory cost {estimatedVMemCost/(1000 * 1000)} MB.", MessageType.Info, wide: true); + } } else { From d323609b624fd823332c556cc3e0724e3407f602 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Thu, 29 Jul 2021 15:22:30 +0200 Subject: [PATCH 2/3] Dont allocate SH2 memory when using SH1 only. --- .../Lighting/ProbeVolume/ProbeBrickPool.cs | 9 ++++++--- .../ProbeVolume/ProbeReferenceVolume.cs | 18 +++++++++++------- .../Runtime/RenderPipeline/HDRenderPipeline.cs | 3 ++- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickPool.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickPool.cs index b67e94d86f3..e8bce452a60 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickPool.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeBrickPool.cs @@ -69,20 +69,23 @@ internal void Cleanup() BrickChunkAlloc m_NextFreeChunk; Stack m_FreeList; - internal ProbeBrickPool(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget) + ProbeVolumeSHBands m_SHBands; + + internal ProbeBrickPool(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget, ProbeVolumeSHBands shBands) { Profiler.BeginSample("Create ProbeBrickPool"); m_NextFreeChunk.x = m_NextFreeChunk.y = m_NextFreeChunk.z = 0; m_AllocationSize = allocationSize; m_MemoryBudget = memoryBudget; + m_SHBands = shBands; m_FreeList = new Stack(256); int width, height, depth; DerivePoolSizeFromBudget(allocationSize, memoryBudget, out width, out height, out depth); int estimatedCost = 0; - m_Pool = CreateDataLocation(width * height * depth, false, ProbeVolumeSHBands.SphericalHarmonicsL2, out estimatedCost); + m_Pool = CreateDataLocation(width * height * depth, false, shBands, out estimatedCost); estimatedVMemCost = estimatedCost; Profiler.EndSample(); @@ -95,7 +98,7 @@ internal void EnsureTextureValidity() { m_Pool.Cleanup(); int estimatedCost = 0; - m_Pool = CreateDataLocation(m_Pool.width * m_Pool.height * m_Pool.depth, false, ProbeVolumeSHBands.SphericalHarmonicsL2, out estimatedCost); + m_Pool = CreateDataLocation(m_Pool.width * m_Pool.height * m_Pool.depth, false, m_SHBands, out estimatedCost); estimatedVMemCost = estimatedCost; } } diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs index 21123463ff7..899643d6ce0 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs @@ -229,6 +229,7 @@ public struct ProbeVolumeSystemParameters public Shader probeDebugShader; public ProbeVolumeSceneBounds sceneBounds; + public ProbeVolumeSHBands shBands; } public struct ProbeVolumeShadingParameters @@ -569,6 +570,7 @@ struct InitInfo #endif ProbeVolumeTextureMemoryBudget m_MemoryBudget; + ProbeVolumeSHBands m_SHBands; internal bool clearAssetsOnVolumeClear = false; @@ -611,8 +613,9 @@ public void Initialize(in ProbeVolumeSystemParameters parameters) } m_MemoryBudget = parameters.memoryBudget; + m_SHBands = parameters.shBands; InitializeDebug(parameters.probeDebugMesh, parameters.probeDebugShader); - InitProbeReferenceVolume(kProbeIndexPoolAllocationSize, m_MemoryBudget); + InitProbeReferenceVolume(kProbeIndexPoolAllocationSize, m_MemoryBudget, m_SHBands); m_IsInitialized = true; sceneBounds = parameters.sceneBounds; #if UNITY_EDITOR @@ -775,7 +778,7 @@ void PerformPendingIndexChangeAndInit() if (m_NeedsIndexRebuild) { CleanupLoadedData(); - InitProbeReferenceVolume(kProbeIndexPoolAllocationSize, m_MemoryBudget); + InitProbeReferenceVolume(kProbeIndexPoolAllocationSize, m_MemoryBudget, m_SHBands); m_HasChangedIndex = true; m_NeedsIndexRebuild = false; } @@ -919,8 +922,8 @@ void LoadPendingCells(bool loadAll = false) bool compressed = false; int allocatedBytes = 0; - var dataLocation = ProbeBrickPool.CreateDataLocation(cell.sh.Length, compressed, ProbeVolumeSHBands.SphericalHarmonicsL2, out allocatedBytes); - ProbeBrickPool.FillDataLocation(ref dataLocation, cell.sh, ProbeVolumeSHBands.SphericalHarmonicsL2); + var dataLocation = ProbeBrickPool.CreateDataLocation(cell.sh.Length, compressed, m_SHBands, out allocatedBytes); + ProbeBrickPool.FillDataLocation(ref dataLocation, cell.sh, m_SHBands); cell.flatIdxInCellIndices = m_CellIndices.GetFlatIdxForCell(cell.position); @@ -966,14 +969,15 @@ public void PerformPendingOperations(bool loadAllCells = false) /// /// Size used for the chunk allocator that handles bricks. /// Probe reference volume memory budget. - void InitProbeReferenceVolume(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget) + /// Probe reference volume SH bands. + void InitProbeReferenceVolume(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget, ProbeVolumeSHBands shBands) { var minCellPosition = m_PendingInitInfo.pendingMinCellPosition; var maxCellPosition = m_PendingInitInfo.pendingMaxCellPosition; if (!m_ProbeReferenceVolumeInit) { Profiler.BeginSample("Initialize Reference Volume"); - m_Pool = new ProbeBrickPool(allocationSize, memoryBudget); + m_Pool = new ProbeBrickPool(allocationSize, memoryBudget, shBands); m_Index = new ProbeBrickIndex(memoryBudget); m_CellIndices = new ProbeCellIndices(minCellPosition, maxCellPosition, (int)Mathf.Pow(3, m_MaxSubdivision - 1)); @@ -1116,7 +1120,7 @@ RegId AddBricks(List bricks, ProbeBrickPool.DataLocation dataloc, ProbeBr } // Update the pool and index and ignore any potential frame latency related issues for now - m_Pool.Update(dataloc, m_TmpSrcChunks, ch_list, ProbeVolumeSHBands.SphericalHarmonicsL2); + m_Pool.Update(dataloc, m_TmpSrcChunks, ch_list, m_SHBands); m_BricksLoaded = true; diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs index 4702767ab6f..dba1b1a4854 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.cs @@ -381,7 +381,8 @@ public HDRenderPipeline(HDRenderPipelineAsset asset) memoryBudget = m_Asset.currentPlatformRenderPipelineSettings.probeVolumeMemoryBudget, probeDebugMesh = defaultResources.assets.sphereMesh, probeDebugShader = defaultResources.shaders.probeVolumeDebugShader, - sceneBounds = m_GlobalSettings.GetOrCreateAPVSceneBounds() + sceneBounds = m_GlobalSettings.GetOrCreateAPVSceneBounds(), + shBands = m_Asset.currentPlatformRenderPipelineSettings.probeVolumeSHBands }); RegisterRetrieveOfProbeVolumeExtraDataAction(); } From cf481e00cc620e1e30427b2240cad3ab1d95a4d5 Mon Sep 17 00:00:00 2001 From: FrancescoC-Unity Date: Thu, 29 Jul 2021 16:47:19 +0200 Subject: [PATCH 3/3] Renaming function. --- .../Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs | 2 +- .../Editor/RenderPipeline/HDRenderPipelineUI.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs index 899643d6ce0..a7692fb7344 100644 --- a/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs +++ b/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs @@ -646,7 +646,7 @@ public void Cleanup() /// Get approximate video memory impact, in bytes, of the system. /// /// An approximation of the video memory impact, in bytes, of the system - public int GetVMemCost() + public int GetVideoMemoryCost() { if (!m_ProbeReferenceVolumeInit) return 0; diff --git a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs index 3988c338294..42f0333e6a1 100644 --- a/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs +++ b/com.unity.render-pipelines.high-definition/Editor/RenderPipeline/HDRenderPipelineUI.cs @@ -220,7 +220,7 @@ static void Drawer_SectionProbeVolume(SerializedHDRenderPipelineAsset serialized EditorGUILayout.PropertyField(serialized.renderPipelineSettings.probeVolumeTextureSize, Styles.probeVolumeMemoryBudget); EditorGUILayout.PropertyField(serialized.renderPipelineSettings.probeVolumeSHBands, Styles.probeVolumeSHBands); - int estimatedVMemCost = ProbeReferenceVolume.instance.GetVMemCost(); + int estimatedVMemCost = ProbeReferenceVolume.instance.GetVideoMemoryCost(); if (estimatedVMemCost == 0) { EditorGUILayout.HelpBox($"Estimated GPU Memory cost 0.\nProbe reference volume is not used in the scene and resources haven't been allocated yet.", MessageType.Info, wide: true);