Migrate rendering from oop to dod

This commit is contained in:
2025-09-16 20:55:20 +09:00
parent 74bb2ccda5
commit 6a504cefc8
20 changed files with 263 additions and 449 deletions

View File

@@ -62,7 +62,7 @@ public unsafe class CommandList
_commandList.Ptr->OMSetRenderTargets(1, pRtvHandle, false, pDsvHandle);
}
public void ClearRenderTarget(RenderTexture renderTarget, Color128 color)
public void ClearRenderTarget(RenderTexture renderTarget, Color16 color)
{
renderTarget.ClearColor(this, color);
}

View File

@@ -11,6 +11,7 @@ namespace Ghost.Graphics.D3D12;
internal unsafe class D3D12Buffer : IBuffer
{
private readonly BufferHandle _handle;
private readonly D3D12ResourceAllocator? _allocator;
private readonly ComPtr<ID3D12Resource> _externalResource; // For externally managed resources
private ResourceState _currentState;
private void* _mappedPtr;
@@ -41,9 +42,11 @@ internal unsafe class D3D12Buffer : IBuffer
get;
}
public BufferHandle Handle => _handle;
public ResourceState CurrentState => _currentState;
public ID3D12Resource* NativeResource => _externalResource.Get() == null ? _handle.ResourceHandle.GetAllocation().Resource : _externalResource.Get();
public ID3D12Resource* NativeResource => _externalResource.Get() == null ? _allocator!.GetResource(_handle.ResourceHandle) : _externalResource.Get();
/// <summary>
/// Constructor for wrapping existing D3D12 resources
@@ -51,6 +54,8 @@ internal unsafe class D3D12Buffer : IBuffer
public D3D12Buffer(ComPtr<ID3D12Resource> resource, ulong size, BufferUsage usage, MemoryType memoryType)
{
_handle = BufferHandle.Invalid;
_allocator = null;
_externalResource = resource.Move();
Size = size;
@@ -62,9 +67,12 @@ internal unsafe class D3D12Buffer : IBuffer
/// <summary>
/// Constructor for allocator-managed buffers
/// </summary>
public D3D12Buffer(BufferHandle handle, ref readonly BufferDesc desc)
public D3D12Buffer(BufferHandle handle, ref readonly BufferDesc desc, D3D12ResourceAllocator allocator)
{
_handle = handle;
_allocator = allocator;
_externalResource = default;
Size = desc.Size;
Usage = desc.Usage;
@@ -75,7 +83,9 @@ internal unsafe class D3D12Buffer : IBuffer
public void* Map()
{
if (_mappedPtr != null)
{
return _mappedPtr;
}
if (MemoryType != MemoryType.Upload && MemoryType != MemoryType.Readback)
{
@@ -107,13 +117,16 @@ internal unsafe class D3D12Buffer : IBuffer
public void Dispose()
{
if (_disposed)
{
return;
}
Unmap();
if (_handle.IsValid)
{
_handle.Dispose();
// Release resource via allocator
_allocator?.ReleaseResource(_handle.ResourceHandle);
}
else
{

View File

@@ -63,7 +63,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
_isRecording = false;
}
public void BeginRenderPass(IRenderTarget renderTarget, Color128 clearColor)
public void BeginRenderPass(IRenderTarget renderTarget, Color16 clearColor)
{
// TODO: Implement render pass begin
throw new NotImplementedException();

View File

@@ -169,7 +169,7 @@ public unsafe class D3D12Renderer : IRenderer
private void RenderScene(IRenderTarget target, ICommandBuffer cmd)
{
var clearColor = new Color128 { r = 1.0f, g = 0.0f, b = 1.0f, a = 1.0f };
var clearColor = new Color16 { r = 1.0f, g = 0.0f, b = 1.0f, a = 1.0f };
cmd.BeginRenderPass(target, clearColor);
@@ -207,7 +207,7 @@ public unsafe class D3D12Renderer : IRenderer
// 3. Apply post-processing effects (tone mapping, gamma correction, etc.)
// For now, just clear the destination (this should be replaced with actual blit)
var clearColor = new Color128 { r = 0.0f, g = 0.0f, b = 0.0f, a = 1.0f };
var clearColor = new Color16 { r = 0.0f, g = 0.0f, b = 0.0f, a = 1.0f };
cmd.BeginRenderPass(destination, clearColor);
cmd.EndRenderPass();

View File

@@ -16,15 +16,13 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
{
public readonly Allocation allocation;
public readonly uint cpuFenceValue;
public readonly uint generation;
public bool Allocated => allocation.IsNotNull;
public AllocationInfo(in Allocation allocation, uint cpuFenceValue, uint generation)
public AllocationInfo(in Allocation allocation, uint cpuFenceValue)
{
this.allocation = allocation;
this.cpuFenceValue = cpuFenceValue;
this.generation = generation;
}
public void Dispose()
@@ -48,8 +46,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
private readonly RenderSystem _renderSystem;
private readonly D3D12DescriptorAllocator _descriptorAllocator;
private UnsafeList<AllocationInfo> _allocations = new(64, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
private UnsafeQueue<int> _freeSlots = new(64, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
private UnsafeSlotMap<AllocationInfo> _allocations = new(64, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
private UnsafeQueue<ResourceHandle> _temResources = new(64, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
private Guid* IID_NULL
@@ -99,32 +96,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
private ResourceHandle TrackResource(ref readonly Allocation allocation, bool isTemp)
{
int id;
uint generation;
AllocationInfo allocInfo;
if (_freeSlots.Count > 0)
{
id = _freeSlots.Dequeue();
var info = _allocations[id];
if (info.Allocated)
{
throw new InvalidOperationException($"ERROR: Resource ID {id} registered as free but still allocated.");
}
generation = info.generation + 1;
allocInfo = new AllocationInfo(in allocation, _renderSystem.CPUFenceValue, generation);
_allocations[id] = allocInfo;
}
else
{
id = _allocations.Count;
generation = 0u;
allocInfo = new AllocationInfo(in allocation, _renderSystem.CPUFenceValue, generation);
_allocations.Add(allocInfo);
}
var id = _allocations.Add(new(in allocation, _renderSystem.CPUFenceValue), out var generation);
var handle = new ResourceHandle(id, generation);
if (isTemp)
@@ -217,19 +189,6 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
return new(handle);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferHandle CreateUploadBuffer(uint sizeInBytes, bool tempResource = false)
{
var desc = new BufferDesc
{
Size = sizeInBytes,
Usage = BufferUsage.Upload,
MemoryType = MemoryType.Upload
};
return CreateBufferHandle(in desc, tempResource);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IRenderTarget CreateRenderTarget(ref readonly RenderTargetDesc desc, bool tempResource = false)
{
@@ -246,7 +205,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IBuffer CreateBuffer(ref readonly BufferDesc desc, bool tempResource = false)
{
return new D3D12Buffer(CreateBufferHandle(in desc, tempResource), in desc);
return new D3D12Buffer(CreateBufferHandle(in desc, tempResource), in desc, this);
}
#region Conversion Methods
@@ -367,9 +326,9 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
while (_temResources.Count > 0)
{
var handle = _temResources.Peek();
var info = _allocations[handle.id];
if (info.Allocated && info.cpuFenceValue > _renderSystem.CPUFenceValue)
if (_allocations.TryGetElementAt(handle.id, handle.generation, out var info)
&& info.Allocated)
{
break;
}
@@ -386,13 +345,13 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
throw new InvalidOperationException("Invalid resource handle.");
}
ref var allocationInfo = ref _allocations[handle.id];
if (!allocationInfo.Allocated || allocationInfo.generation != handle.generation)
var info = _allocations.GetElementAt(handle.id, handle.generation);
if (!info.Allocated)
{
throw new InvalidOperationException($"Resource with ID {handle.id} and generation {handle.generation} is not allocated or has been released.");
}
return allocationInfo.allocation.Resource;
return info.allocation.Resource;
}
public void ReleaseResource(ResourceHandle handle)
@@ -402,15 +361,15 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
return;
}
ref var allocationInfo = ref _allocations[handle.id];
ref var info = ref _allocations.GetElementReferenceAt(handle.id, handle.generation, out var exist);
if (!allocationInfo.Allocated || allocationInfo.generation != handle.generation)
if (!exist || !info.Allocated)
{
return;
}
allocationInfo.Dispose();
_freeSlots.Enqueue(handle.id);
info.Dispose();
_allocations.Remove(handle.id, handle.generation);
}
public void Dispose()
@@ -421,9 +380,9 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator<ID3D12Resource
throw new InvalidOperationException($"ResourceAllocator is being disposed with {_allocations.Count} allocations still registered. Ensure all resources are released before disposing.");
}
#endif
for (var i = 0; i < _allocations.Count; i++)
foreach (var info in _allocations)
{
_allocations[i].Dispose();
info.Dispose();
}
_allocations.Dispose();

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ghost.Graphics.D3D12;
internal class D3D12ResourceDatabase
{
}

View File

@@ -10,11 +10,11 @@ internal unsafe static class D3D12PipelineResource
public const int BACK_BUFFER_COUNT = 2;
private readonly static InputElementDescription[] s_inputElementDescs = [
new InputElementDescription{ SemanticName = Vertex.Semantic.PositionName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 0u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
new InputElementDescription{ SemanticName = Vertex.Semantic.NormalName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 16u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
new InputElementDescription{ SemanticName = Vertex.Semantic.TangentName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 32u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
new InputElementDescription{ SemanticName = Vertex.Semantic.ColorName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 48u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
new InputElementDescription{ SemanticName = Vertex.Semantic.UVName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 64u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 }
new InputElementDescription{ SemanticName = Vertex.Semantic.pPositionName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 0u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
new InputElementDescription{ SemanticName = Vertex.Semantic.pNormalName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 16u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
new InputElementDescription{ SemanticName = Vertex.Semantic.pTangentName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 32u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
new InputElementDescription{ SemanticName = Vertex.Semantic.pColorName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 48u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
new InputElementDescription{ SemanticName = Vertex.Semantic.pUVName, SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 64u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 }
];
public const Format SWAP_CHAIN_BACK_BUFFER_FORMAT = Format.B8G8R8A8Unorm;