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
173 changes: 159 additions & 14 deletions com.unity.render-pipelines.core/Runtime/BatchRenderer/RenderBRG.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine.Assertions;
using UnityEngine.SceneManagement;

namespace UnityEngine.Rendering
Expand Down Expand Up @@ -125,6 +126,13 @@ static float4 GetSHC(SphericalHarmonicsL2 sh)
}
}

struct DeferredMaterialInstance
{
public int instanceIndex;
public int meshHashCode;
public GeometryPoolHandle geoPoolHandle;
}

unsafe class SceneBRG
{
private BatchRendererGroup m_BatchRendererGroup;
Expand All @@ -145,10 +153,13 @@ unsafe class SceneBRG
private NativeArray<DrawRenderer> m_renderers;
private int m_transformVec4InstanceBufferOffsetL2W;
private int m_transformVec4InstanceBufferOffsetW2L;
private NativeList<DeferredMaterialInstance> m_deferredMaterialInstances;

private LightMaps m_Lightmaps;

BRGTransformUpdater m_BRGTransformUpdater = new BRGTransformUpdater();
private BRGTransformUpdater m_BRGTransformUpdater = new BRGTransformUpdater();
private GeometryPool m_GlobalGeoPool = null;


private List<MeshRenderer> m_AddedRenderers;

Expand Down Expand Up @@ -463,8 +474,90 @@ public JobHandle OnPerformCulling(BatchRendererGroup rendererGroup, BatchCulling
return jobHandleOutput;
}

private void ProcessUsedMeshAndMaterialDataFromGameObjects(
RenderPipelineAsset pipelineAsset,
int instanceIndex,
MeshRenderer renderer,
MeshFilter meshFilter,
Dictionary<Tuple<Renderer, int>, Material> rendererMaterialInfos,
int deferredMaterialBufferOffset,
NativeArray<Vector4> deferredMaterialBuffer,
ref Mesh outMesh,
List<int> outSubmeshIndices,
List<Material> outMaterials)
{
outSubmeshIndices.Clear();
outMaterials.Clear();

var sharedMaterials = new List<Material>();
var startSubMesh = renderer.subMeshStartIndex;
renderer.GetSharedMaterials(sharedMaterials);
Material overrideMaterial = null;
int overrideCounts = 0;
for (int matIndex = 0; matIndex < sharedMaterials.Count; ++matIndex)
{
Material matToUse;
if (!rendererMaterialInfos.TryGetValue(new Tuple<Renderer, int>(renderer, matIndex), out matToUse))
matToUse = sharedMaterials[matIndex];

int targetSubmeshIndex = (int)(startSubMesh + matIndex);
if (pipelineAsset != null)
{
RenderPipelineAsset.VisibilityMaterialRendererInfo visMaterialInfo = pipelineAsset.GetVisibilityMaterialInfoForRenderer(new RenderPipelineAsset.GetVisibilityMaterialInfoForRendererArgs()
{
renderer = renderer,
submeshIndex = targetSubmeshIndex,
material = matToUse
});

if (visMaterialInfo.supportsVisibility && visMaterialInfo.materialOverride != null)
{
Assert.IsTrue(
overrideMaterial == null || overrideMaterial == visMaterialInfo.materialOverride,
"RenderBRG only supports one and only 1 override for an entire renderer.");
++overrideCounts;
overrideMaterial = visMaterialInfo.materialOverride;
}
}

outSubmeshIndices.Add(targetSubmeshIndex);
outMaterials.Add(matToUse);
}

outMesh = meshFilter.sharedMesh;

//Special case, if the renderer qualifies for deferred materials, go for it!
//TODO: for now we just handle 1 case, if the entire renderer can be deferred material.
if (overrideMaterial != null && overrideCounts == outMaterials.Count && m_GlobalGeoPool != null)
{
m_GlobalGeoPool.Register(outMesh, out GeometryPoolHandle geoPoolHandle);
if (!geoPoolHandle.valid)
return;

if (!m_deferredMaterialInstances.IsCreated)
m_deferredMaterialInstances = new NativeList<DeferredMaterialInstance>(1024, Allocator.Persistent);

m_deferredMaterialInstances.Add(new DeferredMaterialInstance()
{
instanceIndex = instanceIndex,
meshHashCode = outMesh.GetHashCode(),
geoPoolHandle = geoPoolHandle
});

deferredMaterialBuffer[deferredMaterialBufferOffset + instanceIndex] = new Vector4((float)geoPoolHandle.index, 0.0f, 0.0f, 0.0f);

//We succeeded! lets override the mesh / submesh index and material.
outSubmeshIndices.Clear();
outMaterials.Clear();
outMaterials.Add(overrideMaterial);
outSubmeshIndices.Add(geoPoolHandle.index);
outMesh = m_GlobalGeoPool.globalMesh;

}
}

// Start is called before the first frame update
public void Initialize(List<MeshRenderer> renderers)
public void Initialize(List<MeshRenderer> renderers, GeometryPool geometryPool)
{
m_BatchRendererGroup = new BatchRendererGroup(this.OnPerformCulling, IntPtr.Zero);
m_BRGTransformUpdater.Initialize();
Expand All @@ -480,6 +573,9 @@ public void Initialize(List<MeshRenderer> renderers)
m_drawBatches = new NativeList<DrawBatch>(Allocator.Persistent);
m_drawRanges = new NativeList<DrawRange>(Allocator.Persistent);
m_AddedRenderers = new List<MeshRenderer>(renderers.Count);
m_GlobalGeoPool = geometryPool;

RenderPipelineAsset renderPipelineAsset = GraphicsSettings.renderPipelineAsset;

// Fill the GPU-persistent scene data ComputeBuffer
int bigDataBufferVector4Count =
Expand All @@ -489,7 +585,9 @@ public void Initialize(List<MeshRenderer> renderers)
+ 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*/;
+ m_renderers.Length * 3 * 2 /*per renderer 4x3 matrix+inverse*/
+ 1 * m_renderers.Length; /*per renderer, vec4 with deferredMaterialData*/

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

// First 4xfloat4 of ComputeBuffer needed to be zero filled for default property fall back!
Expand All @@ -516,6 +614,7 @@ public void Initialize(List<MeshRenderer> renderers)
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;

m_transformVec4InstanceBufferOffsetL2W = localToWorldOffset; //this will be used by the transform updated later.
m_transformVec4InstanceBufferOffsetW2L = worldToLocalOffset; //this will be used by the transform updated later.
Expand Down Expand Up @@ -593,7 +692,15 @@ public void Initialize(List<MeshRenderer> renderers)
var transformedBounds = AABB.Transform(m, meshFilter.sharedMesh.bounds.ToAABB());
m_renderers[i] = new DrawRenderer { bounds = transformedBounds };

var mesh = m_BatchRendererGroup.RegisterMesh(meshFilter.sharedMesh);
Mesh usedMesh = null;
var usedSubmeshIndices = new List<int>();
var usedMaterials = new List<Material>();
ProcessUsedMeshAndMaterialDataFromGameObjects(
renderPipelineAsset, i, renderer, meshFilter, rendererMaterialInfos,
deferredMaterialDataOffset, vectorBuffer,
ref usedMesh, usedSubmeshIndices, usedMaterials);

var mesh = m_BatchRendererGroup.RegisterMesh(usedMesh);

// Different renderer settings? -> new draw range
var rangeKey = new RangeKey
Expand All @@ -620,14 +727,9 @@ public void Initialize(List<MeshRenderer> renderers)
}

// Sub-meshes...
var sharedMaterials = new List<Material>();
renderer.GetSharedMaterials(sharedMaterials);
var startSubMesh = renderer.subMeshStartIndex;
for (int matIndex = 0; matIndex < sharedMaterials.Count; matIndex++)
for (int matIndex = 0; matIndex < usedMaterials.Count; matIndex++)
{
Material matToUse;
if (!rendererMaterialInfos.TryGetValue(new Tuple<Renderer, int>(renderer, matIndex), out matToUse))
matToUse = sharedMaterials[matIndex];
Material matToUse = usedMaterials[matIndex];

var material = m_BatchRendererGroup.RegisterMaterial(matToUse);

Expand All @@ -642,7 +744,7 @@ public void Initialize(List<MeshRenderer> renderers)
{
material = material,
meshID = mesh,
submeshIndex = (uint)(matIndex + startSubMesh),
submeshIndex = (uint)usedSubmeshIndices[matIndex],
flags = flags,
range = rangeKey
};
Expand Down Expand Up @@ -671,6 +773,9 @@ public void Initialize(List<MeshRenderer> renderers)
}
}

