using System;
using NUnit.Framework;
using UnityEngine.TestTools;
namespace UnityEngine.Rendering.UnifiedRayTracing.Tests
{
[TestFixture("Compute")]
[TestFixture("Hardware")]
internal class InvalidInputsTests
{
readonly RayTracingBackend m_Backend;
RayTracingContext m_Context;
RayTracingResources m_Resources;
IRayTracingAccelStruct m_AccelStruct;
IRayTracingShader m_Shader;
[Flags]
enum MeshField { Positions=1, Normals=2, Uvs=4, Indices=8 }
static Mesh CreateSingleTriangleMesh(MeshField fields)
{
Mesh mesh = new Mesh();
if ((fields & MeshField.Positions) != 0)
{
Vector3[] vertices = new Vector3[]
{
new Vector3(1.0f, 0.0f, 0),
new Vector3(0.0f, 0.0f, 0),
new Vector3(0.0f, 0.0f, 0)
};
mesh.vertices = vertices;
}
if ((fields & MeshField.Normals) != 0)
{
Vector3[] normals = new Vector3[]
{
-Vector3.forward,
-Vector3.forward,
-Vector3.forward
};
mesh.normals = normals;
}
if ((fields & MeshField.Uvs) != 0)
{
Vector2[] uv = new Vector2[]
{
new Vector2(0, 1),
new Vector2(1, 1),
new Vector2(0, 0)
};
mesh.uv = uv;
}
if ((fields & MeshField.Indices) != 0)
{
int[] tris = new int[3]
{
0, 2, 1
};
mesh.triangles = tris;
}
return mesh;
}
public InvalidInputsTests(string backendAsString)
{
m_Backend = Enum.Parse<RayTracingBackend>(backendAsString);
}
[SetUp]
public void SetUp()
{
if (!SystemInfo.supportsRayTracing && m_Backend == RayTracingBackend.Hardware)
Assert.Ignore("Cannot run test on this Graphics API. Hardware RayTracing is not supported");
if (!SystemInfo.supportsComputeShaders && m_Backend == RayTracingBackend.Compute)
Assert.Ignore("Cannot run test on this Graphics API. Compute shaders are not supported");
m_Resources = new RayTracingResources();
m_Resources.Load();
m_Context = new RayTracingContext(m_Backend, m_Resources);
m_AccelStruct = m_Context.CreateAccelerationStructure(new AccelerationStructureOptions() { useCPUBuild = false });
m_Shader = m_Context.LoadRayTracingShader("Packages/com.unity.render-pipelines.core/Tests/Editor/UnifiedRayTracing/TraceRays.urtshader");
}
[TearDown]
public void TearDown()
{
m_AccelStruct?.Dispose();
m_Context?.Dispose();
}
[Test]
public void AccelStruct_AddInstance_ThrowOnNullMesh()
{
var instanceDesc = new MeshInstanceDesc(null);
Assert.Throws<ArgumentNullException>(() => m_AccelStruct.AddInstance(instanceDesc));
}
[Test]
public void AccelStruct_AddInstance_ThrowOnMeshWithNoPositions()
{
var mesh = new Mesh();
var instanceDesc = new MeshInstanceDesc(mesh);
Assert.Throws<ArgumentException>(() => m_AccelStruct.AddInstance(instanceDesc));
}
[Test]
public void AccelStruct_AddInstance_ThrowOnInvalidSubmeshIndex()
{
var mesh = CreateSingleTriangleMesh(MeshField.Positions | MeshField.Indices | MeshField.Normals | MeshField.Uvs);
var instanceDesc = new MeshInstanceDesc(mesh);
instanceDesc.subMeshIndex = -1;
Assert.Throws<ArgumentOutOfRangeException>(() => m_AccelStruct.AddInstance(instanceDesc));
}
[Test]
public void AccelStruct_AddInstance_ThrowOnInvalidInstanceHandle()
{
var mesh = CreateSingleTriangleMesh(MeshField.Positions | MeshField.Indices | MeshField.Normals | MeshField.Uvs);
var instanceDesc = new MeshInstanceDesc(mesh);
var handle = m_AccelStruct.AddInstance(instanceDesc);
Assert.Throws<ArgumentException>(() => m_AccelStruct.RemoveInstance(handle + 1));
m_AccelStruct.ClearInstances();
Assert.Throws<ArgumentException>(() => m_AccelStruct.RemoveInstance(handle));
}
[Test]
public void RayTracingShader_SetFloatParam_ThrowOnNullCmdBuffer()
{
Assert.Throws<ArgumentNullException>(() => m_Shader.SetFloatParam(null, 0, 1.0f));
}
[Test]
public void RayTracingShader_Dispatch_ThrowOnSmallScratchBuffer()
{
if (m_Backend == RayTracingBackend.Hardware)
{
Assert.Ignore("scratch buffer is lawfully null with hardware backend");
return;
}
using GraphicsBuffer scratch = new GraphicsBuffer(GraphicsBuffer.Target.Structured, 10, 4);
using CommandBuffer cmd = new CommandBuffer();
var except = Assert.Throws<ArgumentException>(() => m_Shader.Dispatch(cmd, scratch, 20, 20, 20));
Assert.That(except.Message, Does.Contain("scratch"));
}
[Test]
public void RayTracingShader_Dispatch_ThrowOnScratchBufferWithInvalidTarget()
{
if (m_Backend == RayTracingBackend.Hardware)
{
Assert.Ignore("scratch buffer is lawfully null with hardware backend");
return;
}
using GraphicsBuffer scratch = new GraphicsBuffer(GraphicsBuffer.Target.Raw, 20*20*20*100, 4);
using CommandBuffer cmd = new CommandBuffer();
var except = Assert.Throws<ArgumentException>(() => m_Shader.Dispatch(cmd, scratch, 20, 20, 20));
Assert.That(except.Message, Does.Contain("target"));
}
}
}