You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
8.4 KiB
191 lines
8.4 KiB
using Unity.Collections;
|
|
using Unity.Burst;
|
|
using UnityEngine.Assertions;
|
|
|
|
namespace UnityEngine.Rendering
|
|
{
|
|
[BurstCompile]
|
|
internal static class InstanceDataSystemBurst
|
|
{
|
|
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
|
|
public static void ReallocateInstances(bool implicitInstanceIndices, in NativeArray<int> rendererGroupIDs, in NativeArray<GPUDrivenPackedRendererData> packedRendererData,
|
|
in NativeArray<int> instanceOffsets, in NativeArray<int> instanceCounts, ref InstanceAllocators instanceAllocators, ref CPUInstanceData instanceData,
|
|
ref CPUSharedInstanceData sharedInstanceData, ref NativeArray<InstanceHandle> instances,
|
|
ref NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash)
|
|
{
|
|
for (int i = 0; i < rendererGroupIDs.Length; ++i)
|
|
{
|
|
var rendererGroupID = rendererGroupIDs[i];
|
|
var hasTree = packedRendererData[i].hasTree;
|
|
|
|
int instanceCount;
|
|
int instanceOffset;
|
|
|
|
if (implicitInstanceIndices)
|
|
{
|
|
instanceCount = 1;
|
|
instanceOffset = i;
|
|
}
|
|
else
|
|
{
|
|
instanceCount = instanceCounts[i];
|
|
instanceOffset = instanceOffsets[i];
|
|
}
|
|
|
|
SharedInstanceHandle sharedInstance;
|
|
|
|
if (rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var instance, out var it))
|
|
{
|
|
sharedInstance = instanceData.Get_SharedInstance(instance);
|
|
|
|
int currentInstancesCount = sharedInstanceData.Get_RefCount(sharedInstance);
|
|
int instancesToFreeCount = currentInstancesCount - instanceCount;
|
|
|
|
if (instancesToFreeCount > 0)
|
|
{
|
|
bool success = true;
|
|
int freedInstancesCount = 0;
|
|
|
|
for (int j = 0; j < instanceCount; ++j)
|
|
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
|
|
|
|
Assert.IsTrue(success);
|
|
|
|
while (success)
|
|
{
|
|
var idx = instanceData.InstanceToIndex(instance);
|
|
instanceData.Remove(instance);
|
|
|
|
instanceAllocators.FreeInstance(instance);
|
|
|
|
rendererGroupInstanceMultiHash.Remove(it);
|
|
++freedInstancesCount;
|
|
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
|
|
}
|
|
|
|
Assert.AreEqual(instancesToFreeCount, freedInstancesCount);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sharedInstance = instanceAllocators.AllocateSharedInstance();
|
|
sharedInstanceData.AddNoGrow(sharedInstance);
|
|
}
|
|
|
|
if (instanceCount > 0)
|
|
{
|
|
sharedInstanceData.Set_RefCount(sharedInstance, instanceCount);
|
|
|
|
for (int j = 0; j < instanceCount; ++j)
|
|
{
|
|
int instanceIndex = instanceOffset + j;
|
|
|
|
if (instances[instanceIndex].valid)
|
|
continue;
|
|
|
|
InstanceHandle newInstance;
|
|
|
|
if (!hasTree)
|
|
newInstance = instanceAllocators.AllocateInstance(InstanceType.MeshRenderer);
|
|
else
|
|
newInstance = instanceAllocators.AllocateInstance(InstanceType.SpeedTree);
|
|
|
|
instanceData.AddNoGrow(newInstance);
|
|
int index = instanceData.InstanceToIndex(newInstance);
|
|
instanceData.sharedInstances[index] = sharedInstance;
|
|
instanceData.movedInCurrentFrameBits.Set(index, false);
|
|
instanceData.movedInPreviousFrameBits.Set(index, false);
|
|
instanceData.visibleInPreviousFrameBits.Set(index, false);
|
|
|
|
rendererGroupInstanceMultiHash.Add(rendererGroupID, newInstance);
|
|
instances[instanceIndex] = newInstance;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sharedInstanceData.Remove(sharedInstance);
|
|
instanceAllocators.FreeSharedInstance(sharedInstance);
|
|
}
|
|
}
|
|
}
|
|
|
|
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
|
|
public static void FreeRendererGroupInstances(in NativeArray<int>.ReadOnly rendererGroupsID, ref InstanceAllocators instanceAllocators, ref CPUInstanceData instanceData,
|
|
ref CPUSharedInstanceData sharedInstanceData, ref NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash)
|
|
{
|
|
foreach (var rendererGroupID in rendererGroupsID)
|
|
{
|
|
for (bool success = rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var instance, out var it); success;)
|
|
{
|
|
SharedInstanceHandle sharedInstance = instanceData.Get_SharedInstance(instance);
|
|
int sharedInstanceIndex = sharedInstanceData.SharedInstanceToIndex(sharedInstance);
|
|
int refCount = sharedInstanceData.refCounts[sharedInstanceIndex];
|
|
|
|
Assert.IsTrue(refCount > 0);
|
|
|
|
if (refCount > 1)
|
|
{
|
|
sharedInstanceData.refCounts[sharedInstanceIndex] = refCount - 1;
|
|
}
|
|
else
|
|
{
|
|
sharedInstanceData.Remove(sharedInstance);
|
|
instanceAllocators.FreeSharedInstance(sharedInstance);
|
|
}
|
|
|
|
var idx = instanceData.InstanceToIndex(instance);
|
|
instanceData.Remove(instance);
|
|
instanceAllocators.FreeInstance(instance);
|
|
|
|
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
|
|
}
|
|
|
|
rendererGroupInstanceMultiHash.Remove(rendererGroupID);
|
|
}
|
|
}
|
|
|
|
|
|
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
|
|
public static void FreeInstances(in NativeArray<InstanceHandle>.ReadOnly instances, ref InstanceAllocators instanceAllocators, ref CPUInstanceData instanceData,
|
|
ref CPUSharedInstanceData sharedInstanceData, ref NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash)
|
|
{
|
|
foreach (var instance in instances)
|
|
{
|
|
if (!instanceData.IsValidInstance(instance))
|
|
continue;
|
|
|
|
int instanceIndex = instanceData.InstanceToIndex(instance);
|
|
SharedInstanceHandle sharedInstance = instanceData.sharedInstances[instanceIndex];
|
|
int sharedInstanceIndex = sharedInstanceData.SharedInstanceToIndex(sharedInstance);
|
|
int refCount = sharedInstanceData.refCounts[sharedInstanceIndex];
|
|
var rendererGroupID = sharedInstanceData.rendererGroupIDs[sharedInstanceIndex];
|
|
|
|
Assert.IsTrue(refCount > 0);
|
|
|
|
if (refCount > 1)
|
|
{
|
|
sharedInstanceData.refCounts[sharedInstanceIndex] = refCount - 1;
|
|
}
|
|
else
|
|
{
|
|
sharedInstanceData.Remove(sharedInstance);
|
|
instanceAllocators.FreeSharedInstance(sharedInstance);
|
|
}
|
|
|
|
instanceData.Remove(instance);
|
|
instanceAllocators.FreeInstance(instance);
|
|
|
|
//@ This will have quadratic cost. Optimize later.
|
|
for (bool success = rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var i, out var it); success;)
|
|
{
|
|
if (instance.Equals(i))
|
|
{
|
|
rendererGroupInstanceMultiHash.Remove(it);
|
|
break;
|
|
}
|
|
success = rendererGroupInstanceMultiHash.TryGetNextValue(out i, ref it);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|