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.
 
 
 
 

141 lines
5.5 KiB

using System.Collections.Generic;
using System.Diagnostics;
namespace UnityEngine.Rendering.UnifiedRayTracing
{
internal sealed class HardwareRayTracingAccelStruct : IRayTracingAccelStruct
{
public RayTracingAccelerationStructure accelStruct { get; }
readonly RayTracingAccelerationStructureBuildFlags m_BuildFlags;
// keep a reference to Meshes because RayTracingAccelerationStructure impl is to automatically
// remove instances when the mesh is disposed
readonly Dictionary<int, Mesh> m_Meshes = new();
readonly ReferenceCounter m_Counter;
#if UNITY_ASSERTIONS
readonly HashSet<int> m_InstanceHandles = new();
#endif
internal HardwareRayTracingAccelStruct(AccelerationStructureOptions options, ReferenceCounter counter)
{
m_BuildFlags = (RayTracingAccelerationStructureBuildFlags)options.buildFlags;
RayTracingAccelerationStructure.Settings settings = new RayTracingAccelerationStructure.Settings();
settings.rayTracingModeMask = RayTracingAccelerationStructure.RayTracingModeMask.Everything;
settings.managementMode = RayTracingAccelerationStructure.ManagementMode.Manual;
settings.enableCompaction = false;
settings.layerMask = 255;
settings.buildFlagsStaticGeometries = m_BuildFlags;
accelStruct = new RayTracingAccelerationStructure(settings);
m_Counter = counter;
m_Counter.Inc();
}
public void Dispose()
{
m_Counter.Dec();
accelStruct?.Dispose();
}
public int AddInstance(MeshInstanceDesc meshInstance)
{
Utils.CheckArgIsNotNull(meshInstance.mesh, "meshInstance.mesh");
Utils.CheckArg(meshInstance.mesh.HasVertexAttribute(VertexAttribute.Position), "Cant use a mesh buffer that has no positions.");
Utils.CheckArgRange(meshInstance.subMeshIndex, 0, meshInstance.mesh.subMeshCount, "meshInstance.subMeshIndex");
var instanceDesc = new RayTracingMeshInstanceConfig(meshInstance.mesh, (uint)meshInstance.subMeshIndex, null);
instanceDesc.mask = meshInstance.mask;
instanceDesc.enableTriangleCulling = meshInstance.enableTriangleCulling;
instanceDesc.frontTriangleCounterClockwise = meshInstance.frontTriangleCounterClockwise;
instanceDesc.subMeshFlags = meshInstance.opaqueGeometry ? RayTracingSubMeshFlags.Enabled | RayTracingSubMeshFlags.ClosestHitOnly : RayTracingSubMeshFlags.Enabled | RayTracingSubMeshFlags.UniqueAnyHitCalls;
int instanceHandle = accelStruct.AddInstance(instanceDesc, meshInstance.localToWorldMatrix, null, meshInstance.instanceID);
// If instanceID is auto assigned, set it in the same way as ComputeRaytracingAccelStruct
if (meshInstance.instanceID == 0xFFFFFFFF)
accelStruct.UpdateInstanceID(instanceHandle, (uint)instanceHandle);
m_Meshes.Add(instanceHandle, meshInstance.mesh);
#if UNITY_ASSERTIONS
m_InstanceHandles.Add(instanceHandle);
#endif
return instanceHandle;
}
public void RemoveInstance(int instanceHandle)
{
#if UNITY_ASSERTIONS
if (!m_InstanceHandles.Remove(instanceHandle))
throw new System.ArgumentException($"accel struct does not contain instanceHandle {instanceHandle}", "instanceHandle");
#endif
m_Meshes.Remove(instanceHandle);
accelStruct.RemoveInstance(instanceHandle);
}
public void ClearInstances()
{
#if UNITY_ASSERTIONS
m_InstanceHandles.Clear();
#endif
m_Meshes.Clear();
accelStruct.ClearInstances();
}
public void UpdateInstanceTransform(int instanceHandle, Matrix4x4 localToWorldMatrix)
{
CheckInstanceHandleIsValid(instanceHandle);
accelStruct.UpdateInstanceTransform(instanceHandle, localToWorldMatrix);
}
public void UpdateInstanceID(int instanceHandle, uint instanceID)
{
CheckInstanceHandleIsValid(instanceHandle);
accelStruct.UpdateInstanceID(instanceHandle, instanceID);
}
public void UpdateInstanceMask(int instanceHandle, uint mask)
{
CheckInstanceHandleIsValid(instanceHandle);
accelStruct.UpdateInstanceMask(instanceHandle, mask);
}
public void Build(CommandBuffer cmd, GraphicsBuffer scratchBuffer)
{
Utils.CheckArgIsNotNull(cmd, nameof(cmd));
var buildSettings = new RayTracingAccelerationStructure.BuildSettings()
{
buildFlags = m_BuildFlags,
relativeOrigin = Vector3.zero
};
cmd.BuildRayTracingAccelerationStructure(accelStruct, buildSettings);
}
public ulong GetBuildScratchBufferRequiredSizeInBytes()
{
// Unity's Hardware impl (RayTracingAccelerationStructure) does not require any scratchbuffers.
// They are directly handled internally by the GfxDevice.
return 0;
}
[Conditional("UNITY_ASSERTIONS")]
void CheckInstanceHandleIsValid(int instanceHandle)
{
#if UNITY_ASSERTIONS
if (!m_InstanceHandles.Contains(instanceHandle))
throw new System.ArgumentException($"accel struct does not contain instanceHandle {instanceHandle}", "instanceHandle");
#endif
}
}
}