power_play/src/gpu/gpu_dx12/gpu_dx12.h
2025-11-23 13:32:37 -06:00

391 lines
9.0 KiB
C

////////////////////////////////////////////////////////////
//~ DirectX12 libs
#pragma warning(push, 0)
# include <d3d12.h>
# include <dxgidebug.h>
# include <dxgi1_6.h>
#pragma warning(pop)
#pragma comment(lib, "d3d12")
#pragma comment(lib, "dxgi")
////////////////////////////////////////////////////////////
//~ Tweakable defines
#define GPU_D12_TearingIsAllowed 1
#define GPU_D12_FrameLatency 1
#define GPU_D12_SwapchainBufferCount 3
#define GPU_D12_SwapchainFlags (((GPU_D12_TearingIsAllowed != 0) * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) \
| ((GPU_D12_FrameLatency != 0) * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
#define GPU_D12_MaxCbvSrvUavDescriptors (1024 * 128)
#define GPU_D12_MaxSamplerDescriptors (1024 * 1)
#define GPU_D12_MaxRtvDescriptors (1024 * 64)
////////////////////////////////////////////////////////////
//~ Pipeline types
Struct(GPU_D12_PipelineDesc)
{
VertexShader vs;
PixelShader ps;
ComputeShader cs;
b32 is_wireframe;
D3D12_PRIMITIVE_TOPOLOGY_TYPE topology_type;
GPU_Format render_target_formats[GPU_MaxRasterTargets];
};
Struct(GPU_D12_Pipeline)
{
GPU_D12_Pipeline *next_in_bin;
u64 hash;
GPU_D12_PipelineDesc desc;
ID3D12PipelineState *pso;
Fence ready_fence;
b32 ok;
String error;
};
Struct(GPU_D12_PipelineBin)
{
Mutex mutex;
GPU_D12_Pipeline *first;
};
////////////////////////////////////////////////////////////
//~ Descriptor types
Enum(GPU_D12_DescriptorHeapKind)
{
GPU_D12_DescriptorHeapKind_CbvSrvUav,
GPU_D12_DescriptorHeapKind_Rtv,
GPU_D12_DescriptorHeapKind_Sampler,
GPU_D12_DescriptorHeapKind_Count
};
Struct(GPU_D12_DescriptorHeap)
{
Arena *descriptors_arena;
D3D12_DESCRIPTOR_HEAP_TYPE type;
u32 descriptor_size;
ID3D12DescriptorHeap *d3d_heap;
D3D12_CPU_DESCRIPTOR_HANDLE start_handle;
Mutex mutex;
struct GPU_D12_Descriptor *first_free;
u32 allocated_count;
u32 max_count;
};
Struct(GPU_D12_Descriptor)
{
GPU_D12_Descriptor *next;
u64 queue_commit_target;
GPU_D12_DescriptorHeap *heap;
D3D12_CPU_DESCRIPTOR_HANDLE handle;
u32 index;
struct GPU_D12_Resource *resource;
};
Struct(GPU_D12_DescriptorList)
{
GPU_D12_Descriptor *first;
GPU_D12_Descriptor *last;
};
////////////////////////////////////////////////////////////
//~ Arena types
Struct(GPU_D12_Arena)
{
GPU_D12_DescriptorList committed_descriptors_by_heap_and_queue[GPU_D12_DescriptorHeapKind_Count][GPU_NumQueues];
};
////////////////////////////////////////////////////////////
//~ Resource types
Struct(GPU_D12_Resource)
{
GPU_D12_Resource *next_free;
ID3D12Resource *d3d_resource;
u64 uid;
/* Buffer info */
GPU_BufferDesc buffer_desc;
D3D12_GPU_VIRTUAL_ADDRESS buffer_gpu_address;
/* Texture info */
b32 is_texture;
D3D12_BARRIER_LAYOUT texture_layout;
GPU_TextureDesc texture_desc;
/* Backbuffer info */
struct GPU_D12_Swapchain *swapchain;
};
////////////////////////////////////////////////////////////
//~ Command queue types
Struct(GPU_D12_CommandQueueDesc)
{
D3D12_COMMAND_LIST_TYPE type;
D3D12_COMMAND_QUEUE_PRIORITY priority;
};
Struct(GPU_D12_Queue)
{
ID3D12CommandQueue *d3d_queue;
GPU_D12_CommandQueueDesc desc;
Mutex commit_mutex;
ID3D12Fence *commit_fence;
u64 commit_fence_target;
struct GPU_D12_RawCommandList *first_committed_cl;
struct GPU_D12_RawCommandList *last_committed_cl;
Fence sync_fence;
};
////////////////////////////////////////////////////////////
//~ Raw command list types
Struct(GPU_D12_RawCommandList)
{
GPU_D12_Queue *queue;
GPU_D12_RawCommandList *next;
u64 commit_fence_target;
ID3D12CommandAllocator *ca;
ID3D12GraphicsCommandList7 *cl;
};
////////////////////////////////////////////////////////////
//~ Command list types
#define GPU_D12_CmdsPerChunk 256
Enum(GPU_D12_CmdKind)
{
GPU_D12_CmdKind_None,
/* Access */
GPU_D12_CmdKind_Access,
/* Constant */
GPU_D12_CmdKind_Constant,
/* Copy */
GPU_D12_CmdKind_Copy,
/* Compute */
GPU_D12_CmdKind_Compute,
/* Rasterize */
GPU_D12_CmdKind_Rasterize,
/* Clear rtv */
GPU_D12_CmdKind_ClearRtv,
};
Struct(GPU_D12_Cmd)
{
GPU_D12_CmdKind kind;
b32 skip;
union
{
struct
{
GPU_AccessKind after;
GPU_D12_Resource *resource;
/* Post-batch data */
b32 is_end_of_batch;
u64 batch_gen;
GPU_AccessKind before;
} access;
struct
{
i32 slot;
u32 value;
} constant;
struct
{
GPU_D12_Resource *dst;
GPU_D12_Resource *src;
u64 dst_offset;
u64 src_offset;
u64 size;
} copy_bytes;
struct
{
GPU_D12_Resource *dst;
GPU_D12_Resource *src;
Vec3I32 dst_offset;
Vec3I32 src_offset;
Vec3I32 size;
} copy_texels;
struct
{
ComputeShader cs;
Vec3I32 groups;
} compute;
struct
{
VertexShader vs;
PixelShader ps;
u32 instances_count;
D3D12_INDEX_BUFFER_VIEW ibv;
GPU_D12_Descriptor *rtv_descriptors[GPU_MaxRasterTargets];
Rng3 viewport;
Rng2 scissor;
GPU_RasterMode mode;
} rasterize;
struct
{
GPU_D12_Descriptor *rtv_descriptor;
Vec4 color;
} clear_rtv;
};
};
Struct(GPU_D12_CmdChunk)
{
GPU_D12_CmdChunk *next;
struct GPU_D12_CmdList *cl;
GPU_D12_Cmd *cmds;
u64 cmds_count;
};
Struct(GPU_D12_CmdList)
{
GPU_D12_CmdList *next;
GPU_D12_CmdChunk *first_cmd_chunk;
GPU_D12_CmdChunk *last_cmd_chunk;
u64 chunks_count;
u64 cmds_count;
};
////////////////////////////////////////////////////////////
//~ Swapchain types
Struct(GPU_D12_Swapchain)
{
IDXGISwapChain3 *d3d_swapchain;
HWND window_hwnd;
HANDLE waitable;
HANDLE present_event;
ID3D12Fence *present_fence;
u64 present_fence_target;
GPU_Format backbuffers_format;
Vec2I32 backbuffers_resolution;
GPU_D12_Resource backbuffers[GPU_D12_SwapchainBufferCount];
};
////////////////////////////////////////////////////////////
//~ State types
Struct(GPU_D12_SharedState)
{
Atomic64Padded next_resource_uid;
/* Stats */
Atomic64 driver_resources_allocated;
Atomic64 driver_descriptors_allocated;
/* Queues */
GPU_D12_Queue queues[GPU_NumQueues];
/* Descriptor heaps */
GPU_D12_DescriptorHeap descriptor_heaps[GPU_D12_DescriptorHeapKind_Count];
/* Rootsig */
ID3D12RootSignature *bindless_rootsig;
/* Pipelines */
GPU_D12_PipelineBin pipeline_bins[1024];
/* Command lists */
Mutex free_cmd_lists_mutex;
GPU_D12_CmdList *first_free_cmd_list;
/* Command chunks */
Mutex free_cmd_chunks_mutex;
GPU_D12_CmdChunk *first_free_cmd_chunk;
/* Swapchains */
Mutex free_swapchains_mutex;
GPU_D12_Swapchain *first_free_swapchain;
/* Device */
IDXGIFactory6 *factory;
IDXGIAdapter3 *adapter;
ID3D12Device *device;
} extern GPU_D12_shared_state;
////////////////////////////////////////////////////////////
//~ Startup
void GPU_D12_Startup(void);
////////////////////////////////////////////////////////////
//~ Helpers
DXGI_FORMAT GPU_D12_DxgiFormatFromGpuFormat(GPU_Format format);
GPU_D12_Arena *GPU_D12_ArenaFromHandle(GPU_ArenaHandle handle);
GPU_D12_CmdList *GPU_D12_CommandListFromHandle(GPU_CommandListHandle handle);
GPU_D12_Resource *GPU_D12_ResourceFromHandle(GPU_ResourceHandle handle);
GPU_D12_Swapchain *GPU_D12_SwapchainFromHandle(GPU_SwapchainHandle handle);
////////////////////////////////////////////////////////////
//~ Pipeline
JobDecl(GPU_D12_LoadPipeline, { GPU_D12_Pipeline *pipeline; });
GPU_D12_Pipeline *GPU_D12_PipelineFromDesc(GPU_D12_PipelineDesc desc);
////////////////////////////////////////////////////////////
//~ Queue
GPU_D12_Queue *GPU_D12_QueueFromKind(GPU_QueueKind kind);
////////////////////////////////////////////////////////////
//~ Resource helpers
GPU_D12_Descriptor *GPU_D12_PushDescriptor(GPU_D12_Arena *gpu_arena, GPU_D12_Resource *resource, GPU_D12_DescriptorHeapKind heap_kind);
GPU_D12_Descriptor *GPU_D12_DescriptorFromIndex(GPU_D12_DescriptorHeapKind heap_kind, u32 index);
D3D12_INDEX_BUFFER_VIEW GPU_D12_IbvFromIbPtr(IndexBufferGpuPtr ptr);
////////////////////////////////////////////////////////////
//~ Raw command list
GPU_D12_RawCommandList *GPU_D12_PrepareRawCommandList(GPU_QueueKind queue_kind);
void GPU_D12_CommitRawCommandList(GPU_D12_RawCommandList *cl);
////////////////////////////////////////////////////////////
//~ Command helpers
GPU_D12_Cmd *GPU_D12_PushCmd(GPU_D12_CmdList *cl);
////////////////////////////////////////////////////////////
//~ Sync job
// JobDecl(GPU_D12_StartQueueSync, EmptySig);