if (m_GlobalGeoPool != null)
m_GlobalGeoPool.SendGpuCommands();

m_GPUPersistentInstanceData =
new GraphicsBuffer(GraphicsBuffer.Target.Raw, (int)bigDataBufferVector4Count * 16 / 4, 4);
m_GPUPersistentInstanceData.SetData(vectorBuffer);
Expand Down Expand Up @@ -758,8 +863,9 @@ public void Initialize(List<MeshRenderer> renderers)
int SHBgID = Shader.PropertyToID("unity_SHBg");
int SHBbID = Shader.PropertyToID("unity_SHBb");
int SHCID = Shader.PropertyToID("unity_SHC");
int deferredMaterialInstanceDataID = Shader.PropertyToID("_DeferredMaterialInstanceData");

var batchMetadata = new NativeArray<MetadataValue>(13, Allocator.Temp);
var batchMetadata = new NativeArray<MetadataValue>(14, Allocator.Temp);
batchMetadata[0] = CreateMetadataValue(objectToWorldID, localToWorldOffset * UnsafeUtility.SizeOf<Vector4>(), true);
batchMetadata[1] = CreateMetadataValue(worldToObjectID, worldToLocalOffset * UnsafeUtility.SizeOf<Vector4>(), true);
batchMetadata[2] = CreateMetadataValue(lightmapSTID, lightMapScaleOffset * UnsafeUtility.SizeOf<Vector4>(), true);
Expand All @@ -773,6 +879,7 @@ public void Initialize(List<MeshRenderer> renderers)
batchMetadata[10] = CreateMetadataValue(SHBgID, SHBgOffset * UnsafeUtility.SizeOf<Vector4>(), true);
batchMetadata[11] = CreateMetadataValue(SHBbID, SHBbOffset * UnsafeUtility.SizeOf<Vector4>(), true);
batchMetadata[12] = CreateMetadataValue(SHCID, SHCOffset * UnsafeUtility.SizeOf<Vector4>(), true);
batchMetadata[13] = CreateMetadataValue(deferredMaterialInstanceDataID, deferredMaterialDataOffset * UnsafeUtility.SizeOf<Vector4>(), true);

