Refactor material palette system with GPU indirection

Major overhaul of material palette management:
- Added two-buffer indirection (PaletteOffsetBuffer, MaterialIndexBuffer) for GPU material lookup, with incremental upload and resizing.
- MaterialPaletteStore now tracks dirty ranges, supports deferred slot reclamation, and exposes CPU-side arrays for upload.
- ResourceManager manages persistent GPU buffers and uploads only dirty subranges per frame.
- Updated HLSL and C# structs to use palette indices.
- Refactored systems/components to use new palette index and release logic.
- Added RenderContext.UploadBufferRange for partial uploads.
Minor: Fixed StbIApi interop signatures, updated test namespaces, and performed code cleanups.
This commit is contained in:
2026-04-28 18:22:09 +09:00
parent 631638f3fb
commit 0eaf7cd51d
19 changed files with 390 additions and 30 deletions

View File

@@ -106,6 +106,43 @@ public readonly unsafe ref struct RenderContext
}
}
/// <summary>
/// Uploads a sub-range of data into an existing GPU buffer at the specified byte offset.
/// Used for incremental uploads (e.g. dirty palette ranges).
/// </summary>
public void UploadBufferRange<T>(Handle<GPUBuffer> buffer, ReadOnlySpan<T> data, uint byteOffset)
where T : unmanaged
{
if (data.IsEmpty)
{
return;
}
var sizeInBytes = (nuint)(data.Length * sizeof(T));
var uploadDesc = new BufferDesc
{
Size = sizeInBytes,
Usage = BufferUsage.Upload,
HeapType = HeapType.Upload,
};
var uploadHandle = ResourceManager.CreateTransientBuffer(in uploadDesc);
if (uploadHandle.IsInvalid)
{
throw new OutOfMemoryException("Failed to create upload buffer for range upload.");
}
fixed (T* pData = data)
{
var mappedData = ResourceDatabase.MapResource(uploadHandle.AsResource(), 0, null);
MemoryUtility.MemCpy(mappedData, pData, sizeInBytes);
ResourceDatabase.UnmapResource(uploadHandle.AsResource(), 0, null);
}
CommandBuffer.CopyBuffer(buffer, uploadHandle, byteOffset, 0, sizeInBytes);
}
public Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices, bool staticMesh)
{
var mesh = ResourceManager.CreateMesh(vertices, indices);
@@ -253,6 +290,7 @@ public readonly unsafe ref struct RenderContext
meshletBuffer = ResourceDatabase.GetBindlessIndex(meshData.MeshLetBuffer.AsResource()),
meshletVerticesBuffer = ResourceDatabase.GetBindlessIndex(meshData.MeshletVerticesBuffer.AsResource()),
meshletTrianglesBuffer = ResourceDatabase.GetBindlessIndex(meshData.MeshletTrianglesBuffer.AsResource()),
materialSlotCount = (uint)meshData.MeshletData.materialSlotCount,
};
var bufferHandle = meshData.MeshDataBuffer.AsResource();