From b1a40da82d278acef22911012e9622e901cecd39 Mon Sep 17 00:00:00 2001 From: Kleber Garcia Date: Tue, 2 Nov 2021 13:59:03 -0400 Subject: [PATCH] ** Adding support for transforms for BRG ** * Updating filtering of BRG * Adding short circuit to updates of empty length * Formatting --- .../Runtime/BatchRenderer/AABB.cs | 12 +- .../BatchRenderer/BRGTransformUpdater.cs | 256 ++++++++++++++++++ .../BatchRenderer/BRGTransformUpdater.cs.meta | 11 + .../Runtime/BatchRenderer/BoundsToAABB.cs | 4 +- .../Runtime/BatchRenderer/Lightmaps.cs | 10 +- .../Runtime/BatchRenderer/RenderBRG.cs | 74 ++++- .../Runtime/BatchRenderer/Resources.meta | 8 + .../Resources/BRGTransformUpdateCS.compute | 31 +++ .../BRGTransformUpdateCS.compute.meta | 7 + .../Resources/BRGTransformUpdaterDefs.cs | 16 ++ .../Resources/BRGTransformUpdaterDefs.cs.hlsl | 47 ++++ .../BRGTransformUpdaterDefs.cs.hlsl.meta | 7 + .../Resources/BRGTransformUpdaterDefs.cs.meta | 11 + .../Runtime/BatchRenderer/ToggleBRG.cs | 34 +-- 14 files changed, 486 insertions(+), 42 deletions(-) create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/BRGTransformUpdater.cs create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/BRGTransformUpdater.cs.meta create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources.meta create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdateCS.compute create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdateCS.compute.meta create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.hlsl create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.hlsl.meta create mode 100644 com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.meta diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/AABB.cs b/com.unity.render-pipelines.core/Runtime/BatchRenderer/AABB.cs index 2f8c13a4661..845e23084f3 100644 --- a/com.unity.render-pipelines.core/Runtime/BatchRenderer/AABB.cs +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/AABB.cs @@ -42,13 +42,13 @@ public bool Contains(float3 point) public bool Contains(AABB b) { return Contains(b.Center + float3(-b.Extents.x, -b.Extents.y, -b.Extents.z)) - && Contains(b.Center + float3(-b.Extents.x, -b.Extents.y, b.Extents.z)) - && Contains(b.Center + float3(-b.Extents.x, b.Extents.y, -b.Extents.z)) - && Contains(b.Center + float3(-b.Extents.x, b.Extents.y, b.Extents.z)) + && Contains(b.Center + float3(-b.Extents.x, -b.Extents.y, b.Extents.z)) + && Contains(b.Center + float3(-b.Extents.x, b.Extents.y, -b.Extents.z)) + && Contains(b.Center + float3(-b.Extents.x, b.Extents.y, b.Extents.z)) && Contains(b.Center + float3(b.Extents.x, -b.Extents.y, -b.Extents.z)) - && Contains(b.Center + float3(b.Extents.x, -b.Extents.y, b.Extents.z)) - && Contains(b.Center + float3(b.Extents.x, b.Extents.y, -b.Extents.z)) - && Contains(b.Center + float3(b.Extents.x, b.Extents.y, b.Extents.z)); + && Contains(b.Center + float3(b.Extents.x, -b.Extents.y, b.Extents.z)) + && Contains(b.Center + float3(b.Extents.x, b.Extents.y, -b.Extents.z)) + && Contains(b.Center + float3(b.Extents.x, b.Extents.y, b.Extents.z)); } static float3 RotateExtents(float3 extents, float3 m0, float3 m1, float3 m2) diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/BRGTransformUpdater.cs b/com.unity.render-pipelines.core/Runtime/BatchRenderer/BRGTransformUpdater.cs new file mode 100644 index 00000000000..e15f00f5504 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/BRGTransformUpdater.cs @@ -0,0 +1,256 @@ +using UnityEngine.Jobs; +using Unity.Burst; +using Unity.Collections; +using Unity.Mathematics; +using System.Threading; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; + +namespace UnityEngine.Rendering +{ + + internal struct BRGTransformUpdater + { + private const int sBlockSize = 128; + private int m_Capacity; + private int m_Length; + private NativeArray m_Indices; + private TransformAccessArray m_Transforms; + private NativeArray m_CachedPositions; + private NativeArray m_CachedRotations; + private NativeArray m_CachedScales; + + public NativeArray m_UpdateQueueCounter; + public NativeArray m_TransformUpdateIndexQueue; + public NativeArray m_TransformUpdateDataQueue; + + private JobHandle m_UpdateTransformsJobHandle; + + private ComputeBuffer m_IndexQueueBuffer; + private ComputeBuffer m_DataQeueueBuffer; + private ComputeShader m_UpdateCS; + private int m_UpdateKernel; + + private static class BRGTransformParams + { + public static readonly int _TransformUpdateQueueCount = Shader.PropertyToID("_TransformUpdateQueueCount"); + public static readonly int _TransformUpdateOutputL2WVec4Offset = Shader.PropertyToID("_TransformUpdateOutputL2WVec4Offset"); + public static readonly int _TransformUpdateOutputW2LVec4Offset = Shader.PropertyToID("_TransformUpdateOutputW2LVec4Offset"); + public static readonly int _TransformUpdateDataQueue = Shader.PropertyToID("_TransformUpdateDataQueue"); + public static readonly int _TransformUpdateIndexQueue = Shader.PropertyToID("_TransformUpdateIndexQueue"); + public static readonly int _OutputTransformBuffer = Shader.PropertyToID("_OutputTransformBuffer"); + } + + private void LoadShaders() + { + m_UpdateCS = (ComputeShader)Resources.Load("BRGTransformUpdateCS"); + m_UpdateKernel = m_UpdateCS.FindKernel("ScatterUpdateMain"); + } + + private void AddUpdateCommand( + CommandBuffer cmdBuffer, + int queueCount, + int outputByteOffsetL2W, + int outputByteOffsetW2L, + ComputeBuffer inputIndexQueueBuffer, + ComputeBuffer inputDataQueueBuffer, + GraphicsBuffer outputBuffer, + NativeArray transformIndexQueue, + NativeArray updateDataQueue) + { + cmdBuffer.SetBufferData(inputIndexQueueBuffer, transformIndexQueue, 0, 0, queueCount); + cmdBuffer.SetBufferData(inputDataQueueBuffer, updateDataQueue, 0, 0, queueCount); + cmdBuffer.SetComputeIntParam(m_UpdateCS, BRGTransformParams._TransformUpdateQueueCount, queueCount); + cmdBuffer.SetComputeIntParam(m_UpdateCS, BRGTransformParams._TransformUpdateOutputL2WVec4Offset, outputByteOffsetL2W); + cmdBuffer.SetComputeIntParam(m_UpdateCS, BRGTransformParams._TransformUpdateOutputW2LVec4Offset, outputByteOffsetW2L); + cmdBuffer.SetComputeBufferParam(m_UpdateCS, m_UpdateKernel, BRGTransformParams._TransformUpdateIndexQueue, inputIndexQueueBuffer); + cmdBuffer.SetComputeBufferParam(m_UpdateCS, m_UpdateKernel, BRGTransformParams._TransformUpdateDataQueue, inputDataQueueBuffer); + cmdBuffer.SetComputeBufferParam(m_UpdateCS, m_UpdateKernel, BRGTransformParams._OutputTransformBuffer, outputBuffer); + cmdBuffer.DispatchCompute(m_UpdateCS, m_UpdateKernel, (queueCount + 63) / 64, 1, 1); + } + + [BurstCompile] + private struct UpdateJob : IJobParallelForTransform + { + public float minDistance; + + [ReadOnly] + public NativeArray inputIndices; + + public NativeArray cachedPositions; + public NativeArray cachedRotations; + public NativeArray cachedScales; + + [WriteOnly] + public NativeArray updateQueueCounter; + [NativeDisableContainerSafetyRestriction] + public NativeArray transformUpdateIndexQueue; + [NativeDisableContainerSafetyRestriction] + public NativeArray transformUpdateDataQueue; + + private int IncrementCounter() + { + int outputIndex = 0; + unsafe + { + int* ptr = (int*)updateQueueCounter.GetUnsafePtr(); + outputIndex = Interlocked.Increment(ref UnsafeUtility.AsRef(ptr)); + } + return outputIndex - 1; + } + + public void Execute(int index, TransformAccess transform) + { + bool positionChanged = math.distancesq(transform.position, cachedPositions[index]) > minDistance; + if (positionChanged) + cachedPositions[index] = transform.position; + + bool scalesChanged = math.distancesq(transform.localScale, cachedScales[index]) > minDistance; + if (scalesChanged) + cachedScales[index] = transform.localScale; + + quaternion tq = transform.rotation; + bool rotationChanged = math.distancesq(tq.value, cachedRotations[index].value) > minDistance; + if (rotationChanged) + cachedRotations[index] = tq; + + if (!rotationChanged && !scalesChanged && !positionChanged) + return; + + int outputIndex = IncrementCounter(); + transformUpdateIndexQueue[outputIndex] = inputIndices[index]; + + /* mat4x3 packed like this: + p1.x, p1.w, p2.z, p3.y, + p1.y, p2.x, p2.w, p3.z, + p1.z, p2.y, p3.x, p3.w, + 0.0, 0.0, 0.0, 1.0 + */ + var m = transform.localToWorldMatrix; + var mi = transform.worldToLocalMatrix; + transformUpdateDataQueue[outputIndex] = new BRGGpuTransformUpdate() + { + localToWorld0 = new float4(m.m00, m.m10, m.m20, m.m01), + localToWorld1 = new float4(m.m11, m.m21, m.m02, m.m12), + localToWorld2 = new float4(m.m22, m.m03, m.m13, m.m23), + worldToLocal0 = new float4(mi.m00, mi.m10, mi.m20, mi.m01), + worldToLocal1 = new float4(mi.m11, mi.m21, mi.m02, mi.m12), + worldToLocal2 = new float4(mi.m22, mi.m03, mi.m13, mi.m23), + }; + } + } + + private void RecreteGpuBuffers() + { + if (m_IndexQueueBuffer != null) + m_IndexQueueBuffer.Release(); + + if (m_DataQeueueBuffer != null) + m_DataQeueueBuffer.Release(); + + m_IndexQueueBuffer = new ComputeBuffer(m_Capacity, 4, ComputeBufferType.Raw); + m_DataQeueueBuffer = new ComputeBuffer(m_Capacity, System.Runtime.InteropServices.Marshal.SizeOf(), ComputeBufferType.Structured); + } + + public void Initialize() + { + m_IndexQueueBuffer = null; + m_DataQeueueBuffer = null; + + LoadShaders(); + + m_Length = 0; + m_Capacity = sBlockSize; + m_Transforms = new TransformAccessArray(m_Capacity); + m_Indices = new NativeArray(m_Capacity, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + m_CachedPositions = new NativeArray(m_Capacity, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + m_CachedRotations = new NativeArray(m_Capacity, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + m_CachedScales = new NativeArray(m_Capacity, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + m_TransformUpdateIndexQueue = new NativeArray(m_Capacity, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + m_TransformUpdateDataQueue = new NativeArray(m_Capacity, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + m_UpdateQueueCounter = new NativeArray(1, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + RecreteGpuBuffers(); + } + + public void RegisterTransformObject(int instanceIndex, Transform transformObject) + { + int newLen = m_Length + 1; + if (newLen == m_Capacity) + { + m_Capacity += sBlockSize; + m_Transforms.ResizeArray(m_Capacity); + m_Indices.ResizeArray(m_Capacity); + m_CachedPositions.ResizeArray(m_Capacity); + m_CachedRotations.ResizeArray(m_Capacity); + m_CachedScales.ResizeArray(m_Capacity); + m_TransformUpdateIndexQueue.ResizeArray(m_Capacity); + m_TransformUpdateDataQueue.ResizeArray(m_Capacity); + RecreteGpuBuffers(); + } + + m_Transforms.Add(transformObject); + m_Indices[m_Length] = instanceIndex; + m_CachedPositions[m_Length] = transformObject.position; + m_CachedRotations[m_Length] = transformObject.rotation; + m_CachedScales[m_Length] = transformObject.localScale; + + m_Length = newLen; + } + + public void StartUpdateJobs() + { + if (m_Length == 0) + return; + + m_UpdateQueueCounter[0] = 0; //reset queue to 0 + var jobData = new UpdateJob() + { + minDistance = System.Single.Epsilon, + inputIndices = m_Indices, + cachedPositions = m_CachedPositions, + cachedRotations = m_CachedRotations, + cachedScales = m_CachedScales, + + updateQueueCounter = m_UpdateQueueCounter, + transformUpdateIndexQueue = m_TransformUpdateIndexQueue, + transformUpdateDataQueue = m_TransformUpdateDataQueue + }; + + m_UpdateTransformsJobHandle = jobData.Schedule(m_Transforms); + } + + public bool EndUpdateJobs(CommandBuffer cmdBuffer, int outputByteOffsetL2W, int outputByteOffsetW2L, GraphicsBuffer outputBuffer) + { + if (m_Length == 0) + return false; + + m_UpdateTransformsJobHandle.Complete(); + bool hasUpdates = m_UpdateQueueCounter[0] != 0; + + if (hasUpdates) + AddUpdateCommand( + cmdBuffer, m_UpdateQueueCounter[0], + outputByteOffsetL2W, outputByteOffsetW2L, m_IndexQueueBuffer, m_DataQeueueBuffer, outputBuffer, + m_TransformUpdateIndexQueue, m_TransformUpdateDataQueue); + + return hasUpdates; + } + + public void Dispose() + { + m_Transforms.Dispose(); + m_Indices.Dispose(); + m_CachedPositions.Dispose(); + m_CachedRotations.Dispose(); + m_CachedScales.Dispose(); + + m_UpdateQueueCounter.Dispose(); + m_TransformUpdateIndexQueue.Dispose(); + m_TransformUpdateDataQueue.Dispose(); + + m_IndexQueueBuffer.Release(); + m_DataQeueueBuffer.Release(); + } + } + +} diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/BRGTransformUpdater.cs.meta b/com.unity.render-pipelines.core/Runtime/BatchRenderer/BRGTransformUpdater.cs.meta new file mode 100644 index 00000000000..46494058dbc --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/BRGTransformUpdater.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0384c2952818ba478b23b5bca5b75b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/BoundsToAABB.cs b/com.unity.render-pipelines.core/Runtime/BatchRenderer/BoundsToAABB.cs index 7ac8b61ea45..9376860bef5 100644 --- a/com.unity.render-pipelines.core/Runtime/BatchRenderer/BoundsToAABB.cs +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/BoundsToAABB.cs @@ -6,12 +6,12 @@ public static class AABBExtensions { public static AABB ToAABB(this Bounds bounds) { - return new AABB { Center = bounds.center, Extents = bounds.extents}; + return new AABB { Center = bounds.center, Extents = bounds.extents }; } public static Bounds ToBounds(this AABB aabb) { - return new Bounds { center = aabb.Center, extents = aabb.Extents}; + return new Bounds { center = aabb.Center, extents = aabb.Extents }; } } } diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Lightmaps.cs b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Lightmaps.cs index 485c7216baf..e80773d28f4 100644 --- a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Lightmaps.cs +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Lightmaps.cs @@ -105,7 +105,7 @@ private static Tuple> GetLightmapsStruct(List re // renderer foreach (var renderer in renderers) { - if(renderer == null) + if (renderer == null) continue; var lightmapIndex = renderer.lightmapIndex; @@ -231,11 +231,11 @@ public static LightMapInformation GenerateLightMappingData(List re public void Destroy() { - if(colors != null) + if (colors != null) Object.Destroy(colors); - if(directions != null) + if (directions != null) Object.Destroy(directions); - if(shadowMasks != null) + if (shadowMasks != null) Object.Destroy(shadowMasks); } } diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/RenderBRG.cs b/com.unity.render-pipelines.core/Runtime/BatchRenderer/RenderBRG.cs index 9f8f75b58a7..25755447d75 100644 --- a/com.unity.render-pipelines.core/Runtime/BatchRenderer/RenderBRG.cs +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/RenderBRG.cs @@ -124,7 +124,7 @@ static float4 GetSHC(SphericalHarmonicsL2 sh) return new float4(sh[0, 8], sh[1, 8], sh[2, 8], 1); } } - + unsafe class SceneBRG { private BatchRendererGroup m_BatchRendererGroup; @@ -143,9 +143,13 @@ unsafe class SceneBRG private NativeArray m_instanceIndices; private NativeArray m_drawIndices; private NativeArray m_renderers; + private int m_transformVec4InstanceBufferOffsetL2W; + private int m_transformVec4InstanceBufferOffsetW2L; private LightMaps m_Lightmaps; + BRGTransformUpdater m_BRGTransformUpdater = new BRGTransformUpdater(); + private List m_AddedRenderers; public static T* Malloc(int count) where T : unmanaged @@ -161,7 +165,8 @@ static MetadataValue CreateMetadataValue(int nameID, int gpuAddress, bool isOver const uint kIsOverriddenBit = 0x80000000; return new MetadataValue { - NameID = nameID, Value = (uint)gpuAddress | (isOverridden ? kIsOverriddenBit : 0), + NameID = nameID, + Value = (uint)gpuAddress | (isOverridden ? kIsOverriddenBit : 0), }; } @@ -240,7 +245,7 @@ public void Execute() var rendererIndex = instanceIndices[i]; uint visibleMask = (uint)((rendererVisibility[rendererIndex / 8] >> ((rendererIndex % 8) * 8)) & 0xfful); - if (visibleMask != 0) + if (visibleMask != 0) { // Emit extra DrawCommand if visible mask changes // TODO: Sort draws in batch first to minimize the number of DrawCommands @@ -251,7 +256,7 @@ public void Execute() { draws.drawCommands[outBatch] = new BatchDrawCommand { - visibleOffset = (uint)batchStartIndex, + visibleOffset = (uint)batchStartIndex, visibleCount = (uint)visibleCount, batchID = batchID, materialID = drawBatches[remappedIndex].key.material, @@ -462,6 +467,7 @@ public JobHandle OnPerformCulling(BatchRendererGroup rendererGroup, BatchCulling public void Initialize(List renderers) { m_BatchRendererGroup = new BatchRendererGroup(this.OnPerformCulling, IntPtr.Zero); + m_BRGTransformUpdater.Initialize(); // Create a batch... #if DEBUG_LOG_SCENE @@ -511,6 +517,9 @@ public void Initialize(List renderers) var localToWorldOffset = lightMapScaleOffset + m_renderers.Length; var worldToLocalOffset = localToWorldOffset + m_renderers.Length * 3; + m_transformVec4InstanceBufferOffsetL2W = localToWorldOffset; //this will be used by the transform updated later. + m_transformVec4InstanceBufferOffsetW2L = worldToLocalOffset; //this will be used by the transform updated later. + m_instances = new NativeList(1024, Allocator.Persistent); var lightmappingData = LightMaps.GenerateLightMappingData(renderers); @@ -526,7 +535,7 @@ public void Initialize(List renderers) m_renderers[i] = new DrawRenderer { - bounds = new AABB {Center = new float3(0, 0, 0), Extents = new float3(0, 0, 0)} + bounds = new AABB { Center = new float3(0, 0, 0), Extents = new float3(0, 0, 0) } }; var meshFilter = renderer.gameObject.GetComponent(); @@ -564,6 +573,8 @@ public void Initialize(List renderers) 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); + lpq.CalculateInterpolatedLightAndOcclusionProbe(rendererTransform.position, -1, out var lp, out var probeOcclusion); @@ -580,7 +591,7 @@ public void Initialize(List renderers) // Renderer bounds var transformedBounds = AABB.Transform(m, meshFilter.sharedMesh.bounds.ToAABB()); - m_renderers[i] = new DrawRenderer {bounds = transformedBounds}; + m_renderers[i] = new DrawRenderer { bounds = transformedBounds }; var mesh = m_BatchRendererGroup.RegisterMesh(meshFilter.sharedMesh); @@ -594,7 +605,7 @@ public void Initialize(List renderers) (renderer.staticShadowCaster ? RangeShadowFlags.StaticShadowCaster : 0) }; - var drawRange = new DrawRange {key = rangeKey, drawCount = 0, drawOffset = 0}; + var drawRange = new DrawRange { key = rangeKey, drawCount = 0, drawOffset = 0 }; int drawRangeIndex; if (m_rangeHash.TryGetValue(rangeKey, out drawRangeIndex)) @@ -636,9 +647,9 @@ public void Initialize(List renderers) range = rangeKey }; - var drawBatch = new DrawBatch {key = key, instanceCount = 0, instanceOffset = 0}; + var drawBatch = new DrawBatch { key = key, instanceCount = 0, instanceOffset = 0 }; - m_instances.Add(new DrawInstance {key = key, instanceIndex = i}); + m_instances.Add(new DrawInstance { key = key, instanceIndex = i }); int drawBatchIndex; if (m_batchHash.TryGetValue(key, out drawBatchIndex)) @@ -776,6 +787,16 @@ void Update() // https://docs.unity3d.com/ScriptReference/Jobs.TransformAccess.html } + public void StartTransformsUpdate() + { + m_BRGTransformUpdater.StartUpdateJobs(); + } + + public bool EndTransformsUpdate(CommandBuffer cmdBuffer) + { + return m_BRGTransformUpdater.EndUpdateJobs(cmdBuffer, m_transformVec4InstanceBufferOffsetL2W, m_transformVec4InstanceBufferOffsetW2L, m_GPUPersistentInstanceData); + } + public void Destroy() { if (m_initialized) @@ -783,6 +804,7 @@ public void Destroy() // NOTE: Don't need to remove batch or unregister BatchRendererGroup resources. BRG.Dispose takes care of that. m_BatchRendererGroup.Dispose(); m_GPUPersistentInstanceData.Dispose(); + m_BRGTransformUpdater.Dispose(); m_renderers.Dispose(); m_batchHash.Dispose(); @@ -807,9 +829,11 @@ public class RenderBRG : MonoBehaviour { private static bool s_QueryLoadedScenes = true; private Dictionary m_Scenes = new(); + private CommandBuffer m_gpuCmdBuffer; private void OnEnable() { + m_gpuCmdBuffer = new CommandBuffer(); SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.sceneUnloaded += OnSceneUnloaded; @@ -837,6 +861,8 @@ private void OnEnable() private void OnDisable() { + m_gpuCmdBuffer.Release(); + m_gpuCmdBuffer = null; SceneManager.sceneLoaded -= OnSceneLoaded; SceneManager.sceneUnloaded -= OnSceneUnloaded; @@ -855,9 +881,7 @@ private static void GetValidChildRenderers(GameObject root, List t { if (root == null || root.activeInHierarchy == false - || root.GetComponent() != null - || root.GetComponent() != null - || root.GetComponent() != null) + || root.GetComponent() != null) return; var mr = root.GetComponent(); @@ -893,6 +917,32 @@ private void OnSceneUnloaded(Scene scene) } } + private void Update() + { + m_gpuCmdBuffer.Clear(); + + foreach (var sceneBrg in m_Scenes) + { + if (sceneBrg.Value == null) + continue; + + sceneBrg.Value.StartTransformsUpdate(); + } + + int gpuCmds = 0; + foreach (var sceneBrg in m_Scenes) + { + if (sceneBrg.Value == null) + continue; + + if (sceneBrg.Value.EndTransformsUpdate(m_gpuCmdBuffer)) + ++gpuCmds; + } + + if (gpuCmds > 0) + Graphics.ExecuteCommandBuffer(m_gpuCmdBuffer); + } + private void OnDestroy() { foreach (var scene in m_Scenes) diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources.meta b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources.meta new file mode 100644 index 00000000000..8d92eb426a3 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc2c9850a91e6ee4e95edb1ab4ffbf3c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdateCS.compute b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdateCS.compute new file mode 100644 index 00000000000..6bd9e8a9a33 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdateCS.compute @@ -0,0 +1,31 @@ +#include "BRGTransformUpdaterDefs.cs.hlsl" + +#pragma kernel ScatterUpdateMain + +int _TransformUpdateQueueCount; +int _TransformUpdateOutputL2WVec4Offset; +int _TransformUpdateOutputW2LVec4Offset; + +StructuredBuffer _TransformUpdateDataQueue; +ByteAddressBuffer _TransformUpdateIndexQueue; +RWByteAddressBuffer _OutputTransformBuffer; + +[numthreads(64, 1, 1)] +void ScatterUpdateMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + if (dispatchThreadID.x >= (uint)_TransformUpdateQueueCount) + return; + + uint outputIndex = _TransformUpdateIndexQueue.Load(dispatchThreadID.x << 2); + BRGGpuTransformUpdate updatePacket = _TransformUpdateDataQueue[dispatchThreadID.x]; + + uint byteOutputL2WOffset = _TransformUpdateOutputL2WVec4Offset * 16 + outputIndex * 4 * 4 * 3; + uint byteOutputW2LOffset = _TransformUpdateOutputW2LVec4Offset * 16 + outputIndex * 4 * 4 * 3; + + _OutputTransformBuffer.Store4(byteOutputL2WOffset + 0, asuint(updatePacket.localToWorld0)); + _OutputTransformBuffer.Store4(byteOutputL2WOffset + 16, asuint(updatePacket.localToWorld1)); + _OutputTransformBuffer.Store4(byteOutputL2WOffset + 32, asuint(updatePacket.localToWorld2)); + _OutputTransformBuffer.Store4(byteOutputW2LOffset + 0, asuint(updatePacket.worldToLocal0)); + _OutputTransformBuffer.Store4(byteOutputW2LOffset + 16, asuint(updatePacket.worldToLocal1)); + _OutputTransformBuffer.Store4(byteOutputW2LOffset + 32, asuint(updatePacket.worldToLocal2)); +} diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdateCS.compute.meta b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdateCS.compute.meta new file mode 100644 index 00000000000..1fb2bece277 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdateCS.compute.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8c64c8c8fecfee54ba77a70ce97bdd11 +ComputeShaderImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs new file mode 100644 index 00000000000..2add40210ab --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs @@ -0,0 +1,16 @@ +using Unity.Mathematics; + +namespace UnityEngine.Rendering +{ + [GenerateHLSL] + internal struct BRGGpuTransformUpdate + { + public float4 localToWorld0; + public float4 localToWorld1; + public float4 localToWorld2; + + public float4 worldToLocal0; + public float4 worldToLocal1; + public float4 worldToLocal2; + } +} diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.hlsl b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.hlsl new file mode 100644 index 00000000000..84dacd9241d --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.hlsl @@ -0,0 +1,47 @@ +// +// This file was automatically generated. Please don't edit by hand. Execute Editor command [ Edit > Rendering > Generate Shader Includes ] instead +// + +#ifndef BRGTRANSFORMUPDATERDEFS_CS_HLSL +#define BRGTRANSFORMUPDATERDEFS_CS_HLSL +// Generated from UnityEngine.Rendering.BRGGpuTransformUpdate +// PackingRules = Exact +struct BRGGpuTransformUpdate +{ + float4 localToWorld0; // x: x y: y z: z w: w + float4 localToWorld1; // x: x y: y z: z w: w + float4 localToWorld2; // x: x y: y z: z w: w + float4 worldToLocal0; // x: x y: y z: z w: w + float4 worldToLocal1; // x: x y: y z: z w: w + float4 worldToLocal2; // x: x y: y z: z w: w +}; + +// +// Accessors for UnityEngine.Rendering.BRGGpuTransformUpdate +// +float4 GetLocalToWorld0(BRGGpuTransformUpdate value) +{ + return value.localToWorld0; +} +float4 GetLocalToWorld1(BRGGpuTransformUpdate value) +{ + return value.localToWorld1; +} +float4 GetLocalToWorld2(BRGGpuTransformUpdate value) +{ + return value.localToWorld2; +} +float4 GetWorldToLocal0(BRGGpuTransformUpdate value) +{ + return value.worldToLocal0; +} +float4 GetWorldToLocal1(BRGGpuTransformUpdate value) +{ + return value.worldToLocal1; +} +float4 GetWorldToLocal2(BRGGpuTransformUpdate value) +{ + return value.worldToLocal2; +} + +#endif diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.hlsl.meta b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.hlsl.meta new file mode 100644 index 00000000000..77ac9f8aa92 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: aad4fdbbfe30ff7459d6c6f05e7eaa65 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.meta b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.meta new file mode 100644 index 00000000000..4a268c100b1 --- /dev/null +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/Resources/BRGTransformUpdaterDefs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 39c61558833551e4baa6edfa795338be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Runtime/BatchRenderer/ToggleBRG.cs b/com.unity.render-pipelines.core/Runtime/BatchRenderer/ToggleBRG.cs index 0072f2d5f12..4a74bc3fe5c 100644 --- a/com.unity.render-pipelines.core/Runtime/BatchRenderer/ToggleBRG.cs +++ b/com.unity.render-pipelines.core/Runtime/BatchRenderer/ToggleBRG.cs @@ -2,25 +2,25 @@ namespace UnityEngine.Rendering { public class ToggleBRG : MonoBehaviour { - void OnGUI() - { - var brg = GetComponent(); - if (brg == null) - return; + void OnGUI() + { + var brg = GetComponent(); + if (brg == null) + return; - var state = brg.enabled ? "enabled" : "disabled"; - if (GUILayout.Button($"Toggle BRG (F). Current State: {state}")) - brg.enabled = !brg.enabled; - } + var state = brg.enabled ? "enabled" : "disabled"; + if (GUILayout.Button($"Toggle BRG (F). Current State: {state}")) + brg.enabled = !brg.enabled; + } - private void Update() - { - var brg = GetComponent(); - if (brg == null) - return; + private void Update() + { + var brg = GetComponent(); + if (brg == null) + return; - if (Input.GetKeyDown(KeyCode.F)) - brg.enabled = !brg.enabled; - } + if (Input.GetKeyDown(KeyCode.F)) + brg.enabled = !brg.enabled; + } } }