Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal class ProbeBrickIndex
ComputeBuffer m_PhysicalIndexBuffer;
int[] m_PhysicalIndexBufferData;

internal int estimatedVMemCost { get; private set; }

[DebuggerDisplay("Brick [{position}, {subdivisionLevel}]")]
[Serializable]
Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -67,20 +69,25 @@ internal void Cleanup()
BrickChunkAlloc m_NextFreeChunk;
Stack<BrickChunkAlloc> 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<BrickChunkAlloc>(256);

int width, height, depth;
DerivePoolSizeFromBudget(allocationSize, memoryBudget, out width, out height, out depth);
int estimatedCost = 0;
m_Pool = CreateDataLocation(width * height * depth, false, shBands, out estimatedCost);
estimatedVMemCost = estimatedCost;

m_Pool = CreateDataLocation(width * height * depth, false, ProbeVolumeSHBands.SphericalHarmonicsL2);
Profiler.EndSample();
}

Expand All @@ -90,7 +97,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, m_SHBands, out estimatedCost);
estimatedVMemCost = estimatedCost;
}
}

Expand Down Expand Up @@ -213,26 +222,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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace UnityEngine.Experimental.Rendering
internal class ProbeCellIndices
{
const int kUintPerEntry = 3;
internal int estimatedVMemCost { get; private set; }

internal struct IndexMetaData
{
Expand All @@ -20,7 +21,6 @@ internal struct IndexMetaData
internal int firstChunkIndex;
internal int minSubdiv;


internal void Pack(out uint[] vals)
{
vals = new uint[kUintPerEntry];
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ public struct ProbeVolumeSystemParameters
public Shader probeDebugShader;

public ProbeVolumeSceneBounds sceneBounds;
public ProbeVolumeSHBands shBands;
}

public struct ProbeVolumeShadingParameters
Expand Down Expand Up @@ -569,6 +570,7 @@ struct InitInfo
#endif

ProbeVolumeTextureMemoryBudget m_MemoryBudget;
ProbeVolumeSHBands m_SHBands;

internal bool clearAssetsOnVolumeClear = false;

Expand Down Expand Up @@ -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
Expand All @@ -623,6 +626,7 @@ public void Initialize(in ProbeVolumeSystemParameters parameters)
#endif
}

/// <summary>
/// Cleanup the Probe Volume system.
/// </summary>
public void Cleanup()
Expand All @@ -638,6 +642,18 @@ public void Cleanup()
m_IsInitialized = false;
}

/// <summary>
/// Get approximate video memory impact, in bytes, of the system.
/// </summary>
/// <returns>An approximation of the video memory impact, in bytes, of the system<returns>
public int GetVideoMemoryCost()
{
if (!m_ProbeReferenceVolumeInit)
return 0;

return m_Pool.estimatedVMemCost + m_Index.estimatedVMemCost + m_CellIndices.estimatedVMemCost;
}

void RemoveCell(Cell cell)
{
if (cell.loaded)
Expand Down Expand Up @@ -762,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;
}
Expand Down Expand Up @@ -905,8 +921,9 @@ void LoadPendingCells(bool loadAll = false)
var path = sortInfo.sourceAsset;

bool compressed = false;
var dataLocation = ProbeBrickPool.CreateDataLocation(cell.sh.Length, compressed, ProbeVolumeSHBands.SphericalHarmonicsL2);
ProbeBrickPool.FillDataLocation(ref dataLocation, cell.sh, ProbeVolumeSHBands.SphericalHarmonicsL2);
int allocatedBytes = 0;
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);

Expand Down Expand Up @@ -952,14 +969,15 @@ public void PerformPendingOperations(bool loadAllCells = false)
/// </summary>
/// <param name ="allocationSize"> Size used for the chunk allocator that handles bricks.</param>
/// <param name ="memoryBudget">Probe reference volume memory budget.</param>
void InitProbeReferenceVolume(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget)
/// <param name ="shBands">Probe reference volume SH bands.</param>
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));
Expand Down Expand Up @@ -1102,7 +1120,7 @@ RegId AddBricks(List<Brick> 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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.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);
}
else
{
EditorGUILayout.HelpBox($"Estimated GPU Memory cost {estimatedVMemCost/(1000 * 1000)} MB.", MessageType.Info, wide: true);
}
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down