diff --git a/anton_render.raddb_proj b/anton_render.raddb_proj new file mode 100644 index 0000000..da69b92 --- /dev/null +++ b/anton_render.raddb_proj @@ -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 +} diff --git a/src/main.c b/src/main.c index 6118f8f..e5e987c 100644 --- a/src/main.c +++ b/src/main.c @@ -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 diff --git a/src/render/d3d12/render_d3d12.c b/src/render/d3d12/render_d3d12.c index 5c70bca..6bff732 100644 --- a/src/render/d3d12/render_d3d12.c +++ b/src/render/d3d12/render_d3d12.c @@ -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 ) { @@ -37,41 +39,195 @@ 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, ¤tRTV); + 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; -//} \ No newline at end of file