// Register batch
m_batchID = m_BatchRendererGroup.AddBatch(batchMetadata, m_GPUPersistentInstanceData.bufferHandle);
Expand Down Expand Up @@ -821,6 +928,16 @@ public void Destroy()
if (added != null)
added.forceRenderingOff = false;
}

if (m_deferredMaterialInstances.IsCreated)
{
foreach (var deferredInstance in m_deferredMaterialInstances)
{
m_GlobalGeoPool.UnregisterByMeshHashCode(deferredInstance.meshHashCode);
}
m_GlobalGeoPool.SendGpuCommands();
m_deferredMaterialInstances.Dispose();
}
}
}
}
Expand All @@ -831,8 +948,30 @@ public class RenderBRG : MonoBehaviour
private Dictionary<Scene, SceneBRG> m_Scenes = new();
private CommandBuffer m_gpuCmdBuffer;

public bool EnableDeferredMaterials = false;
private GeometryPool m_GlobalGeoPool;

public static GeometryPool FindGlobalGeometryPool()
{
RenderBRG[] brgers = Resources.FindObjectsOfTypeAll<RenderBRG>();
if (brgers == null)
return null;

foreach (var brg in brgers)
{
if (brg.m_GlobalGeoPool != null)
return brg.m_GlobalGeoPool;
}

return null;
}

private void OnEnable()
{
var globalGeoPool = FindGlobalGeometryPool();
if (EnableDeferredMaterials && globalGeoPool == null && m_GlobalGeoPool == null)
m_GlobalGeoPool = new GeometryPool(GeometryPoolDesc.NewDefault());

m_gpuCmdBuffer = new CommandBuffer();
SceneManager.sceneLoaded += OnSceneLoaded;
SceneManager.sceneUnloaded += OnSceneUnloaded;
Expand Down Expand Up @@ -909,7 +1048,7 @@ private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
Debug.Log("Loading scene: " + scene.name);
#endif
SceneBRG brg = new SceneBRG();
brg.Initialize(renderers);
brg.Initialize(renderers, RenderBRG.FindGlobalGeometryPool());
m_Scenes[scene] = brg;
}

Expand Down Expand Up @@ -955,6 +1094,12 @@ private void OnDestroy()
scene.Value?.Destroy();

m_Scenes.Clear();

if (m_GlobalGeoPool != null)
{
m_GlobalGeoPool.Dispose();
m_GlobalGeoPool = null;
}
}
}
}
Loading