Files
GhostEngine/Ghost.Graphics/D3D12/GraphicsBuffer.cs
Misaki eafbfb2fa1 Update rendering architecture and resource management
Added a new `Ref<T>` struct for reference semantics.
Added the `RenderGraph` system for managing rendering passes.
Added the `RenderTexture` class for encapsulating GPU resources.
Added `GraphicsBuffer` class for effective GPU resource management.
Changed `CommandList` methods from public to internal for visibility control.
Changed `IRenderPass` interface from internal to public for accessibility.
Changed `GetData<T>()` in `ComponentObject.cs` to return `CompRef<T>`.
Changed `GetComponent<T>()` in `EntityManager.cs` to return `CompRef<T>`.
Changed `GetSingleton<T>()` in `World.cs` to use `CompRef<T>`.
Changed `IQueryTypeParameter` to use `CompRef<T>` for consistency.
Changed `QueryItem<T0>` and related structs to use `CompRef<T>`.
Changed `Material` class to support bindless textures.
Changed `Shader` class to support bindless rendering.
Changed `Mesh` class to support bindless vertex and index buffer access.
Updated documentation to reflect the new bindless rendering architecture.
2025-08-01 21:34:48 +09:00

120 lines
3.5 KiB
C#

using Ghost.Graphics.Data;
using System.Runtime.CompilerServices;
using Win32.Graphics.Direct3D12;
namespace Ghost.Graphics.D3D12;
public unsafe class GraphicsBuffer : GraphicsResource
{
public enum Usage
{
Common,
Vertex,
Index,
CopySource,
CopyDestination,
Structured,
Raw,
Append,
Counter,
Indirect,
Constant,
}
private readonly Usage _usage;
public Usage BufferUsage => _usage;
private GraphicsBuffer(Usage usage, in BufferHandle handle, bool tempResource = false)
: base(handle.ResourceHandle, tempResource)
{
_usage = usage;
}
public static GraphicsBuffer Create(uint sizeInBytes, Usage usage, bool tempResource = false)
{
var heapType = HeapType.Default;
var state = ResourceStates.Common;
switch (usage)
{
case Usage.Vertex:
heapType = HeapType.Default;
state = ResourceStates.VertexAndConstantBuffer;
break;
case Usage.Index:
heapType = HeapType.Default;
state = ResourceStates.IndexBuffer;
break;
case Usage.CopySource:
heapType = HeapType.Readback;
state = ResourceStates.CopySource;
break;
case Usage.CopyDestination:
heapType = HeapType.Default;
state = ResourceStates.CopyDest;
break;
case Usage.Structured:
case Usage.Raw:
case Usage.Append:
case Usage.Counter:
heapType = HeapType.Default;
state = ResourceStates.AllShaderResource | ResourceStates.UnorderedAccess;
break;
case Usage.Indirect:
heapType = HeapType.Default;
state = ResourceStates.IndirectArgument;
break;
case Usage.Constant:
heapType = HeapType.Upload;
state = ResourceStates.GenericRead;
break;
default:
break;
}
var handle = GraphicsPipeline.ResourceAllocator.CreateBuffer(sizeInBytes, heapType, initialState: state, tempResource: tempResource);
return new GraphicsBuffer(usage, in handle, tempResource);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetData<T>(Span<T> data, uint offset)
where T : unmanaged
{
fixed (T* ptr = data)
{
SetData(ptr, offset, (uint)data.Length);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void SetData<T>(T* data, uint offset, uint length)
where T : unmanaged
{
var size = (uint)(length * sizeof(T));
SetData((void*)data, offset, size);
}
public unsafe void SetData(void* data, uint offset, uint size)
{
ThrowIfDisposed();
if (data == null)
{
throw new ArgumentNullException(nameof(data), "Data pointer cannot be null.");
}
if (size > Size)
{
throw new ArgumentException($"Data size {size} exceeds buffer size {Size}.", nameof(size));
}
var range = new Win32.Graphics.Direct3D12.Range(offset, size);
void* mappedPtr;
ThrowIfFailed(NativeResource.Ptr->Map(0, &range, &mappedPtr));
Unsafe.CopyBlock(mappedPtr, data, size);
NativeResource.Ptr->Unmap(0, &range);
}
}