217 lines
9.1 KiB
C#
217 lines
9.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.PathTracing.Core;
|
|
using UnityEngine.PathTracing.Integration;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.UnifiedRayTracing;
|
|
|
|
namespace UnityEngine.PathTracing.Lightmapping
|
|
{
|
|
internal class LightmapIntegrationResourceCache : IDisposable
|
|
{
|
|
private Dictionary<ulong, UVMesh> _meshToUVMesh = new();
|
|
private Dictionary<ulong, UVAccelerationStructure> _meshToUVAccelerationStructure = new();
|
|
private Dictionary<UVFallbackBufferKey, UVFallbackBuffer> _meshToUVFallbackBuffer = new();
|
|
|
|
private struct UVFallbackBufferKey : IEquatable<UVFallbackBufferKey>
|
|
{
|
|
int width;
|
|
int height;
|
|
ulong meshInstanceID;
|
|
|
|
public UVFallbackBufferKey(int width, int height, EntityId meshInstanceID)
|
|
{
|
|
this.width = width;
|
|
this.height = height;
|
|
this.meshInstanceID = Util.EntityIDToUlong(meshInstanceID);
|
|
}
|
|
|
|
public bool Equals(UVFallbackBufferKey other) =>
|
|
width == other.width && height == other.height && meshInstanceID == other.meshInstanceID;
|
|
public override bool Equals(object obj) => obj is UVFallbackBufferKey other && Equals(other);
|
|
public override int GetHashCode() => HashCode.Combine(width, height, meshInstanceID);
|
|
public static bool operator ==(UVFallbackBufferKey left, UVFallbackBufferKey right) => left.Equals(right);
|
|
public static bool operator !=(UVFallbackBufferKey left, UVFallbackBufferKey right) => !left.Equals(right);
|
|
}
|
|
|
|
public int UVMeshCount()
|
|
{
|
|
return _meshToUVMesh.Count;
|
|
}
|
|
|
|
public int UVAccelerationStructureCount()
|
|
{
|
|
return _meshToUVAccelerationStructure.Count;
|
|
}
|
|
|
|
public int UVFallbackBufferCount()
|
|
{
|
|
return _meshToUVFallbackBuffer.Count;
|
|
}
|
|
|
|
internal bool CacheIsHot(BakeInstance[] instances)
|
|
{
|
|
foreach (BakeInstance instance in instances)
|
|
{
|
|
// UVMesh
|
|
ulong uvMeshHash = Util.EntityIDToUlong(instance.Mesh.GetEntityId());
|
|
if (!_meshToUVMesh.TryGetValue(uvMeshHash, out UVMesh uvMesh))
|
|
return false;
|
|
|
|
// UVAccelerationStructure
|
|
ulong uvASHash = uvMeshHash;
|
|
if (!_meshToUVAccelerationStructure.TryGetValue(uvASHash, out UVAccelerationStructure uvAS))
|
|
return false;
|
|
|
|
// UVFallbackBuffer
|
|
var uvFBKey = new UVFallbackBufferKey(instance.TexelSize.x, instance.TexelSize.y, uvMesh.Mesh.GetEntityId());
|
|
if (!_meshToUVFallbackBuffer.TryGetValue(uvFBKey, out UVFallbackBuffer uvFB))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
internal bool AddResources(
|
|
BakeInstance[] instances,
|
|
RayTracingContext context,
|
|
CommandBuffer cmd,
|
|
UVFallbackBufferBuilder uvFallbackBufferBuilder)
|
|
{
|
|
foreach (BakeInstance instance in instances)
|
|
{
|
|
// UVMesh
|
|
ulong uvMeshHash = Util.EntityIDToUlong(instance.Mesh.GetEntityId());
|
|
if (!_meshToUVMesh.TryGetValue(uvMeshHash, out UVMesh uvMesh))
|
|
{
|
|
UVMesh newUVMesh = new();
|
|
if (!newUVMesh.Build(instance.Mesh))
|
|
{
|
|
newUVMesh?.Dispose();
|
|
return false;
|
|
}
|
|
_meshToUVMesh.Add(uvMeshHash, newUVMesh);
|
|
uvMesh = newUVMesh;
|
|
}
|
|
// UVAccelerationStructure
|
|
ulong uvASHash = Util.EntityIDToUlong(uvMesh.Mesh.GetEntityId());
|
|
if (!_meshToUVAccelerationStructure.TryGetValue(uvASHash, out UVAccelerationStructure uvAS))
|
|
{
|
|
cmd.BeginSample("Build UVAccelerationStructure");
|
|
UVAccelerationStructure newUVAS = new();
|
|
newUVAS.Build(cmd, context, uvMesh, BuildFlags.None);
|
|
_meshToUVAccelerationStructure.Add(uvASHash, newUVAS);
|
|
uvAS = newUVAS;
|
|
cmd.EndSample("Build UVAccelerationStructure");
|
|
}
|
|
// UVFallbackBuffer
|
|
var uvFBKey = new UVFallbackBufferKey(instance.TexelSize.x, instance.TexelSize.y, uvMesh.Mesh.GetEntityId());
|
|
if (!_meshToUVFallbackBuffer.TryGetValue(uvFBKey, out UVFallbackBuffer uvFB))
|
|
{
|
|
UVFallbackBuffer newUVFB = new();
|
|
if (!newUVFB.Build(
|
|
cmd,
|
|
uvFallbackBufferBuilder,
|
|
instance.TexelSize.x,
|
|
instance.TexelSize.y,
|
|
uvMesh))
|
|
{
|
|
newUVFB?.Dispose();
|
|
return false;
|
|
}
|
|
_meshToUVFallbackBuffer.Add(uvFBKey, newUVFB);
|
|
uvFB = newUVFB;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
internal void FreeResources(BakeInstance[] instancesToKeep)
|
|
{
|
|
// Build dictionary over resources to keep
|
|
Dictionary<ulong, UVMesh> uvMeshesToKeep = new();
|
|
Dictionary<ulong, UVAccelerationStructure> uvASToKeep = new();
|
|
Dictionary<UVFallbackBufferKey, UVFallbackBuffer> uvFBToKeep = new();
|
|
foreach (var instance in instancesToKeep)
|
|
{
|
|
ulong uvMeshHash = Util.EntityIDToUlong(instance.Mesh.GetEntityId());
|
|
if (_meshToUVMesh.TryGetValue(uvMeshHash, out UVMesh uvMesh))
|
|
{
|
|
uvMeshesToKeep.Add(uvMeshHash, uvMesh);
|
|
_meshToUVMesh.Remove(uvMeshHash);
|
|
ulong uvASHash = Util.EntityIDToUlong(uvMesh.Mesh.GetEntityId());
|
|
if (_meshToUVAccelerationStructure.TryGetValue(uvASHash, out UVAccelerationStructure uvAS))
|
|
{
|
|
uvASToKeep.Add(uvASHash, uvAS);
|
|
_meshToUVAccelerationStructure.Remove(uvASHash);
|
|
var uvFBKey = new UVFallbackBufferKey(instance.TexelSize.x, instance.TexelSize.y, uvMesh.Mesh.GetEntityId());
|
|
if (_meshToUVFallbackBuffer.TryGetValue(uvFBKey, out UVFallbackBuffer uvFB))
|
|
{
|
|
uvFBToKeep.Add(uvFBKey, uvFB);
|
|
_meshToUVFallbackBuffer.Remove(uvFBKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dispose remaining resources
|
|
Clear();
|
|
|
|
// Restore resources to keep
|
|
_meshToUVMesh = uvMeshesToKeep;
|
|
_meshToUVAccelerationStructure = uvASToKeep;
|
|
_meshToUVFallbackBuffer = uvFBToKeep;
|
|
}
|
|
|
|
internal bool GetResources(
|
|
BakeInstance[] instances,
|
|
out UVMesh[] uvMeshes,
|
|
out UVAccelerationStructure[] uvAccelerationStructures,
|
|
out UVFallbackBuffer[] uvFallbackBuffers)
|
|
{
|
|
List<UVMesh> uvMeshList = new();
|
|
List<UVAccelerationStructure> uvAccelerationStructureList = new();
|
|
List<UVFallbackBuffer> uvFallbackBufferList = new();
|
|
uvMeshes = null;
|
|
uvAccelerationStructures = null;
|
|
uvFallbackBuffers = null;
|
|
foreach (var instance in instances)
|
|
{
|
|
ulong uvMeshHash = Util.EntityIDToUlong(instance.Mesh.GetEntityId());
|
|
if (!_meshToUVMesh.TryGetValue(uvMeshHash, out UVMesh uvMesh))
|
|
return false;
|
|
uvMeshList.Add(uvMesh);
|
|
ulong uvASHash = Util.EntityIDToUlong(uvMesh.Mesh.GetEntityId());
|
|
if (!_meshToUVAccelerationStructure.TryGetValue(uvASHash, out UVAccelerationStructure uvAS))
|
|
return false;
|
|
uvAccelerationStructureList.Add(uvAS);
|
|
var uvFBKey = new UVFallbackBufferKey(instance.TexelSize.x, instance.TexelSize.y, uvMesh.Mesh.GetEntityId());
|
|
if (!_meshToUVFallbackBuffer.TryGetValue(uvFBKey, out UVFallbackBuffer uvFB))
|
|
return false;
|
|
uvFallbackBufferList.Add(uvFB);
|
|
}
|
|
uvMeshes = uvMeshList.ToArray();
|
|
uvAccelerationStructures = uvAccelerationStructureList.ToArray();
|
|
uvFallbackBuffers = uvFallbackBufferList.ToArray();
|
|
return true;
|
|
}
|
|
|
|
private void Clear()
|
|
{
|
|
foreach (var uvMesh in _meshToUVMesh)
|
|
uvMesh.Value.Dispose();
|
|
foreach (var uvAccelerationStructure in _meshToUVAccelerationStructure)
|
|
uvAccelerationStructure.Value.Dispose();
|
|
foreach (var uvFallbackBuffer in _meshToUVFallbackBuffer)
|
|
uvFallbackBuffer.Value.Dispose();
|
|
_meshToUVMesh.Clear();
|
|
_meshToUVAccelerationStructure.Clear();
|
|
_meshToUVFallbackBuffer.Clear();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Clear();
|
|
}
|
|
}
|
|
}
|