A game about forced loneliness, made by TACStudios
at master 223 lines 8.5 kB view raw
1using System; 2using System.Collections.Generic; 3using Unity.Burst; 4using Unity.Collections; 5using Unity.Jobs; 6using UnityEngine.Assertions; 7using static UnityEngine.Rendering.RenderersParameters; 8 9namespace UnityEngine.Rendering 10{ 11 internal struct GPUInstanceComponentDesc 12 { 13 public int propertyID; 14 public int byteSize; 15 public bool isOverriden; 16 public bool isPerInstance; 17 public InstanceType instanceType; 18 public InstanceComponentGroup componentGroup; 19 20 public GPUInstanceComponentDesc(int inPropertyID, int inByteSize, bool inIsOverriden, bool inPerInstance, InstanceType inInstanceType, InstanceComponentGroup inComponentType) 21 { 22 propertyID = inPropertyID; 23 byteSize = inByteSize; 24 isOverriden = inIsOverriden; 25 isPerInstance = inPerInstance; 26 instanceType = inInstanceType; 27 componentGroup = inComponentType; 28 } 29 } 30 31 internal class GPUInstanceDataBuffer : IDisposable 32 { 33 private static int s_NextLayoutVersion = 0; 34 public static int NextVersion() { return ++s_NextLayoutVersion; } 35 36 public InstanceNumInfo instanceNumInfo; 37 public NativeArray<int> instancesNumPrefixSum; 38 public NativeArray<int> instancesSpan; 39 public int byteSize; 40 public int perInstanceComponentCount; 41 public int version; 42 public int layoutVersion; 43 public GraphicsBuffer gpuBuffer; 44 public GraphicsBuffer validComponentsIndicesGpuBuffer; 45 public GraphicsBuffer componentAddressesGpuBuffer; 46 public GraphicsBuffer componentInstanceIndexRangesGpuBuffer; 47 public GraphicsBuffer componentByteCountsGpuBuffer; 48 public NativeArray<GPUInstanceComponentDesc> descriptions; 49 public NativeArray<MetadataValue> defaultMetadata; 50 public NativeArray<int> gpuBufferComponentAddress; 51 public NativeParallelHashMap<int, int> nameToMetadataMap; 52 53 public bool valid => instancesSpan.IsCreated; 54 55 private static GPUInstanceIndex CPUInstanceToGPUInstance(in NativeArray<int> instancesNumPrefixSum, InstanceHandle instance) 56 { 57 bool valid = instance.valid && instance.type < InstanceType.Count; 58#if DEBUG 59 Assert.IsTrue(valid); 60#endif 61 62 if (!valid) 63 return GPUInstanceIndex.Invalid; 64 65 int instanceType = (int)instance.type; 66 int perTypeInstanceIndex = instance.instanceIndex; 67 int gpuInstanceIndex = instancesNumPrefixSum[instanceType] + perTypeInstanceIndex; 68 69 return new GPUInstanceIndex { index = gpuInstanceIndex }; 70 } 71 72 public int GetPropertyIndex(int propertyID, bool assertOnFail = true) 73 { 74 if (nameToMetadataMap.TryGetValue(propertyID, out int componentIndex)) 75 { 76 return componentIndex; 77 } 78 79 if (assertOnFail) 80 Assert.IsTrue(false, "Count not find gpu address for parameter specified: " + propertyID); 81 return -1; 82 } 83 84 public int GetGpuAddress(string strName, bool assertOnFail = true) 85 { 86 int componentIndex = GetPropertyIndex(Shader.PropertyToID(strName), false); 87 if (assertOnFail && componentIndex == -1) 88 Assert.IsTrue(false, "Count not find gpu address for parameter specified: " + strName); 89 90 return componentIndex != -1 ? gpuBufferComponentAddress[componentIndex] : -1; 91 } 92 93 public int GetGpuAddress(int propertyID, bool assertOnFail = true) 94 { 95 int componentIndex = GetPropertyIndex(propertyID, assertOnFail); 96 return componentIndex != -1 ? gpuBufferComponentAddress[componentIndex] : -1; 97 } 98 99 public GPUInstanceIndex CPUInstanceToGPUInstance(InstanceHandle instance) 100 { 101 return CPUInstanceToGPUInstance(instancesNumPrefixSum, instance); 102 } 103 104 public unsafe InstanceHandle GPUInstanceToCPUInstance(GPUInstanceIndex gpuInstanceIndex) 105 { 106 var instanceIndex = gpuInstanceIndex.index; 107 InstanceType instanceType = InstanceType.Count; 108 109 for(int i = 0; i < (int)InstanceType.Count; ++i) 110 { 111 int instanceNum = instanceNumInfo.GetInstanceNum((InstanceType)i); 112 if(instanceIndex < instanceNum) 113 { 114 instanceType = (InstanceType)i; 115 break; 116 } 117 instanceIndex -= instanceNum; 118 } 119 120 if(instanceType == InstanceType.Count) 121 return InstanceHandle.Invalid; 122 123 Assert.IsTrue(instanceIndex < instanceNumInfo.GetInstanceNum(instanceType)); 124 return InstanceHandle.Create(instanceIndex, instanceType); 125 } 126 127 public void CPUInstanceArrayToGPUInstanceArray(NativeArray<InstanceHandle> instances, NativeArray<GPUInstanceIndex> gpuInstanceIndices) 128 { 129 Assert.AreEqual(instances.Length, gpuInstanceIndices.Length); 130 131 Profiling.Profiler.BeginSample("CPUInstanceArrayToGPUInstanceArray"); 132 133 new ConvertCPUInstancesToGPUInstancesJob { instancesNumPrefixSum = instancesNumPrefixSum, instances = instances, gpuInstanceIndices = gpuInstanceIndices } 134 .Schedule(instances.Length, ConvertCPUInstancesToGPUInstancesJob.k_BatchSize).Complete(); 135 136 Profiling.Profiler.EndSample(); 137 } 138 139 public void Dispose() 140 { 141 if(instancesSpan.IsCreated) 142 instancesSpan.Dispose(); 143 144 if(instancesNumPrefixSum.IsCreated) 145 instancesNumPrefixSum.Dispose(); 146 147 if (descriptions.IsCreated) 148 descriptions.Dispose(); 149 150 if (defaultMetadata.IsCreated) 151 defaultMetadata.Dispose(); 152 153 if (gpuBufferComponentAddress.IsCreated) 154 gpuBufferComponentAddress.Dispose(); 155 156 if (nameToMetadataMap.IsCreated) 157 nameToMetadataMap.Dispose(); 158 159 if (gpuBuffer != null) 160 gpuBuffer.Release(); 161 162 if (validComponentsIndicesGpuBuffer != null) 163 validComponentsIndicesGpuBuffer.Release(); 164 165 if (componentAddressesGpuBuffer != null) 166 componentAddressesGpuBuffer.Release(); 167 168 if (componentInstanceIndexRangesGpuBuffer != null) 169 componentInstanceIndexRangesGpuBuffer.Release(); 170 171 if (componentByteCountsGpuBuffer != null) 172 componentByteCountsGpuBuffer.Release(); 173 } 174 175 public ReadOnly AsReadOnly() 176 { 177 return new ReadOnly(this); 178 } 179 180 internal readonly struct ReadOnly 181 { 182 private readonly NativeArray<int> instancesNumPrefixSum; 183 184 public ReadOnly(GPUInstanceDataBuffer buffer) 185 { 186 instancesNumPrefixSum = buffer.instancesNumPrefixSum; 187 } 188 189 public GPUInstanceIndex CPUInstanceToGPUInstance(InstanceHandle instance) 190 { 191 return GPUInstanceDataBuffer.CPUInstanceToGPUInstance(instancesNumPrefixSum, instance); 192 } 193 194 public void CPUInstanceArrayToGPUInstanceArray(NativeArray<InstanceHandle> instances, NativeArray<GPUInstanceIndex> gpuInstanceIndices) 195 { 196 Assert.AreEqual(instances.Length, gpuInstanceIndices.Length); 197 198 Profiling.Profiler.BeginSample("CPUInstanceArrayToGPUInstanceArray"); 199 200 new ConvertCPUInstancesToGPUInstancesJob { instancesNumPrefixSum = instancesNumPrefixSum, instances = instances, gpuInstanceIndices = gpuInstanceIndices } 201 .Schedule(instances.Length, ConvertCPUInstancesToGPUInstancesJob.k_BatchSize).Complete(); 202 203 Profiling.Profiler.EndSample(); 204 } 205 } 206 207 [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)] 208 struct ConvertCPUInstancesToGPUInstancesJob : IJobParallelFor 209 { 210 public const int k_BatchSize = 512; 211 212 [ReadOnly] public NativeArray<int> instancesNumPrefixSum; 213 [ReadOnly] public NativeArray<InstanceHandle> instances; 214 215 [WriteOnly] public NativeArray<GPUInstanceIndex> gpuInstanceIndices; 216 217 public void Execute(int index) 218 { 219 gpuInstanceIndices[index] = CPUInstanceToGPUInstance(instancesNumPrefixSum, instances[index]); 220 } 221 } 222 } 223}