Refactor MeshInstance

This commit is contained in:
2026-03-13 15:10:25 +09:00
parent 619720feee
commit 8a3b40b4f8
15 changed files with 57 additions and 61 deletions

View File

@@ -1,47 +1,15 @@
using Ghost.Core;
using Ghost.Entities;
using Ghost.Graphics.Core;
using Misaki.HighPerformance.LowLevel.Collections;
namespace Ghost.Engine.Components;
public struct MeshPalette : ISharedComponent, IEquatable<MeshPalette>
{
public UnsafeArray<Handle<Mesh>> meshes;
public UnsafeArray<Handle<Material>> materials;
public bool Equals(MeshPalette other)
{
throw new NotImplementedException();
}
public override int GetHashCode()
{
throw new NotImplementedException();
}
public override bool Equals(object? obj)
{
return obj is MeshPalette palette && Equals(palette);
}
public static bool operator ==(MeshPalette left, MeshPalette right)
{
return left.Equals(right);
}
public static bool operator !=(MeshPalette left, MeshPalette right)
{
return !(left == right);
}
}
public struct MeshInstance : IComponent
{
public int meshIndex;
public int materialIndex;
public Handle<Mesh> mesh;
// NOTE: This will be the first material, we can access other materials by the bindless index of the first material + the local index stored in the meshlet.
public Handle<Material> materialStart;
public ShadowCastingMode shadowCastingMode;
public RenderingLayerMask renderingLayerMask;
public byte subMeshIndex;
public bool staticShadowCaster;
}

View File

@@ -3,7 +3,6 @@ using Ghost.Engine.Components;
using Ghost.Entities;
using Ghost.Graphics.Core;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Utilities;
namespace Ghost.Engine.Systems;
@@ -14,7 +13,6 @@ public class RenderExtractionSystem : ISystem
public void Initialize(ref readonly SystemAPI systemAPI)
{
_queryID = new QueryBuilder()
// TODO: We also need to filter by MeshPalette.
.WithAll<MeshInstance, LocalToWorld>()
.Build(systemAPI.World);
}
@@ -30,6 +28,7 @@ public class RenderExtractionSystem : ISystem
var renderList = new RenderList(1, 64, Allocator.Temp);
// TODO: We should extract the render record for each camera because different cameras may have different culling results.
// TODO: This chould be done in parallel jobs.
foreach (var chunk in query.GetChunkIterator())
{
var meshInstances = chunk.GetComponentData<MeshInstance>();
@@ -47,7 +46,6 @@ public class RenderExtractionSystem : ISystem
// mesh = meshInstance.meshIndex,
// material = meshInstance.materialIndex,
renderingLayerMask = meshInstance.renderingLayerMask,
subMeshIndex = meshInstance.subMeshIndex,
}, 0);
}

View File

@@ -341,6 +341,23 @@ internal class D3D12ResourceDatabase : IResourceDatabase
_descriptorAllocator.Release(new Identifier<SamplerDescriptor>(id.Value));
}
public Error Swap(Handle<GPUResource> handleA, Handle<GPUResource> handleB)
{
ref var recordA = ref _resources.GetElementReferenceAt(handleA.ID, handleA.Generation, out var existA);
ref var recordB = ref _resources.GetElementReferenceAt(handleB.ID, handleB.Generation, out var existB);
if (!existA || !existB)
{
return Error.NotFound;
}
var temp = recordA;
recordA = recordB;
recordB = temp;
return Error.None;
}
public void BeginFrame(uint currentFrameFenceValue)
{
ObjectDisposedException.ThrowIf(_disposed, this);

View File

@@ -127,4 +127,12 @@ public interface IResourceDatabase : IDisposable
/// </summary>
/// <param name="id">The identifier of the sampler to release. Must reference a valid, existing sampler.</param>
void ReleaseSampler(Identifier<Sampler> id);
/// <summary>
/// Swaps the resources associated with the two specified handles, effectively exchanging their identities and all associated data.
/// </summary>
/// <param name="handleA">The first handle whose associated resource is to be swapped.</param>
/// <param name="handleB">The second handle whose associated resource is to be swapped.</param>
/// <returns>An Error indicating the success or failure of the swap operation.</returns>
Error Swap(Handle<GPUResource> handleA, Handle<GPUResource> handleB);
}

View File

@@ -8,10 +8,9 @@ namespace Ghost.Graphics.Core;
public record struct RenderRecord
{
public float4x4 localToWorld;
public Handle<Material> material;
public Handle<Mesh> mesh;
public Handle<Material> materialOffset;
public RenderingLayerMask renderingLayerMask;
public byte subMeshIndex;
}
public struct RenderList : IDisposable

View File

@@ -20,7 +20,10 @@ internal sealed class SwapChainRecord
while (true)
{
int current = Volatile.Read(ref _refCount);
if (current == 0) return false; // It's dead, let it go.
if (current == 0)
{
return false; // It's dead, let it go.
}
if (Interlocked.CompareExchange(ref _refCount, current + 1, current) == current)
{
@@ -66,7 +69,10 @@ internal class SwapChainManager
if (record != null)
{
if (record.TryAddRef()) return record.SwapChain;
if (record.TryAddRef())
{
return record.SwapChain;
}
Thread.Yield();
continue;