using Ghost.Core; using Ghost.Graphics.Data; using Win32.Graphics.Direct3D12; 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); } /// /// Viewport description /// public struct ViewportDesc { public float x; public float y; public float width; public float height; public float minDepth; public float maxDepth; } /// /// Rectangle description /// public struct RectDesc { public uint left; public uint top; public uint right; public uint bottom; } /// /// Resource states /// [Flags] public enum ResourceState { Common = 0, VertexAndConstantBuffer = 1 << 0, IndexBuffer = 1 << 1, RenderTarget = 1 << 2, UnorderedAccess = 1 << 3, DepthWrite = 1 << 4, DepthRead = 1 << 5, PixelShaderResource = 1 << 6, CopyDest = 1 << 7, CopySource = 1 << 8, GenericRead = 1 << 9, IndirectArgument = 1 << 10, Present = 0, } internal static class ResourceStateExtensions { public static ResourceStates ToD3D12States(this ResourceState state) { return state switch { ResourceState.Common or ResourceState.Present => ResourceStates.Common, ResourceState.VertexAndConstantBuffer => ResourceStates.VertexAndConstantBuffer, ResourceState.IndexBuffer => ResourceStates.IndexBuffer, ResourceState.RenderTarget => ResourceStates.RenderTarget, ResourceState.UnorderedAccess => ResourceStates.UnorderedAccess, ResourceState.DepthWrite => ResourceStates.DepthWrite, ResourceState.DepthRead => ResourceStates.DepthRead, ResourceState.PixelShaderResource => ResourceStates.PixelShaderResource, ResourceState.CopyDest => ResourceStates.CopyDest, ResourceState.CopySource => ResourceStates.CopySource, _ => throw new ArgumentException($"Unknown resource state: {state}") }; } } public struct SubResourceData { public unsafe void* pData; public nint rowPitch; public nint slicePitch; }