internal ProbeBrickIndex(ProbeVolumeTextureMemoryBudget memoryBudget) { Profiler.BeginSample("Create ProbeBrickIndex"); m_CenterRS = new Vector3Int(0, 0, 0); m_VoxelToBricks = new Dictionary <Vector3Int, List <VoxelMeta> >(); m_BricksToVoxels = new Dictionary <Cell, BrickMeta>(); m_NeedUpdateIndexComputeBuffer = false; m_IndexInChunks = Mathf.CeilToInt((float)SizeOfPhysicalIndexFromBudget(memoryBudget) / kIndexChunkSize); m_AvailableChunkCount = m_IndexInChunks; m_IndexChunks = new BitArray(Mathf.Max(1, m_IndexInChunks)); int physicalBufferSize = m_IndexInChunks * kIndexChunkSize; m_PhysicalIndexBufferData = new int[physicalBufferSize]; 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(); }
/// <summary> /// Initialize the reference volume. /// </summary> /// <param name ="allocationSize"> Size used for the chunk allocator that handles bricks.</param> /// <param name ="memoryBudget">Probe reference volume memory budget.</param> /// <param name ="indexDimensions">Dimensions of the index data structure.</param> public void InitProbeReferenceVolume(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget, Vector3Int indexDimensions) { if (!m_ProbeReferenceVolumeInit) { Profiler.BeginSample("Initialize Reference Volume"); m_Pool = new ProbeBrickPool(allocationSize, memoryBudget); m_Index = new ProbeBrickIndex(indexDimensions); m_TmpBricks[0] = new List <Brick>(); m_TmpBricks[1] = new List <Brick>(); m_TmpBricks[0].Capacity = m_TmpBricks[1].Capacity = 1024; // initialize offsets m_PositionOffsets[0] = 0.0f; float probeDelta = 1.0f / ProbeBrickPool.kBrickCellCount; for (int i = 1; i < ProbeBrickPool.kBrickProbeCountPerDim - 1; i++) { m_PositionOffsets[i] = i * probeDelta; } m_PositionOffsets[m_PositionOffsets.Length - 1] = 1.0f; Profiler.EndSample(); m_ProbeReferenceVolumeInit = true; } m_NeedLoadAsset = true; }
/// <summary> /// Initialize the reference volume. /// </summary> /// <param name ="allocationSize"> Size used for the chunk allocator that handles bricks.</param> /// <param name ="memoryBudget">Probe reference volume memory budget.</param> /// <param name ="indexDimensions">Dimensions of the index data structure.</param> public void InitProbeReferenceVolume(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget, Vector3Int indexDimensions) { if (!m_ProbeReferenceVolumeInit) { Profiler.BeginSample("Initialize Reference Volume"); m_Pool = new ProbeBrickPool(allocationSize, memoryBudget); m_Index = new ProbeBrickIndex(indexDimensions); m_TmpBricks[0] = new List <Brick>(); m_TmpBricks[1] = new List <Brick>(); m_TmpBricks[0].Capacity = m_TmpBricks[1].Capacity = 1024; // initialize offsets m_PositionOffsets[0] = 0.0f; float probeDelta = 1.0f / ProbeBrickPool.kBrickCellCount; for (int i = 1; i < ProbeBrickPool.kBrickProbeCountPerDim - 1; i++) { m_PositionOffsets[i] = i * probeDelta; } m_PositionOffsets[m_PositionOffsets.Length - 1] = 1.0f; Profiler.EndSample(); m_ProbeReferenceVolumeInit = true; // Write constants on init to start with right data. m_Index.WriteConstants(ref m_Transform, m_Pool.GetPoolDimensions(), m_NormalBias); // Set the normalBiasFromProfile to avoid re-update of the constants up until the next change in profile editor normalBiasFromProfile = m_NormalBias; } m_NeedLoadAsset = true; }
/// <summary> /// Initialize the reference volume. /// </summary> /// <param name ="allocationSize"> Size used for the chunk allocator that handles bricks.</param> /// <param name ="memoryBudget">Probe reference volume memory budget.</param> /// <param name ="indexDimensions">Dimensions of the index data structure.</param> public void InitProbeReferenceVolume(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget, Vector3Int indexDimensions) { if (!m_ProbeReferenceVolumeInit) { Profiler.BeginSample("Initialize Reference Volume"); m_Pool = new ProbeBrickPool(allocationSize, memoryBudget); if ((indexDimensions.x * (indexDimensions.y + 1) * indexDimensions.z) == 0) { // Give a momentarily dummy size to allow the system to function with no asset assigned. indexDimensions = new Vector3Int(1, 1, 1); } m_Index = new ProbeBrickIndex(indexDimensions); m_TmpBricks[0] = new List <Brick>(); m_TmpBricks[1] = new List <Brick>(); m_TmpBricks[0].Capacity = m_TmpBricks[1].Capacity = 1024; // initialize offsets m_PositionOffsets[0] = 0.0f; float probeDelta = 1.0f / ProbeBrickPool.kBrickCellCount; for (int i = 1; i < ProbeBrickPool.kBrickProbeCountPerDim - 1; i++) { m_PositionOffsets[i] = i * probeDelta; } m_PositionOffsets[m_PositionOffsets.Length - 1] = 1.0f; Profiler.EndSample(); m_ProbeReferenceVolumeInit = true; } m_NeedLoadAsset = true; }
void DerivePoolSizeFromBudget(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget, out int width, out int height, out int depth) { // TODO: This is fairly simplistic for now and relies on the enum to have the value set to the desired numbers, // might change the heuristic later on. width = (int)memoryBudget; height = (int)memoryBudget; depth = kBrickProbeCountPerDim; }
/// <summary> /// Set the memory budget for the Probe Volume System. /// </summary> /// <param name="budget"></param> public void SetMemoryBudget(ProbeVolumeTextureMemoryBudget budget) { if (m_MemoryBudget != budget) { m_MemoryBudget = budget; Cleanup(); InitProbeReferenceVolume(s_ProbeIndexPoolAllocationSize, m_MemoryBudget, m_PendingIndexDimChange); } }
internal ProbeBrickPool(int allocationSize, ProbeVolumeTextureMemoryBudget memoryBudget) { Profiler.BeginSample("Create ProbeBrickPool"); m_NextFreeChunk.x = m_NextFreeChunk.y = m_NextFreeChunk.z = 0; m_AllocationSize = allocationSize; m_MemoryBudget = memoryBudget; m_FreeList = new Stack <BrickChunkAlloc>(256); int width, height, depth; DerivePoolSizeFromBudget(allocationSize, memoryBudget, out width, out height, out depth); m_Pool = CreateDataLocation(width * height * depth, false, ProbeVolumeSHBands.SphericalHarmonicsL2); Profiler.EndSample(); }
internal ProbeBrickPool(ProbeVolumeTextureMemoryBudget memoryBudget, ProbeVolumeSHBands shBands) { Profiler.BeginSample("Create ProbeBrickPool"); m_NextFreeChunk.x = m_NextFreeChunk.y = m_NextFreeChunk.z = 0; m_SHBands = shBands; m_FreeList = new Stack <BrickChunkAlloc>(256); DerivePoolSizeFromBudget(memoryBudget, out int width, out int height, out int depth); m_Pool = CreateDataLocation(width * height * depth, false, shBands, "APV", true, out int estimatedCost); estimatedVMemCost = estimatedCost; m_AvailableChunkCount = (m_Pool.width / (kProbePoolChunkSizeInBricks * kBrickProbeCountPerDim)) * (m_Pool.height / kBrickProbeCountPerDim) * (m_Pool.depth / kBrickProbeCountPerDim); Profiler.EndSample(); }
int SizeOfPhysicalIndexFromBudget(ProbeVolumeTextureMemoryBudget memoryBudget) { switch (memoryBudget) { case ProbeVolumeTextureMemoryBudget.MemoryBudgetLow: // 16 MB - 4 million of bricks worth of space. At full resolution and a distance of 1 meter between probes, this is roughly 474 * 474 * 474 meters worth of bricks. If 0.25x on Y axis, this is equivalent to 948 * 118 * 948 meters return(16000000); case ProbeVolumeTextureMemoryBudget.MemoryBudgetMedium: // 32 MB - 8 million of bricks worth of space. At full resolution and a distance of 1 meter between probes, this is roughly 600 * 600 * 600 meters worth of bricks. If 0.25x on Y axis, this is equivalent to 1200 * 150 * 1200 meters return(32000000); case ProbeVolumeTextureMemoryBudget.MemoryBudgetHigh: // 64 MB - 16 million of bricks worth of space. At full resolution and a distance of 1 meter between probes, this is roughly 756 * 756 * 756 meters worth of bricks. If 0.25x on Y axis, this is equivalent to 1512 * 184 * 1512 meters return(64000000); } return(32000000); }