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.
 
 
 
 
 

208 lines
7.5 KiB

using System;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Assertions;
using UnityEngine.Rendering;
using Unity.Mathematics;
using System.Collections.Generic;
namespace UnityEngine.Rendering.Tests
{
internal struct GPUDrivenTestHelper
{
static public uint4 UnpackUintTo4x8Bit(uint val)
{
return new uint4(val & 0xFF, (val >> 8) & 0xFF, (val >> 16) & 0xFF, (val >> 24) & 0xFF);
}
}
internal struct MeshTestData : IDisposable
{
public Mesh cube;
public Mesh sphere;
public Mesh capsule;
public Mesh cube16bit;
public Mesh capsule16bit;
public Mesh mergedCubeSphere;
public Mesh mergedSphereCube;
public void Initialize()
{
// SetupGeometryPoolTests
cube = GameObject.CreatePrimitive(PrimitiveType.Cube).GetComponent<MeshFilter>().sharedMesh;
cube.name = "Cube";
sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere).GetComponent<MeshFilter>().sharedMesh;
capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule).GetComponent<MeshFilter>().sharedMesh;
cube16bit = Create16BitIndexMesh(cube);
cube16bit.name = "Cube16bit";
capsule16bit = Create16BitIndexMesh(capsule);
capsule16bit.name = "Capsule16bit";
mergedCubeSphere = MergeMeshes(cube, sphere);
mergedCubeSphere.name = "MergedCubeSphere";
mergedSphereCube = MergeMeshes(sphere, cube);
mergedSphereCube.name = "MergedSphereCube";
}
public static Mesh Create16BitIndexMesh(Mesh input)
{
Mesh newMesh = new Mesh();
newMesh.vertices = new Vector3[input.vertexCount];
System.Array.Copy(input.vertices, newMesh.vertices, input.vertexCount);
newMesh.uv = new Vector2[input.vertexCount];
System.Array.Copy(input.uv, newMesh.uv, input.vertexCount);
newMesh.normals = new Vector3[input.vertexCount];
System.Array.Copy(input.normals, newMesh.normals, input.vertexCount);
newMesh.vertexBufferTarget = GraphicsBuffer.Target.Raw;
newMesh.indexBufferTarget = GraphicsBuffer.Target.Raw;
newMesh.subMeshCount = input.subMeshCount;
int indexCounts = 0;
for (int i = 0; i < input.subMeshCount; ++i)
indexCounts += (int)input.GetIndexCount(i);
newMesh.SetIndexBufferParams(indexCounts, IndexFormat.UInt16);
for (int i = 0; i < input.subMeshCount; ++i)
{
newMesh.SetSubMesh(i, input.GetSubMesh(i), MeshUpdateFlags.DontValidateIndices | MeshUpdateFlags.DontNotifyMeshUsers | MeshUpdateFlags.DontRecalculateBounds);
newMesh.SetIndices(input.GetIndices(i), MeshTopology.Triangles, i);
}
newMesh.UploadMeshData(false);
return newMesh;
}
public static Mesh MergeMeshes(Mesh a, Mesh b)
{
Mesh newMesh = new Mesh();
CombineInstance[] c = new CombineInstance[2];
var ca = new CombineInstance();
ca.transform = Matrix4x4.identity;
ca.subMeshIndex = 0;
ca.mesh = a;
var cb = new CombineInstance();
cb.transform = Matrix4x4.identity;
cb.subMeshIndex = 0;
cb.mesh = b;
c[0] = ca;
c[1] = cb;
newMesh.CombineMeshes(c, false);
newMesh.UploadMeshData(false);
return newMesh;
}
public void Dispose()
{
cube = null;
sphere = null;
capsule = null;
cube16bit = null;
capsule16bit = null;
mergedCubeSphere = null;
mergedSphereCube = null;
}
}
//Helper class containing a snapshot of the GPU big instance buffer data
internal struct InstanceDataBufferCPUReadbackData : IDisposable
{
public NativeArray<uint> data;
GPUInstanceDataBuffer m_InstanceDataBuffer;
public bool Load(GPUInstanceDataBuffer instanceDataBuffer)
{
int errorCount = 0;
m_InstanceDataBuffer = instanceDataBuffer;
var cmdBuffer = new CommandBuffer();
int uintSize = UnsafeUtility.SizeOf<uint>();
var localData = new NativeArray<uint>(instanceDataBuffer.byteSize / uintSize, Allocator.Persistent);
cmdBuffer.RequestAsyncReadback(instanceDataBuffer.gpuBuffer, (AsyncGPUReadbackRequest req) =>
{
if (req.done)
localData.CopyFrom(req.GetData<uint>());
else ++errorCount;
});
cmdBuffer.WaitAllAsyncReadbackRequests();
Graphics.ExecuteCommandBuffer(cmdBuffer);
cmdBuffer.Release();
data = localData;
if (errorCount != 0)
Debug.LogError("GPU Readback fail: Instance buffer data. Abandoning test.");
return errorCount == 0;
}
public T LoadData<T>(InstanceHandle instance, int propertyID) where T : unmanaged
{
return LoadData<T>(m_InstanceDataBuffer.CPUInstanceToGPUInstance(instance), propertyID);
}
public T LoadData<T>(GPUInstanceIndex gpuInstanceIndex, int propertyID) where T : unmanaged
{
int uintSize = UnsafeUtility.SizeOf<uint>();
int propertyIndex = m_InstanceDataBuffer.GetPropertyIndex(propertyID);
Assert.IsTrue(m_InstanceDataBuffer.descriptions[propertyIndex].isPerInstance);
int gpuBaseAddress = m_InstanceDataBuffer.gpuBufferComponentAddress[propertyIndex];
int indexInArray = (gpuBaseAddress + m_InstanceDataBuffer.descriptions[propertyIndex].byteSize * gpuInstanceIndex.index) / uintSize;
unsafe
{
uint* dataPtr = (uint*)data.GetUnsafePtr<uint>() + indexInArray;
T result = *(T*)(dataPtr);
return result;
}
}
public void Dispose()
{
data.Dispose();
}
}
internal class RenderPassTest : RenderPipelineAsset<RenderPassTestCullInstance>
{
public delegate void TestDelegate(ScriptableRenderContext ctx, Camera[] cameras);
protected override RenderPipeline CreatePipeline()
{
return new RenderPassTestCullInstance(this);
}
}
internal class RenderPassTestCullInstance : RenderPipeline
{
RenderPassTest m_Owner;
public RenderPassTestCullInstance(RenderPassTest owner)
{
m_Owner = owner;
}
protected override void Render(ScriptableRenderContext renderContext, Camera[] cameras)
{
foreach (var camera in cameras)
{
if (!camera.enabled)
continue;
ScriptableCullingParameters cullingParams;
camera.TryGetCullingParameters(out cullingParams);
renderContext.Cull(ref cullingParams);
}
renderContext.Submit();
}
}
[SupportedOnRenderPipeline(typeof(RenderPassTest))]
[System.ComponentModel.DisplayName("RenderPass")]
internal class RenderPassGlobalSettings : RenderPipelineGlobalSettings<RenderPassGlobalSettings, RenderPassTestCullInstance>
{
[SerializeField] RenderPipelineGraphicsSettingsContainer m_Settings = new();
protected override List<IRenderPipelineGraphicsSettings> settingsList => m_Settings.settingsList;
}
}