Cthulhu  0.2.10
Cthulhu compiler collection
draw.cpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-3.0-only
2 
3 #include "draw/draw.hpp"
4 
5 #include "imgui.h"
6 #include "backends/imgui_impl_win32.h"
7 #include "backends/imgui_impl_dx12.h"
8 
9 #include "implot.h"
10 
11 #include <d3d12.h>
12 #include <dxgi1_4.h>
13 #include <tchar.h>
14 
15 #ifdef _DEBUG
16 #define DX12_ENABLE_DEBUG_LAYER
17 #endif
18 
19 #ifdef DX12_ENABLE_DEBUG_LAYER
20 #include <dxgidebug.h>
21 #pragma comment(lib, "dxguid.lib")
22 #endif
23 
25 {
26  ID3D12CommandAllocator* CommandAllocator;
27  UINT64 FenceValue;
28 };
29 
30 // Data
31 static int const NUM_FRAMES_IN_FLIGHT = 3;
32 static FrameContext g_frameContext[NUM_FRAMES_IN_FLIGHT] = {};
33 static UINT g_frameIndex = 0;
34 
35 static int const NUM_BACK_BUFFERS = 3;
36 static IDXGIAdapter3* g_adapter = nullptr;
37 static ID3D12Device* g_pd3dDevice = nullptr;
38 static ID3D12DescriptorHeap* g_pd3dRtvDescHeap = nullptr;
39 static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = nullptr;
40 static ID3D12CommandQueue* g_pd3dCommandQueue = nullptr;
41 static ID3D12GraphicsCommandList* g_pd3dCommandList = nullptr;
42 static ID3D12Fence* g_fence = nullptr;
43 static HANDLE g_fenceEvent = nullptr;
44 static UINT64 g_fenceLastSignaledValue = 0;
45 static IDXGISwapChain3* g_pSwapChain = nullptr;
46 static HANDLE g_hSwapChainWaitableObject = nullptr;
47 static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
48 static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
49 
50 static WNDCLASSEXW wc;
51 static HWND hwnd;
52 
53 // Forward declarations of helper functions
54 bool CreateDeviceD3D(HWND hWnd);
55 void CleanupDeviceD3D();
56 void CreateRenderTarget();
57 void CleanupRenderTarget();
60 LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
61 
62 // Helper functions
63 bool CreateDeviceD3D(HWND hWnd, bool use_warp_adapter)
64 {
65  // Setup swap chain
66  DXGI_SWAP_CHAIN_DESC1 sd;
67  {
68  ZeroMemory(&sd, sizeof(sd));
69  sd.BufferCount = NUM_BACK_BUFFERS;
70  sd.Width = 0;
71  sd.Height = 0;
72  sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
73  sd.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
74  sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
75  sd.SampleDesc.Count = 1;
76  sd.SampleDesc.Quality = 0;
77  sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
78  sd.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
79  sd.Scaling = DXGI_SCALING_STRETCH;
80  sd.Stereo = FALSE;
81  }
82 
83  // [DEBUG] Enable debug interface
84 #ifdef DX12_ENABLE_DEBUG_LAYER
85  ID3D12Debug* pdx12Debug = nullptr;
86  if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pdx12Debug))))
87  pdx12Debug->EnableDebugLayer();
88 #endif
89 
90  if (use_warp_adapter)
91  {
92  IDXGIFactory4* dxgiFactory = nullptr;
93  if (CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)) != S_OK)
94  return false;
95  if (dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&g_adapter)) != S_OK)
96  return false;
97  dxgiFactory->Release();
98  }
99 
100  // Create device
101  D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
102  if (D3D12CreateDevice(g_adapter, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK)
103  return false;
104 
105  // [DEBUG] Setup debug interface to break on any warnings/errors
106 #ifdef DX12_ENABLE_DEBUG_LAYER
107  if (pdx12Debug != nullptr)
108  {
109  ID3D12InfoQueue* pInfoQueue = nullptr;
110  g_pd3dDevice->QueryInterface(IID_PPV_ARGS(&pInfoQueue));
111  pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true);
112  pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
113  pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true);
114  pInfoQueue->Release();
115  pdx12Debug->Release();
116  }
117 #endif
118 
119  {
120  D3D12_DESCRIPTOR_HEAP_DESC desc = {};
121  desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
122  desc.NumDescriptors = NUM_BACK_BUFFERS;
123  desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
124  desc.NodeMask = 1;
125  if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dRtvDescHeap)) != S_OK)
126  return false;
127 
128  SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
129  D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart();
130  for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
131  {
132  g_mainRenderTargetDescriptor[i] = rtvHandle;
133  rtvHandle.ptr += rtvDescriptorSize;
134  }
135  }
136 
137  {
138  D3D12_DESCRIPTOR_HEAP_DESC desc = {};
139  desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
140  desc.NumDescriptors = 1;
141  desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
142  if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dSrvDescHeap)) != S_OK)
143  return false;
144  }
145 
146  {
147  D3D12_COMMAND_QUEUE_DESC desc = {};
148  desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
149  desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
150  desc.NodeMask = 1;
151  if (g_pd3dDevice->CreateCommandQueue(&desc, IID_PPV_ARGS(&g_pd3dCommandQueue)) != S_OK)
152  return false;
153  }
154 
155  for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
156  if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK)
157  return false;
158 
159  if (g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, g_frameContext[0].CommandAllocator, nullptr, IID_PPV_ARGS(&g_pd3dCommandList)) != S_OK ||
160  g_pd3dCommandList->Close() != S_OK)
161  return false;
162 
163  if (g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&g_fence)) != S_OK)
164  return false;
165 
166  g_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
167  if (g_fenceEvent == nullptr)
168  return false;
169 
170  {
171  IDXGIFactory4* dxgiFactory = nullptr;
172  IDXGISwapChain1* swapChain1 = nullptr;
173  if (CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)) != S_OK)
174  return false;
175  if (dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, nullptr, nullptr, &swapChain1) != S_OK)
176  return false;
177  if (swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain)) != S_OK)
178  return false;
179  swapChain1->Release();
180  dxgiFactory->Release();
181  g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
182  g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
183  }
184 
186  return true;
187 }
188 
190 {
192  if (g_pSwapChain) { g_pSwapChain->SetFullscreenState(false, nullptr); g_pSwapChain->Release(); g_pSwapChain = nullptr; }
193  if (g_hSwapChainWaitableObject != nullptr) { CloseHandle(g_hSwapChainWaitableObject); }
194  for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
195  if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = nullptr; }
196  if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = nullptr; }
197  if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = nullptr; }
198  if (g_pd3dRtvDescHeap) { g_pd3dRtvDescHeap->Release(); g_pd3dRtvDescHeap = nullptr; }
199  if (g_pd3dSrvDescHeap) { g_pd3dSrvDescHeap->Release(); g_pd3dSrvDescHeap = nullptr; }
200  if (g_fence) { g_fence->Release(); g_fence = nullptr; }
201  if (g_fenceEvent) { CloseHandle(g_fenceEvent); g_fenceEvent = nullptr; }
202  if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
203 
204 #ifdef DX12_ENABLE_DEBUG_LAYER
205  IDXGIDebug1* pDebug = nullptr;
206  if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&pDebug))))
207  {
208  pDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_SUMMARY);
209  pDebug->Release();
210  }
211 #endif
212 
213  if (g_adapter) { g_adapter->Release(); g_adapter = nullptr; }
214 }
215 
217 {
218  for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
219  {
220  ID3D12Resource* pBackBuffer = nullptr;
221  g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
222  g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, g_mainRenderTargetDescriptor[i]);
223  g_mainRenderTargetResource[i] = pBackBuffer;
224  }
225 }
226 
228 {
230 
231  for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
232  if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = nullptr; }
233 }
234 
236 {
237  FrameContext* frameCtx = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT];
238 
239  UINT64 fenceValue = frameCtx->FenceValue;
240  if (fenceValue == 0)
241  return; // No fence was signaled
242 
243  frameCtx->FenceValue = 0;
244  if (g_fence->GetCompletedValue() >= fenceValue)
245  return;
246 
247  g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
248  WaitForSingleObject(g_fenceEvent, INFINITE);
249 }
250 
252 {
253  UINT nextFrameIndex = g_frameIndex + 1;
254  g_frameIndex = nextFrameIndex;
255 
256  HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, nullptr };
257  DWORD numWaitableObjects = 1;
258 
259  FrameContext* frameCtx = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT];
260  UINT64 fenceValue = frameCtx->FenceValue;
261  if (fenceValue != 0) // means no fence was signaled
262  {
263  frameCtx->FenceValue = 0;
264  g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
265  waitableObjects[1] = g_fenceEvent;
266  numWaitableObjects = 2;
267  }
268 
269  WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE);
270 
271  return frameCtx;
272 }
273 
274 // Forward declare message handler from imgui_impl_win32.cpp
275 extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
276 
277 // Win32 message handler
278 // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
279 // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
280 // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
281 // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
282 LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
283 {
284  if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
285  return true;
286 
287  switch (msg)
288  {
289  case WM_SIZE:
290  if (g_pd3dDevice != nullptr && wParam != SIZE_MINIMIZED)
291  {
294  HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT);
295  CTASSERT(SUCCEEDED(result) && "Failed to resize swapchain.");
297  }
298  return 0;
299  case WM_SYSCOMMAND:
300  if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
301  return 0;
302  break;
303  case WM_DESTROY:
304  ::PostQuitMessage(0);
305  return 0;
306  }
307  return ::DefWindowProcW(hWnd, msg, wParam, lParam);
308 }
309 
310 bool draw::create(const config_t& config)
311 {
312  // Create application window
313  //ImGui_ImplWin32_EnableDpiAwareness();
314  wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr };
315  ::RegisterClassExW(&wc);
316  hwnd = ::CreateWindowW(wc.lpszClassName, config.title, WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
317 
318  // center window
319  RECT rc;
320  GetWindowRect(hwnd, &rc);
321  int xPos = (GetSystemMetrics(SM_CXSCREEN) - rc.right) / 2;
322  int yPos = (GetSystemMetrics(SM_CYSCREEN) - rc.bottom) / 2;
323  SetWindowPos(hwnd, 0, xPos, yPos, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
324 
325  // Initialize Direct3D
326  if (!CreateDeviceD3D(hwnd, !config.hwaccel))
327  {
329  ::UnregisterClassW(wc.lpszClassName, wc.hInstance);
330  return false;
331  }
332 
333  // Show the window
334  ::ShowWindow(hwnd, SW_SHOWDEFAULT);
335  ::UpdateWindow(hwnd);
336 
337  // Setup Dear ImGui context
338  IMGUI_CHECKVERSION();
339  ImGui::CreateContext();
340  ImGuiIO& io = ImGui::GetIO(); (void)io;
341  io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
342  io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
343  io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
344  io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
345  //io.ConfigViewportsNoAutoMerge = true;
346  //io.ConfigViewportsNoTaskBarIcon = true;
347 
348  ImPlot::CreateContext();
349 
350  // Setup Dear ImGui style
351  ImGui::StyleColorsDark();
352  ImPlot::StyleColorsDark();
353  //ImGui::StyleColorsLight();
354 
355  // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
356  ImGuiStyle& style = ImGui::GetStyle();
357  if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
358  {
359  style.WindowRounding = 0.0f;
360  style.Colors[ImGuiCol_WindowBg].w = 1.0f;
361  }
362 
363  // Setup Platform/Renderer backends
364  ImGui_ImplWin32_Init(hwnd);
365  ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT,
366  DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap,
367  g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(),
368  g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart());
369 
370  // Load Fonts
371  // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
372  // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
373  // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
374  // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
375  // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
376  // - Read 'docs/FONTS.md' for more instructions and details.
377  // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
378  //io.Fonts->AddFontDefault();
379  //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
380  //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
381  //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
382  //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
383  //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
384  //IM_ASSERT(font != nullptr);
385 
386  return true;
387 }
388 
390 {
392 
393  // Cleanup
394  ImGui_ImplDX12_Shutdown();
395  ImGui_ImplWin32_Shutdown();
396  ImPlot::DestroyContext();
397  ImGui::DestroyContext();
398 
400  ::DestroyWindow(hwnd);
401  ::UnregisterClassW(wc.lpszClassName, wc.hInstance);
402 }
403 
405 {
406  // Poll and handle messages (inputs, window resize, etc.)
407  // See the WndProc() function below for our to dispatch events to the Win32 backend.
408  MSG msg;
409  bool done = false;
410  while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
411  {
412  ::TranslateMessage(&msg);
413  ::DispatchMessage(&msg);
414  if (msg.message == WM_QUIT)
415  done = true;
416  }
417  if (done)
418  return false;
419 
420  // Start the Dear ImGui frame
421  ImGui_ImplDX12_NewFrame();
422  ImGui_ImplWin32_NewFrame();
423  ImGui::NewFrame();
424 
425  return true;
426 }
427 
429 {
430  ::PostMessage(hwnd, WM_CLOSE, 0, 0);
431 }
432 
434 {
435  ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
436 
437  // Rendering
438  ImGui::Render();
439 
441  UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex();
442  frameCtx->CommandAllocator->Reset();
443 
444  D3D12_RESOURCE_BARRIER barrier = {};
445  barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
446  barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
447  barrier.Transition.pResource = g_mainRenderTargetResource[backBufferIdx];
448  barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
449  barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
450  barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
451  g_pd3dCommandList->Reset(frameCtx->CommandAllocator, nullptr);
452  g_pd3dCommandList->ResourceBarrier(1, &barrier);
453 
454  // Render Dear ImGui graphics
455  const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
456  g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], clear_color_with_alpha, 0, nullptr);
457  g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, nullptr);
458  g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap);
459  ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), g_pd3dCommandList);
460  barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
461  barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
462  g_pd3dCommandList->ResourceBarrier(1, &barrier);
463  g_pd3dCommandList->Close();
464 
465  g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList);
466 
467  ImGuiIO& io = ImGui::GetIO();
468 
469  // Update and Render additional Platform Windows
470  if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
471  {
472  ImGui::UpdatePlatformWindows();
473  ImGui::RenderPlatformWindowsDefault(nullptr, (void*)g_pd3dCommandList);
474  }
475 
476  g_pSwapChain->Present(1, 0); // Present with vsync
477  //g_pSwapChain->Present(0, 0); // Present without vsync
478 
479  UINT64 fenceValue = g_fenceLastSignaledValue + 1;
480  g_pd3dCommandQueue->Signal(g_fence, fenceValue);
481  g_fenceLastSignaledValue = fenceValue;
482  frameCtx->FenceValue = fenceValue;
483 }
FrameContext * WaitForNextFrameResources()
Definition: draw.cpp:251
void CleanupRenderTarget()
Definition: draw.cpp:227
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
bool CreateDeviceD3D(HWND hWnd)
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: draw.cpp:282
void CreateRenderTarget()
Definition: draw.cpp:216
void CleanupDeviceD3D()
Definition: draw.cpp:189
void WaitForLastSubmittedFrame()
Definition: draw.cpp:235
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
bool create(const config_t &config)
Definition: draw.cpp:310
void end_frame()
Definition: draw.cpp:433
void close()
Definition: draw.cpp:428
bool begin_frame()
Definition: draw.cpp:404
void destroy()
Definition: draw.cpp:389
ID3D12CommandAllocator * CommandAllocator
Definition: draw.cpp:26
UINT64 FenceValue
Definition: draw.cpp:27
const wchar_t * title
Definition: draw.hpp:7
bool hwaccel
Definition: draw.hpp:8