//////////////////////////////////////////////////////////// //~ DirectX12 libs #pragma warning(push, 0) # include # include # include #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);