simple clear color from d3d12, but with debug layer errors and warnings

This commit is contained in:
Anton Ljungdahl 2025-05-19 22:17:50 +02:00
parent d73c450d21
commit f488b22239
3 changed files with 198 additions and 102 deletions

11
anton_render.raddb_proj Normal file
View File

@ -0,0 +1,11 @@
// raddbg 0.9.17 project file
recent_file: path: "src/render/d3d12/render_d3d12.c"
recent_file: path: "src/os/win32/os_gfx_win32.c"
recent_file: path: "src/main.c"
target:
{
executable: "build/program.exe"
working_directory: build
enabled: 1
}

View File

@ -38,7 +38,7 @@ entry_point()
r_init();
//test_arena(arena);
r_trigger_debug_message();
//r_trigger_debug_message();
//r_log_debug_messages();
// Main program loop

View File

@ -9,7 +9,7 @@
//~
#define D3D12_ERROR(msg, ...) LOG("D3D12 ERROR (anton): "); LOG(msg, __VA_ARGS__); Trap();
#define D3D12_CHECK(hr) if(FAILED((hr))) { Trap(); }
#define D3D12_CHECK(hr, msg) if(FAILED((hr))) { D3D12_ERROR(msg, __VA_ARGS__) }
#define D3D12_RELEASE(res) if( (res) && (res)->lpVtbl) { (res)->lpVtbl->Release((res)); (res) = 0; }
@ -18,16 +18,18 @@ global R_D3D12_State *r_d3d12_state = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
// D3D12 initialisiation
internal void
r_init()
{
Arena *arena = arena_alloc();
r_d3d12_state = push_array(arena, R_D3D12_State, 1);
r_d3d12_state->arena = arena;
r_d3d12_state->window_handle = g_win32_window_handle;
HRESULT hr;
// ---------------------------------------------------------------------------
// Debug interface
hr = D3D12GetDebugInterface(&IID_ID3D12Debug, (void**)&r_d3d12_state->debug);
if(SUCCEEDED(hr) && r_d3d12_state->debug )
{
@ -38,40 +40,194 @@ r_init()
D3D12_ERROR("Failed to create D3D12 Debug interface \n");
}
// ---------------------------------------------------------------------------
// Create device
hr = D3D12CreateDevice(0,
D3D_FEATURE_LEVEL_11_0,
&IID_ID3D12Device,
(void **)&r_d3d12_state->device);
if(FAILED(hr))
{
D3D12_ERROR("Failed to create device \n");
D3D12_CHECK(hr, "Failed to create device\n");
// ---------------------------------------------------------------------------
// Create command queue
D3D12_COMMAND_QUEUE_DESC queue_desc = {
.Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
.NodeMask = 0
};
ID3D12CommandQueue *command_queue;
hr = r_d3d12_state->device->lpVtbl->CreateCommandQueue(r_d3d12_state->device,
&queue_desc,
&IID_ID3D12CommandQueue,
(void**)&command_queue);
D3D12_CHECK(hr, "Failed to create command queue\n");
// ---------------------------------------------------------------------------
// Create DXGI factory
IDXGIFactory4 *factory;
hr = CreateDXGIFactory1(&IID_IDXGIFactory4, (void**)&factory);
D3D12_CHECK(hr, "Failed to create factory\n");
// ---------------------------------------------------------------------------
// Create Swapchain
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {
.Width = WINDOW_WIDTH_PX,
.Height = WINDOW_HEIGHT_PX,
.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
.Stereo = FALSE,
.SampleDesc = {1, 0},
.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
.BufferCount = 2,
.Scaling = DXGI_SCALING_STRETCH,
.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED,
.Flags = 0
};
// We create a temporary SwapChain1 that is then upgraded to a SwapChain3.
IDXGISwapChain1* temp_swap_chain;
hr = factory->lpVtbl->CreateSwapChainForHwnd(factory,
(IUnknown*)command_queue,
r_d3d12_state->window_handle,
&swap_chain_desc,
0,
0,
&temp_swap_chain);
D3D12_CHECK(hr, "Failed to create temp swap chain \n");
hr = temp_swap_chain->lpVtbl->QueryInterface(temp_swap_chain,
&IID_IDXGISwapChain3,
(void**)&r_d3d12_state->swapchain);
D3D12_CHECK(hr, "Failed to upgrade to swapchain3\n");
temp_swap_chain->lpVtbl->Release(temp_swap_chain);
// ---------------------------------------------------------------------------
// Create Render target view (RTV) descriptor heap
D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc = {
.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
.NumDescriptors = 2,
.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
.NodeMask = 0
};
ID3D12DescriptorHeap *rtv_heap;
hr = r_d3d12_state->device->lpVtbl->
CreateDescriptorHeap(r_d3d12_state->device,
&rtv_heap_desc,
&IID_ID3D12DescriptorHeap,
(void**)&rtv_heap);
D3D12_CHECK(hr, "Failed to create descriptor heap\n");
U32 rtv_descriptor_size = r_d3d12_state->device->lpVtbl->
GetDescriptorHandleIncrementSize(r_d3d12_state->device,
D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
// ---------------------------------------------------------------------------
// Create render target views
ID3D12Resource* render_targets[2];
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle;
// TODO(anton): This is probably not correct D3D12 API, but I might have an old SDK.
rtv_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(rtv_heap, &rtv_handle);
for (U32 i = 0; i < 2; ++i) {
r_d3d12_state->swapchain->lpVtbl->GetBuffer(r_d3d12_state->swapchain,
i,
&IID_ID3D12Resource,
(void**)&render_targets[i]);
r_d3d12_state->device->lpVtbl->
CreateRenderTargetView(r_d3d12_state->device,
render_targets[i],
0,
rtv_handle);
rtv_handle.ptr += rtv_descriptor_size;
}
// ---------------------------------------------------------------------------
// Command allocator and command list
ID3D12CommandAllocator* cmd_allocator;
r_d3d12_state->device->lpVtbl->CreateCommandAllocator(r_d3d12_state->device,
D3D12_COMMAND_LIST_TYPE_DIRECT,
&IID_ID3D12CommandAllocator,
(void**)&cmd_allocator);
ID3D12GraphicsCommandList* cmd_list;
r_d3d12_state->device->lpVtbl->CreateCommandList(r_d3d12_state->device,
0,
D3D12_COMMAND_LIST_TYPE_DIRECT,
cmd_allocator,
0,
&IID_ID3D12GraphicsCommandList,
(void**)&cmd_list);
// ---------------------------------------------------------------------------
// Fence and event
ID3D12Fence *fence;
U64 fence_value = 0;
hr = r_d3d12_state->device->lpVtbl->CreateFence(r_d3d12_state->device,
0,
D3D12_FENCE_FLAG_NONE,
&IID_ID3D12Fence,
(void**)&fence);
HANDLE fence_event = CreateEvent(0, FALSE, FALSE, 0);
// Record commands to clear screen
U32 frameIndex = r_d3d12_state->swapchain->lpVtbl->GetCurrentBackBufferIndex(r_d3d12_state->swapchain);
cmd_allocator->lpVtbl->Reset(cmd_allocator);
cmd_list->lpVtbl->Reset(cmd_list, cmd_allocator, 0);
D3D12_RESOURCE_BARRIER barrier = {
.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
.Transition = {
.pResource = render_targets[frameIndex],
.StateBefore = D3D12_RESOURCE_STATE_PRESENT,
.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET,
.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES
}
};
cmd_list->lpVtbl->ResourceBarrier(cmd_list, 1, &barrier);
D3D12_CPU_DESCRIPTOR_HANDLE currentRTV;
// TODO(anton): Probably wrong API due to old SDK...
rtv_heap->lpVtbl->GetCPUDescriptorHandleForHeapStart(rtv_heap, &currentRTV);
currentRTV.ptr += frameIndex * rtv_descriptor_size;
F32 clearColor[4] = {0.1f, 0.2f, 0.3f, 1.0f};
cmd_list->lpVtbl->ClearRenderTargetView(cmd_list, currentRTV, clearColor, 0, 0);
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
cmd_list->lpVtbl->ResourceBarrier(cmd_list, 1, &barrier);
cmd_list->lpVtbl->Close(cmd_list);
// Execute and present
ID3D12CommandList* lists[] = { (ID3D12CommandList*)cmd_list };
command_queue->lpVtbl->ExecuteCommandLists(command_queue, 1, lists);
r_d3d12_state->swapchain->lpVtbl->Present(r_d3d12_state->swapchain, 1, 0);
// Wait for GPU
fence_value++;
command_queue->lpVtbl->Signal(command_queue, fence, fence_value);
if (fence->lpVtbl->GetCompletedValue(fence) < fence_value) {
fence->lpVtbl->SetEventOnCompletion(fence, fence_value, fence_event);
WaitForSingleObject(fence_event, INFINITE);
}
}
//internal void
//r_log_debug_messages()
//{
// if(r_d3d12_state->info_queue)
// {
// UINT64 numMessages = r_d3d12_state->info_queue->lpVtbl->GetNumStoredMessages(r_d3d12_state->info_queue);
// for (UINT64 i = 0; i < numMessages; i++) {
// SIZE_T messageLength = 0;
// r_d3d12_state->info_queue->lpVtbl->GetMessage(r_d3d12_state->info_queue, i, NULL, &messageLength);
//
// D3D12_MESSAGE* message = (D3D12_MESSAGE*)malloc(messageLength);
// if (message) {
// r_d3d12_state->info_queue->lpVtbl->GetMessage(r_d3d12_state->info_queue, i, message, &messageLength);
// LOG("DX12 Debug: %s\n", message->pDescription);
// free(message);
// }
// }
// r_d3d12_state->info_queue->lpVtbl->ClearStoredMessages(r_d3d12_state->info_queue);
// }
//}
internal void
r_trigger_debug_message()
{
@ -114,79 +270,8 @@ r_cleanup()
D3D12_RELEASE(r_d3d12_state->device);
D3D12_RELEASE(r_d3d12_state->debug);
D3D12_RELEASE(r_d3d12_state->swapchain);
arena_release(r_d3d12_state->arena);
}
//internal LRESULT
//r_d3d12_create_swapchain(IDXGIFactory4 *factory)
//{
// LRESULT result = 0;
// HRESULT hr = 0;
//
// // Log window state
// RECT clientRect;
// GetClientRect(g_win32_window_handle, &clientRect);
// LOG("Swap chain creation - Window state: HWND %p, Visible %d, Client area %ldx%ld\n",
// g_win32_window_handle,
// IsWindowVisible(g_win32_window_handle),
// clientRect.right - clientRect.left,
// clientRect.bottom - clientRect.top);
//
// if (!IsWindowVisible(g_win32_window_handle)) {
// LOG("WARNING: Window not visible, attempting to show\n");
// ShowWindow(g_win32_window_handle, SW_SHOW);
// UpdateWindow(g_win32_window_handle);
// }
//
// if (clientRect.right - clientRect.left == 0 || clientRect.bottom - clientRect.top == 0) {
// LOG("ERROR: Window has zero client area\n");
// result = 0;
// Trap();
// }
//
//
// DXGI_SWAP_CHAIN_DESC1 swapDesc = {0};
// swapDesc.Width = WINDOW_WIDTH_PX;
// swapDesc.Height = WINDOW_HEIGHT_PX;
// swapDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
// swapDesc.SampleDesc.Count = 1;
// swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
// swapDesc.BufferCount = 2;
// swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
// swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
//
// LOG("Creating swap chain on service thread: %dx%d\n", swapDesc.Width, swapDesc.Height);
// IDXGISwapChain1* swapChain = 0;
// hr = factory->lpVtbl->CreateSwapChainForHwnd(
// factory,
// (IUnknown*)r_d3d12_state->device,
// g_win32_window_handle,
// &swapDesc,
// 0, 0,
// &swapChain
// );
// if (FAILED(hr)) {
// LOG("Failed to create swap chain in service thread: HRESULT 0x%X\n", hr);
// r_log_debug_messages();
// result = 0;
// } else {
// hr = swapChain->lpVtbl->QueryInterface(
// swapChain,
// &IID_IDXGISwapChain3,
// (void**)&r_d3d12_state->swapchain
// );
// swapChain->lpVtbl->Release(swapChain);
// if (FAILED(hr)) {
// LOG("Failed to query swap chain: HRESULT 0x%X\n", hr);
// r_log_debug_messages();
// Trap();
// result = 0;
// } else {
// result = 1;
// }
// }
//
// return result;
//}