Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,27 @@ public bool Equals(BRGMatrix other)
}
}

internal struct BRGDrawData
{
public int length;
public NativeArray<int> sourceAABBIndex;
public NativeArray<AABB> bounds;

public void Resize(int capacity)
{
sourceAABBIndex.ResizeArray(capacity);
bounds.ResizeArray(capacity);
}

public void Dispose()
{
if (sourceAABBIndex.IsCreated)
sourceAABBIndex.Dispose();
if (bounds.IsCreated)
bounds.Dispose();
}
}

internal struct BRGTransformUpdater
{
private const int sBlockSize = 128;
Expand All @@ -60,13 +81,17 @@ internal struct BRGTransformUpdater
private TransformAccessArray m_Transforms;
private NativeArray<BRGMatrix> m_CachedTransforms;

public NativeArray<int> m_UpdateQueueCounter;
public NativeArray<int> m_TransformUpdateIndexQueue;
public NativeArray<BRGGpuTransformUpdate> m_TransformUpdateDataQueue;
public NativeArray<int> m_ProbeUpdateIndexQueue;
public NativeArray<SphericalHarmonicsL2> m_ProbeUpdateDataQueue;
public NativeArray<Vector4> m_ProbeOcclusionUpdateDataQueue;
public NativeArray<Vector3> m_QueryProbePosition;
private NativeHashMap<int, int> m_MeshToBoundIndexMap;
private NativeArray<AABB> m_MeshBounds;
private int m_MeshBoundsCount;

private NativeArray<int> m_UpdateQueueCounter;
private NativeArray<int> m_TransformUpdateIndexQueue;
private NativeArray<BRGGpuTransformUpdate> m_TransformUpdateDataQueue;
private NativeArray<int> m_ProbeUpdateIndexQueue;
private NativeArray<SphericalHarmonicsL2> m_ProbeUpdateDataQueue;
private NativeArray<Vector4> m_ProbeOcclusionUpdateDataQueue;
private NativeArray<Vector3> m_QueryProbePosition;

private JobHandle m_UpdateTransformsJobHandle;
private LightProbesQuery m_LightProbesQuery;
Expand All @@ -80,6 +105,9 @@ internal struct BRGTransformUpdater
private int m_TransformUpdateKernel;
private int m_ProbeUpdateKernel;

private BRGDrawData m_DrawData;
public BRGDrawData drawData => m_DrawData;

private enum QueueType
{
Transform,
Expand Down Expand Up @@ -183,6 +211,12 @@ private struct UpdateJob : IJobParallelForTransform
[ReadOnly]
public NativeArray<int> inputIndices;

[ReadOnly]
public NativeArray<int> sourceAABBIndex;

[ReadOnly]
public NativeArray<AABB> meshAABB;

[ReadOnly]
public NativeArray<bool> hasProbes;

Expand All @@ -207,6 +241,8 @@ private struct UpdateJob : IJobParallelForTransform
public NativeArray<Vector4> probeOcclusionUpdateDataQueue;
[NativeDisableContainerSafetyRestriction]
public NativeArray<Vector3> probeQueryPosition;
[NativeDisableContainerSafetyRestriction]
public NativeArray<AABB> boundsToUpdate;

private int IncrementCounter(QueueType queueType)
{
Expand All @@ -229,6 +265,9 @@ public void Execute(int index, TransformAccess transform)
if (cachedTransforms[index].Equals(m))
return;

AABB srcAABB = meshAABB[sourceAABBIndex[index]];
boundsToUpdate[index] = AABB.Transform(transform.localToWorldMatrix, srcAABB);

int outputIndex = IncrementCounter(QueueType.Transform);
int instanceIndex = inputIndices[index];
transformUpdateIndexQueue[outputIndex] = instanceIndex;
Expand Down Expand Up @@ -313,10 +352,32 @@ public void Initialize()
m_QueryProbePosition = new NativeArray<Vector3>(m_Capacity, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
m_UpdateQueueCounter = new NativeArray<int>((int)QueueType.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);

m_MeshToBoundIndexMap = new NativeHashMap<int, int>(1024, Allocator.Persistent);
m_MeshBounds = new NativeArray<AABB>(1024, Allocator.Persistent);
m_MeshBoundsCount = 0;

m_DrawData = new BRGDrawData();
m_DrawData.Resize(m_Capacity);

RecreteGpuBuffers();
}

public void RegisterTransformObject(int instanceIndex, Transform transformObject, bool hasLightProbe)
int RegisterMesh(Mesh mesh)
{
if (m_MeshToBoundIndexMap.TryGetValue(mesh.GetHashCode(), out var foundIndex))
return foundIndex;

int nextIndex = m_MeshBoundsCount++;
if (nextIndex == m_MeshBounds.Length)
{
m_MeshBounds.ResizeArray(m_MeshBounds.Length * 2);
}

m_MeshToBoundIndexMap.Add(mesh.GetHashCode(), nextIndex);
return nextIndex;
}

public void RegisterTransformObject(int instanceIndex, Transform transformObject, Mesh mesh, bool hasLightProbe)
{
int newLen = m_Length + 1;
if (newLen == m_Capacity)
Expand All @@ -333,6 +394,7 @@ public void RegisterTransformObject(int instanceIndex, Transform transformObject
m_ProbeUpdateDataQueue.ResizeArray(m_Capacity);
m_ProbeOcclusionUpdateDataQueue.ResizeArray(m_Capacity);
m_QueryProbePosition.ResizeArray(m_Capacity);
m_DrawData.Resize(m_Capacity);
RecreteGpuBuffers();
}

Expand All @@ -346,7 +408,13 @@ public void RegisterTransformObject(int instanceIndex, Transform transformObject
cachedTransform.SetTranslation(new float3(10000.0f, 10000.0f, 10000.0f));
m_CachedTransforms[m_Length] = cachedTransform;

int boundsIndex = RegisterMesh(mesh);
var localAABB = mesh.bounds.ToAABB();
m_MeshBounds[boundsIndex] = localAABB;
m_DrawData.sourceAABBIndex[m_Length] = boundsIndex;
m_DrawData.bounds[m_Length] = AABB.Transform(transformObject.localToWorldMatrix, mesh.bounds.ToAABB());
m_Length = newLen;
m_DrawData.length = newLen;
}

public void StartUpdateJobs()
Expand All @@ -362,6 +430,8 @@ public void StartUpdateJobs()
{
minDistance = System.Single.Epsilon,
inputIndices = m_Indices,
sourceAABBIndex = m_DrawData.sourceAABBIndex,
meshAABB = m_MeshBounds,
hasProbes = m_HasProbes,
tetrahedronCache = m_TetrahedronCache,
lightProbesQuery = m_LightProbesQuery,
Expand All @@ -372,7 +442,8 @@ public void StartUpdateJobs()
probeUpdateIndexQueue = m_ProbeUpdateIndexQueue,
probeUpdateDataQueue = m_ProbeUpdateDataQueue,
probeOcclusionUpdateDataQueue = m_ProbeOcclusionUpdateDataQueue,
probeQueryPosition = m_QueryProbePosition
probeQueryPosition = m_QueryProbePosition,
boundsToUpdate = m_DrawData.bounds
};

m_UpdateTransformsJobHandle = jobData.ScheduleReadOnly(m_Transforms, 64);
Expand Down Expand Up @@ -436,6 +507,10 @@ public void Dispose()
m_ProbeUpdateIndexQueueBuffer.Release();
m_ProbeUpdateDataQueueBuffer.Release();
m_ProbeOcclusionUpdateDataQueueBuffer.Release();

m_MeshToBoundIndexMap.Dispose();
m_MeshBounds.Dispose();
m_DrawData.Dispose();
}
}

Expand Down
76 changes: 31 additions & 45 deletions com.unity.render-pipelines.core/Runtime/BatchRenderer/RenderBRG.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,6 @@ public struct DrawInstance
public int instanceIndex;
}

public struct DrawRenderer
{
public AABB bounds;
}

struct SHProperties
{
public float4 SHAr;
Expand Down Expand Up @@ -166,7 +161,6 @@ unsafe class SceneBRG
private NativeList<DrawInstance> m_instances;
private NativeArray<int> m_instanceIndices;
private NativeArray<int> m_drawIndices;
private NativeArray<DrawRenderer> m_renderers;
private BRGInstanceBufferOffsets m_instanceBufferOffsets;
private NativeList<DeferredMaterialInstance> m_deferredMaterialInstances;

Expand Down Expand Up @@ -202,33 +196,34 @@ private struct CullingJob : IJobParallelFor
[DeallocateOnJobCompletion] [ReadOnly] public NativeArray<FrustumPlanes.PlanePacket4> receiverPlanes;
[DeallocateOnJobCompletion] [ReadOnly] public NativeArray<int> splitCounts;

[ReadOnly] public NativeArray<DrawRenderer> renderers;
[ReadOnly] public BRGDrawData brgDrawData;

[WriteOnly] public NativeArray<ulong> rendererVisibility;

public void Execute(int index)
{
// Each invocation is culling 8 renderers (8 split bits * 8 renderers = 64 bit bitfield)
int start = index * 8;
int end = math.min(start + 8, renderers.Length);
int end = math.min(start + 8, brgDrawData.length);

ulong visibleBits = 0;
for (int i = start; i < end; i++)
{
AABB instanceBounds = brgDrawData.bounds[i];
#if DEBUG_LOG_CULLING_RESULTS_SLOW
bool receiverCulled = FrustumPlanes.Intersect2NoPartial(receiverPlanes, renderers[i].bounds) == FrustumPlanes.IntersectResult.Out;
bool receiverCulled = FrustumPlanes.Intersect2NoPartial(receiverPlanes, instanceBounds) == FrustumPlanes.IntersectResult.Out;
{
ulong splitMask = FrustumPlanes.Intersect2NoPartialMulti(planes, splitCounts, renderers[i].bounds);
ulong splitMask = FrustumPlanes.Intersect2NoPartialMulti(planes, splitCounts, instanceBounds);
if (receiverCulled && splitMask != 0)
{
splitMask = 0x80UL; // Use bit 8 to mark receiver culling for profiling output (only 6 bits needed for payload)
}
visibleBits |= splitMask << (8 * (i - start));
}
#else
if (FrustumPlanes.Intersect2NoPartial(receiverPlanes, renderers[i].bounds) != FrustumPlanes.IntersectResult.Out)
if (FrustumPlanes.Intersect2NoPartial(receiverPlanes, instanceBounds) != FrustumPlanes.IntersectResult.Out)
{
ulong splitMask = FrustumPlanes.Intersect2NoPartialMulti(planes, splitCounts, renderers[i].bounds);
ulong splitMask = FrustumPlanes.Intersect2NoPartialMulti(planes, splitCounts, instanceBounds);
visibleBits |= splitMask << (8 * (i - start)); // 8x 8 bit masks per uint64
}
#endif
Expand Down Expand Up @@ -697,7 +692,8 @@ public JobHandle OnPerformCulling(BatchRendererGroup rendererGroup, BatchCulling

cullingOutput.drawCommands[0] = drawCommands;

var visibilityLength = (m_renderers.Length + 7) / 8;
BRGDrawData drawData = m_BRGTransformUpdater.drawData;
var visibilityLength = (drawData.length + 7) / 8;
var rendererVisibility =
new NativeArray<ulong>(visibilityLength, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

Expand All @@ -706,7 +702,7 @@ public JobHandle OnPerformCulling(BatchRendererGroup rendererGroup, BatchCulling
planes = planes,
receiverPlanes = receiverPlanePackets,
splitCounts = splitCounts,
renderers = m_renderers,
brgDrawData = drawData,
rendererVisibility = rendererVisibility
};

Expand Down Expand Up @@ -870,24 +866,24 @@ public void Initialize(List<MeshRenderer> renderers, GeometryPool geometryPool)
Debug.Log("Converting " + renderers.Count + " renderers...");
#endif

m_renderers = new NativeArray<DrawRenderer>(renderers.Count, Allocator.Persistent);
int renderersLength = renderers.Count;
m_batchHash = new NativeHashMap<DrawKey, int>(1024, Allocator.Persistent);
m_rangeHash = new NativeHashMap<RangeKey, int>(1024, Allocator.Persistent);
m_drawBatches = new NativeList<DrawBatch>(Allocator.Persistent);
m_drawRanges = new NativeList<DrawRange>(Allocator.Persistent);
m_AddedRenderers = new List<MeshRenderer>(renderers.Count);
m_AddedRenderers = new List<MeshRenderer>(renderersLength);
m_GlobalGeoPool = geometryPool;

// Fill the GPU-persistent scene data ComputeBuffer
int bigDataBufferVector4Count =
4 /*zero*/
+ 1 /*probes*/
+ 1 /*speccube*/
+ 7 * m_renderers.Length /*per renderer SH*/
+ 1 * m_renderers.Length /*per renderer probe occlusion*/
+ 2 * m_renderers.Length /* per renderer lightmapindex + scale/offset*/
+ m_renderers.Length * 3 * 2 /*per renderer 4x3 matrix+inverse*/
+ 1 * m_renderers.Length; /*per renderer, vec4 with deferredMaterialData*/
+ 7 * renderersLength /*per renderer SH*/
+ 1 * renderersLength /*per renderer probe occlusion*/
+ 2 * renderersLength /* per renderer lightmapindex + scale/offset*/
+ renderersLength * 3 * 2 /*per renderer 4x3 matrix+inverse*/
+ 1 * renderersLength; /*per renderer, vec4 with deferredMaterialData*/

var vectorBuffer = new NativeArray<Vector4>(bigDataBufferVector4Count, Allocator.Temp);

Expand All @@ -903,19 +899,19 @@ public void Initialize(List<MeshRenderer> renderers, GeometryPool geometryPool)
startOffset++;

var SHArOffset = startOffset;
var SHAgOffset = SHArOffset + m_renderers.Length;
var SHAbOffset = SHAgOffset + m_renderers.Length;
var SHBrOffset = SHAbOffset + m_renderers.Length;
var SHBgOffset = SHBrOffset + m_renderers.Length;
var SHBbOffset = SHBgOffset + m_renderers.Length;
var SHCOffset = SHBbOffset + m_renderers.Length;

var probeOcclusionOffset = SHCOffset + m_renderers.Length;
var lightMapIndexOffset = probeOcclusionOffset + m_renderers.Length;
var lightMapScaleOffset = lightMapIndexOffset + m_renderers.Length;
var localToWorldOffset = lightMapScaleOffset + m_renderers.Length;
var worldToLocalOffset = localToWorldOffset + m_renderers.Length * 3;
var deferredMaterialDataOffset = worldToLocalOffset + m_renderers.Length * 3;
var SHAgOffset = SHArOffset + renderersLength;
var SHAbOffset = SHAgOffset + renderersLength;
var SHBrOffset = SHAbOffset + renderersLength;
var SHBgOffset = SHBrOffset + renderersLength;
var SHBbOffset = SHBgOffset + renderersLength;
var SHCOffset = SHBbOffset + renderersLength;

var probeOcclusionOffset = SHCOffset + renderersLength;
var lightMapIndexOffset = probeOcclusionOffset + renderersLength;
var lightMapScaleOffset = lightMapIndexOffset + renderersLength;
var localToWorldOffset = lightMapScaleOffset + renderersLength;
var worldToLocalOffset = localToWorldOffset + renderersLength * 3;
var deferredMaterialDataOffset = worldToLocalOffset + renderersLength * 3;

m_instanceBufferOffsets = new BRGInstanceBufferOffsets()
{
Expand Down Expand Up @@ -948,11 +944,6 @@ public void Initialize(List<MeshRenderer> renderers, GeometryPool geometryPool)
{
var renderer = renderers[i];

m_renderers[i] = new DrawRenderer
{
bounds = new AABB { Center = new float3(0, 0, 0), Extents = new float3(0, 0, 0) }
};

var meshFilter = renderer.gameObject.GetComponent<MeshFilter>();
if (!renderer || !meshFilter || !meshFilter.sharedMesh || renderer.enabled == false)
{
Expand Down Expand Up @@ -994,8 +985,6 @@ public void Initialize(List<MeshRenderer> renderers, GeometryPool geometryPool)
vectorBuffer[i * 3 + 1 + worldToLocalOffset] = new Vector4(mi.m11, mi.m21, mi.m02, mi.m12);
vectorBuffer[i * 3 + 2 + worldToLocalOffset] = new Vector4(mi.m22, mi.m03, mi.m13, mi.m23);

m_BRGTransformUpdater.RegisterTransformObject(i, rendererTransform, renderer.lightProbeUsage == LightProbeUsage.BlendProbes);

lpq.CalculateInterpolatedLightAndOcclusionProbe(rendererTransform.position, -1, out var lp,
out var probeOcclusion);

Expand All @@ -1010,9 +999,7 @@ public void Initialize(List<MeshRenderer> renderers, GeometryPool geometryPool)

vectorBuffer[probeOcclusionOffset + i] = probeOcclusion;

// Renderer bounds
var transformedBounds = AABB.Transform(m, meshFilter.sharedMesh.bounds.ToAABB());
m_renderers[i] = new DrawRenderer { bounds = transformedBounds };
m_BRGTransformUpdater.RegisterTransformObject(i, rendererTransform, meshFilter.sharedMesh, renderer.lightProbeUsage == LightProbeUsage.BlendProbes);

Mesh usedMesh = null;
var usedSubmeshIndices = new List<int>();
Expand Down Expand Up @@ -1233,7 +1220,6 @@ public void Destroy()
m_GPUPersistentInstanceData.Dispose();
m_BRGTransformUpdater.Dispose();

m_renderers.Dispose();
m_batchHash.Dispose();
m_rangeHash.Dispose();
m_drawBatches.Dispose();
Expand Down