391 lines
9.0 KiB
C
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);
|