using Ghost.Core;
using Ghost.Graphics.Data;
using TerraFX.Interop.DirectX;
namespace Ghost.Graphics.RHI;
///
/// D3D12-style command buffer interface for recording rendering commands
///
public interface ICommandBuffer : IDisposable
{
public CommandBufferType Type
{
get;
}
public bool IsEmpty
{
get;
}
///
/// Begins recording commands into this command buffer
///
public void Begin();
///
/// Ends recording commands and prepares for submission
///
public void End();
///
/// Sets the optional render targets and optional depth target for subsequent rendering operations.
///
///
/// To specify no render targets, provide an empty span for .
/// Use for if no depth target is required.
///
/// A read-only span of handles to textures that will be used as render targets.
/// The order of handles determines the order in which render targets are bound.
/// A handle to the texture to be used as the depth target. Specify a invalid handle if no depth target is required.
public void SetRenderTargets(ReadOnlySpan> renderTargets, Handle depthTarget);
///
/// Begins a render pass with the specified render target
///
/// Render target to render into (can be invalid)
/// Depth target to use (can be invalid)
/// Color to clear the render target with
public void BeginRenderPass(Handle renderTarget, Handle depthTarget, Color128 clearColor);
///
/// Ends the current render pass
///
public void EndRenderPass();
///
/// Sets the viewport for rendering
///
/// Viewport to set
public void SetViewport(ViewportDesc viewport);
///
/// Sets the scissor rectangle
///
/// Scissor rectangle to set
public void SetScissorRect(RectDesc rect);
///
/// Inserts a resource barrier for state transitions
///
/// Resource to transition
/// Current resource state
/// Target resource state
public void ResourceBarrier(Handle resource, ResourceState before, ResourceState after);
///
/// Sets the graphics root signature
///
/// Root signature to set
public void SetRootSignature(IRootSignature rootSignature);
///
/// Sets the pipeline state object
///
/// Pipeline state to set
public void SetPipelineState(IShaderPipeline pipelineState);
public void SetVertexBuffer(uint slot, Handle buffer, ulong offset = 0);
public void SetIndexBuffer(Handle buffer, IndexType type, ulong offset = 0);
public void Draw(uint vertexCount, uint instanceCount = 1, uint startVertex = 0, uint startInstance = 0);
public void DrawIndexed(uint indexCount, uint instanceCount = 1, uint startIndex = 0, int baseVertex = 0, uint startInstance = 0);
///
/// Dispatches compute threads
///
/// Thread groups in X dimension
/// Thread groups in Y dimension
/// Thread groups in Z dimension
public void Dispatch(uint threadGroupCountX, uint threadGroupCountY = 1, uint threadGroupCountZ = 1);
///
/// Uploads the specified data to the buffer represented by the given handle.
///
/// The unmanaged value type of the elements to upload to the buffer.
/// A handle to the buffer that will receive the uploaded data.
/// A read-only span containing the data to upload to the buffer. The span must contain elements of type
/// .
public void Upload(Handle buffer, ReadOnlySpan data)
where T : unmanaged;
///
/// Uploads texture data to the specified texture resource starting at the given subresource index.
///
/// The texture resource to which the subresource data will be uploaded. Must be a valid, initialized texture handle.
/// The index of the first subresource in the texture to receive data. Must be less than the total number of subresources in the texture.
/// A reference to the structure containing the subresource data to upload. The data must match the format and layout expected by the texture.
/// The number of subresources to upload, starting from .
/// Must be greater than zero and not exceed the remaining subresources in the texture.
public void Upload(Handle texture, params ReadOnlySpan subresources);
///
/// Copies a specified number of bytes from the source graphics buffer to the destination graphics buffer.
///
/// The handle to the destination graphics buffer where data will be written. Cannot be null.
/// The handle to the source graphics buffer from which data will be read. Cannot be null.
/// The byte offset in the destination buffer at which to begin writing. Must be zero or greater.
/// The byte offset in the source buffer at which to begin reading. Must be zero or greater.
/// The number of bytes to copy. If zero, copies the remaining bytes from the source buffer starting at .
public void CopyBuffer(Handle dest, Handle src, ulong destOffset = 0, ulong srcOffset = 0, ulong numBytes = 0);
}
internal static class ResourceStateExtensions
{
public static D3D12_RESOURCE_STATES ToD3D12States(this ResourceState state)
{
return state switch
{
ResourceState.Common or ResourceState.Present => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON,
ResourceState.VertexAndConstantBuffer => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
ResourceState.IndexBuffer => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_INDEX_BUFFER,
ResourceState.RenderTarget => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_RENDER_TARGET,
ResourceState.UnorderedAccess => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
ResourceState.DepthWrite => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_WRITE,
ResourceState.DepthRead => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_READ,
ResourceState.PixelShaderResource => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
ResourceState.CopyDest => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST,
ResourceState.CopySource => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_SOURCE,
_ => throw new ArgumentException($"Unknown resource state: {state}")
};
}
}