// Runtime API starts here internal RegId AddBricks(List <Brick> bricks, ProbeBrickPool.DataLocation dataloc) { Profiler.BeginSample("AddBricks"); // calculate the number of chunks necessary int ch_size = m_Pool.GetChunkSize(); List <Chunk> ch_list = new List <Chunk>((bricks.Count + ch_size - 1) / ch_size); m_Pool.Allocate(ch_list.Capacity, ch_list); // copy chunks into pool m_TmpSrcChunks.Clear(); m_TmpSrcChunks.Capacity = ch_list.Count; Chunk c; c.x = 0; c.y = 0; c.z = 0; // currently this code assumes that the texture width is a multiple of the allocation chunk size for (int i = 0; i < ch_list.Count; i++) { m_TmpSrcChunks.Add(c); c.x += ch_size * ProbeBrickPool.kBrickProbeCountPerDim; if (c.x >= dataloc.width) { c.x = 0; c.y += ProbeBrickPool.kBrickProbeCountPerDim; if (c.y >= dataloc.height) { c.y = 0; c.z += ProbeBrickPool.kBrickProbeCountPerDim; } } } // 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_BricksLoaded = true; // create a registry entry for this request RegId id; m_ID++; id.id = m_ID; m_Registry.Add(id, ch_list); // update the index m_Index.AddBricks(id, bricks, ch_list, m_Pool.GetChunkSize(), m_Pool.GetPoolWidth(), m_Pool.GetPoolHeight()); Profiler.EndSample(); return(id); }
// This is very much modeled to be as close as possible to the way bricks are loaded in the texture pool. // Not necessarily a good thing. static void ComputeValidityMasks(BakingCell bakingCell) { var bricks = bakingCell.bricks; var cell = bakingCell; int chunkSize = ProbeBrickPool.GetChunkSize(); int brickChunksCount = (bricks.Length + chunkSize - 1) / chunkSize; var probeHasEmptySpaceInGrid = new NativeArray <bool>(bakingCell.probePositions.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); int chunkIndex = 0; while (chunkIndex < brickChunksCount) { int chunkToProcess = Math.Min(ProbeReferenceVolume.kTemporaryDataLocChunkCount, brickChunksCount - chunkIndex); Vector3Int locSize = ProbeBrickPool.ProbeCountToDataLocSize(ProbeReferenceVolume.kTemporaryDataLocChunkCount * ProbeBrickPool.GetChunkSizeInProbeCount()); int size = locSize.x * locSize.y * locSize.z; int startIndex = chunkIndex * ProbeBrickPool.GetChunkSizeInProbeCount(); int count = chunkToProcess * ProbeBrickPool.GetChunkSizeInProbeCount(); int shidx = startIndex; int bx = 0, by = 0, bz = 0; s_Validity_locData.Resize(size); s_ProbeIndices.Resize(size); Dictionary <Vector3Int, (float, Vector3, Bounds)> probesToRestoreInfo = new Dictionary <Vector3Int, (float, Vector3, Bounds)>(); HashSet <Vector3Int> probesToRestore = new HashSet <Vector3Int>(); for (int brickIdx = startIndex; brickIdx < (startIndex + count); brickIdx += ProbeBrickPool.kBrickProbeCountTotal) { for (int z = 0; z < ProbeBrickPool.kBrickProbeCountPerDim; z++) { for (int y = 0; y < ProbeBrickPool.kBrickProbeCountPerDim; y++) { for (int x = 0; x < ProbeBrickPool.kBrickProbeCountPerDim; x++) { int ix = bx + x; int iy = by + y; int iz = bz + z; if (shidx >= cell.validity.Length) { StoreScratchData(ix, iy, iz, locSize.x, locSize.y, 1.0f, shidx); } else { StoreScratchData(ix, iy, iz, locSize.x, locSize.y, ProbeReferenceVolume.Cell.GetValidityFromPacked(cell.validity[shidx]), shidx); // Check if we need to do some extra check on this probe. bool hasFreeNeighbourhood = false; Bounds invalidatingTouchupBound; if (s_ForceInvalidatedProbesAndTouchupVols.TryGetValue(cell.probePositions[shidx], out invalidatingTouchupBound)) { int actualBrickIdx = brickIdx / ProbeBrickPool.kBrickProbeCountTotal; float brickSize = ProbeReferenceVolume.CellSize(cell.bricks[actualBrickIdx].subdivisionLevel); Vector3 position = cell.probePositions[shidx]; probesToRestore.Add(new Vector3Int(ix, iy, iz)); var searchDistance = (brickSize * m_BakingProfile.minBrickSize) / ProbeBrickPool.kBrickCellCount; hasFreeNeighbourhood = NeighbourhoodIsEmptySpace(position, searchDistance, invalidatingTouchupBound); } probeHasEmptySpaceInGrid[shidx] = hasFreeNeighbourhood; } shidx++; } } } // update the pool index bx += ProbeBrickPool.kBrickProbeCountPerDim; if (bx >= locSize.x) { bx = 0; by += ProbeBrickPool.kBrickProbeCountPerDim; if (by >= locSize.y) { by = 0; bz += ProbeBrickPool.kBrickProbeCountPerDim; } } } for (int x = 0; x < locSize.x; ++x) { for (int y = 0; y < locSize.y; ++y) { for (int z = 0; z < locSize.z; ++z) { int outIdx = ReadProbeIndex(x, y, z, locSize.x, locSize.y); float probeValidity = ReadValidity(x, y, z, locSize.x, locSize.y); if (outIdx < cell.validity.Length) { float[] validities = new float[8]; bool forceAllValid = false; for (int o = 0; o < 8; ++o) { Vector3Int off = GetSampleOffset(o); Vector3Int samplePos = new Vector3Int(Mathf.Clamp(x + off.x, 0, locSize.x - 1), Mathf.Clamp(y + off.y, 0, locSize.y - 1), Mathf.Clamp(z + off.z, 0, ProbeBrickPool.kBrickProbeCountPerDim - 1)); if (probesToRestore.Contains(samplePos)) { if (probeHasEmptySpaceInGrid[outIdx]) { forceAllValid = true; } } validities[o] = ReadValidity(samplePos.x, samplePos.y, samplePos.z, locSize.x, locSize.y); } byte mask = forceAllValid ? (byte)255 : Convert.ToByte(PackValidity(validities)); float validity = probeValidity; cell.validity[outIdx] = ProbeReferenceVolume.Cell.PackValidityAndMask(validity, mask); } } } } chunkIndex += ProbeReferenceVolume.kTemporaryDataLocChunkCount; } probeHasEmptySpaceInGrid.Dispose(); }