A game about forced loneliness, made by TACStudios
at master 200 lines 8.0 kB view raw
1using CellIndexInfo = UnityEngine.Rendering.ProbeReferenceVolume.CellIndexInfo; 2 3namespace UnityEngine.Rendering 4{ 5 internal class ProbeGlobalIndirection 6 { 7 const int kUintPerEntry = 3; 8 internal int estimatedVMemCost { get; private set; } 9 10 // IMPORTANT! IF THIS VALUE CHANGES DATA NEEDS TO BE REBAKED. 11 internal const int kEntryMaxSubdivLevel = 3; 12 13 internal struct IndexMetaData 14 { 15 static uint[] s_PackedValues = new uint[kUintPerEntry]; 16 17 internal Vector3Int minLocalIdx; 18 internal Vector3Int maxLocalIdxPlusOne; 19 internal int firstChunkIndex; 20 internal int minSubdiv; 21 22 internal void Pack(out uint[] vals) 23 { 24 vals = s_PackedValues; 25 for (int i = 0; i < kUintPerEntry; ++i) 26 { 27 vals[i] = 0; 28 } 29 30 // TODO: Note this packing is too generous, we can get rid of 1 uint 31 // minLocalIndex is in cell space so it has an upper bound 32 // first chunk index is also on 16bits max when using max memory budget 33 // see comment below about size of valid 34 // 35 // UINT 0: 36 // FirstChunkIndex 29 bit 37 // MinSubdiv 3 bit 38 // UINT 1: 39 // minLocalIdx.x 10 bit 40 // minLocalIdx.y 10 bit 41 // minLocalIdx.z 10 bit 42 // UINT 2: 43 // sizeOfValid.x 10 bit 44 // sizeOfValid.y 10 bit 45 // sizeOfValid.z 10 bit 46 47 // This is always less than CellSize(kEntryMaxSubdivLevel)+1 == 28. See GetEntrySubdivLevel() 48 var sizeOfValid = maxLocalIdxPlusOne - minLocalIdx; 49 50 vals[0] = (uint)firstChunkIndex & 0x1FFFFFFF; 51 vals[0] |= ((uint)minSubdiv & 0x7) << 29; 52 53 vals[1] = (uint)minLocalIdx.x & 0x3FF; 54 vals[1] |= ((uint)minLocalIdx.y & 0x3FF) << 10; 55 vals[1] |= ((uint)minLocalIdx.z & 0x3FF) << 20; 56 57 vals[2] = (uint)sizeOfValid.x & 0x3FF; 58 vals[2] |= ((uint)sizeOfValid.y & 0x3FF) << 10; 59 vals[2] |= ((uint)sizeOfValid.z & 0x3FF) << 20; 60 } 61 } 62 63 ComputeBuffer m_IndexOfIndicesBuffer; 64 uint[] m_IndexOfIndicesData; 65 66 int m_CellSizeInMinBricks; 67 68 Vector3Int m_EntriesCount; 69 Vector3Int m_EntryMin; 70 Vector3Int m_EntryMax; 71 72 internal void GetMinMaxEntry(out Vector3Int minEntry, out Vector3Int maxEntry) 73 { 74 minEntry = m_EntryMin; 75 maxEntry = m_EntryMax; 76 } 77 78 bool m_NeedUpdateComputeBuffer; 79 80 internal Vector3Int GetGlobalIndirectionDimension() => m_EntriesCount; 81 internal Vector3Int GetGlobalIndirectionMinEntry() => m_EntryMin; 82 83 int entrySizeInBricks => Mathf.Min((int)Mathf.Pow(ProbeBrickPool.kBrickCellCount, kEntryMaxSubdivLevel), m_CellSizeInMinBricks); 84 internal int entriesPerCellDimension => m_CellSizeInMinBricks / Mathf.Max(1, entrySizeInBricks); 85 86 int GetFlatIndex(Vector3Int normalizedPos) 87 { 88 return normalizedPos.z * (m_EntriesCount.x * m_EntriesCount.y) + normalizedPos.y * m_EntriesCount.x + normalizedPos.x; 89 } 90 91 internal ProbeGlobalIndirection(Vector3Int cellMin, Vector3Int cellMax, int cellSizeInMinBricks) 92 { 93 m_CellSizeInMinBricks = cellSizeInMinBricks; 94 95 Vector3Int cellCount = cellMax + Vector3Int.one - cellMin; 96 m_EntriesCount = cellCount * entriesPerCellDimension; 97 m_EntryMin = cellMin * entriesPerCellDimension; 98 99 m_EntryMax = (cellMax + Vector3Int.one) * entriesPerCellDimension - Vector3Int.one; 100 101 int flatEntryCount = m_EntriesCount.x * m_EntriesCount.y * m_EntriesCount.z; 102 int bufferSize = kUintPerEntry * flatEntryCount; 103 m_IndexOfIndicesBuffer = new ComputeBuffer(flatEntryCount, kUintPerEntry * sizeof(uint)); 104 m_IndexOfIndicesData = new uint[bufferSize]; 105 m_NeedUpdateComputeBuffer = false; 106 estimatedVMemCost = flatEntryCount * kUintPerEntry * sizeof(uint); 107 } 108 109 110 internal int GetFlatIdxForEntry(Vector3Int entryPosition) 111 { 112 Vector3Int normalizedPos = entryPosition - m_EntryMin; 113 Debug.Assert(normalizedPos.x >= 0 && normalizedPos.y >= 0 && normalizedPos.z >= 0); 114 115 return GetFlatIndex(normalizedPos); 116 } 117 118 internal int[] GetFlatIndicesForCell(Vector3Int cellPosition) 119 { 120 Vector3Int firstEntryPosition = cellPosition * entriesPerCellDimension; 121 int entriesPerCellDim = m_CellSizeInMinBricks / entrySizeInBricks; 122 123 int[] outListOfIndices = new int[entriesPerCellDimension * entriesPerCellDimension * entriesPerCellDimension]; 124 125 int i = 0; 126 for (int x = 0; x < entriesPerCellDim; ++x) 127 { 128 for (int y = 0; y < entriesPerCellDim; ++y) 129 { 130 for (int z = 0; z < entriesPerCellDim; ++z) 131 { 132 outListOfIndices[i++] = GetFlatIdxForEntry(firstEntryPosition + new Vector3Int(x, y, z)); 133 } 134 } 135 } 136 137 return outListOfIndices; 138 } 139 140 internal void UpdateCell(CellIndexInfo cellInfo) 141 { 142 for (int entry = 0; entry < cellInfo.flatIndicesInGlobalIndirection.Length; ++entry) 143 { 144 int entryIndex = cellInfo.flatIndicesInGlobalIndirection[entry]; 145 ProbeBrickIndex.IndirectionEntryUpdateInfo entryUpdateInfo = cellInfo.updateInfo.entriesInfo[entry]; 146 147 int minSubdivCellSize = ProbeReferenceVolume.CellSize(entryUpdateInfo.minSubdivInCell); 148 IndexMetaData metaData = new IndexMetaData(); 149 metaData.minSubdiv = entryUpdateInfo.minSubdivInCell; 150 metaData.minLocalIdx = entryUpdateInfo.hasOnlyBiggerBricks ? Vector3Int.zero : entryUpdateInfo.minValidBrickIndexForCellAtMaxRes / minSubdivCellSize; 151 metaData.maxLocalIdxPlusOne = entryUpdateInfo.hasOnlyBiggerBricks ? Vector3Int.one : entryUpdateInfo.maxValidBrickIndexForCellAtMaxResPlusOne / minSubdivCellSize; 152 metaData.firstChunkIndex = entryUpdateInfo.firstChunkIndex; 153 154 metaData.Pack(out uint[] packedVals); 155 156 for (int i = 0; i < kUintPerEntry; ++i) 157 { 158 m_IndexOfIndicesData[entryIndex * kUintPerEntry + i] = packedVals[i]; 159 } 160 } 161 162 m_NeedUpdateComputeBuffer = true; 163 } 164 165 internal void MarkEntriesAsUnloaded(int[] entriesFlatIndices) 166 { 167 for (int entry = 0; entry < entriesFlatIndices.Length; ++entry) 168 { 169 for (int i = 0; i < kUintPerEntry; ++i) 170 { 171 m_IndexOfIndicesData[entriesFlatIndices[entry] * kUintPerEntry + i] = 0xFFFFFFFF; 172 } 173 } 174 m_NeedUpdateComputeBuffer = true; 175 } 176 177 178 internal void PushComputeData() 179 { 180 m_IndexOfIndicesBuffer.SetData(m_IndexOfIndicesData); 181 m_NeedUpdateComputeBuffer = false; 182 } 183 184 internal void GetRuntimeResources(ref ProbeReferenceVolume.RuntimeResources rr) 185 { 186 // If we are pending an update of the actual compute buffer we do it here 187 if (m_NeedUpdateComputeBuffer) 188 { 189 PushComputeData(); 190 } 191 rr.cellIndices = m_IndexOfIndicesBuffer; 192 } 193 194 internal void Cleanup() 195 { 196 CoreUtils.SafeRelease(m_IndexOfIndicesBuffer); 197 m_IndexOfIndicesBuffer = null; 198 } 199 } 200}