Add multi-viewports for DX12. (#2851)

(cherry picked from commit 899e48565d1ecefde06063f99c75e702adcef175)
This commit is contained in:
Ilya.Sevrikov 2019-10-17 16:53:43 +03:00 committed by omar
parent 7feccf9ab2
commit 05c1f2795a
3 changed files with 263 additions and 100 deletions

View File

@ -73,7 +73,7 @@ int main(int, char**)
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows (FIXME: Currently broken in DX12 back-end, need some work!) io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigViewportsNoAutoMerge = true; //io.ConfigViewportsNoAutoMerge = true;
//io.ConfigViewportsNoTaskBarIcon = true; //io.ConfigViewportsNoTaskBarIcon = true;
@ -92,7 +92,7 @@ int main(int, char**)
// Setup Platform/Renderer bindings // Setup Platform/Renderer bindings
ImGui_ImplWin32_Init(hwnd); ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT, ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT,
DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap,
g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(),
g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart());

View File

@ -4,8 +4,8 @@
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// [X] Renderer: Multi-viewport.
// Missing features, issues: // Missing features, issues:
// [ ] Renderer: Missing multi-viewport support.
// [ ] 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)). See github.com/ocornut/imgui/pull/301 // [ ] 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)). See github.com/ocornut/imgui/pull/301
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
@ -46,6 +46,8 @@ static ID3D12Resource* g_pFontTextureResource = NULL;
static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {}; static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {};
static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {}; static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {};
static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = NULL;
struct FrameResources struct FrameResources
{ {
ID3D12Resource* IndexBuffer; ID3D12Resource* IndexBuffer;
@ -53,9 +55,80 @@ struct FrameResources
int IndexBufferSize; int IndexBufferSize;
int VertexBufferSize; int VertexBufferSize;
}; };
static FrameResources* g_pFrameResources = NULL;
static UINT g_numFramesInFlight = 0; static UINT g_numFramesInFlight = 0;
static UINT g_frameIndex = UINT_MAX;
struct FrameContext
{
ID3D12CommandAllocator* CommandAllocator;
UINT64 FenceValue;
ID3D12Resource* RenderTarget;
D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetCpuDescriptors;
};
struct ImGuiViewportDataDx12
{
ID3D12CommandQueue* CommandQueue;
ID3D12GraphicsCommandList* CommandList;
ID3D12DescriptorHeap* RtvDescHeap;
IDXGISwapChain3* SwapChain;
ID3D12Fence* Fence;
UINT64 FenceSignaledValue;
HANDLE FenceEvent;
FrameContext* FrameCtx;
FrameResources* Resources;
UINT FrameIndex;
ImGuiViewportDataDx12()
{
CommandQueue = NULL;
CommandList = NULL;
RtvDescHeap = NULL;
SwapChain = NULL;
FenceSignaledValue = 0;
Fence = NULL;
FenceEvent = NULL;
FrameIndex = UINT_MAX;
FrameCtx = new FrameContext[g_numFramesInFlight];
Resources = new FrameResources[g_numFramesInFlight];
for (UINT i = 0; i < g_numFramesInFlight; ++i)
{
FrameCtx[i].CommandAllocator = NULL;
FrameCtx[i].RenderTarget = NULL;
// Create buffers with a default size (they will later be grown as needed)
Resources[i].IndexBuffer = NULL;
Resources[i].VertexBuffer = NULL;
Resources[i].VertexBufferSize = 5000;
Resources[i].IndexBufferSize = 10000;
}
}
~ImGuiViewportDataDx12()
{
IM_ASSERT(CommandQueue == NULL && CommandList == NULL);
IM_ASSERT(RtvDescHeap == NULL);
IM_ASSERT(SwapChain == NULL);
IM_ASSERT(Fence == NULL);
IM_ASSERT(FenceEvent == NULL);
for (UINT i = 0; i < g_numFramesInFlight; ++i)
{
IM_ASSERT(FrameCtx[i].CommandAllocator == NULL && FrameCtx[i].RenderTarget == NULL);
IM_ASSERT(Resources[i].IndexBuffer == NULL && Resources[i].VertexBuffer == NULL);
}
delete[] FrameCtx; FrameCtx = NULL;
delete[] Resources; Resources = NULL;
}
};
struct VERTEX_CONSTANT_BUFFER struct VERTEX_CONSTANT_BUFFER
{ {
@ -129,10 +202,9 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return; return;
// FIXME: I'm assuming that this only gets called once per frame! ImGuiViewportDataDx12* render_data = (ImGuiViewportDataDx12*)draw_data->OwnerViewport->RendererUserData;
// If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. render_data->FrameIndex++;
g_frameIndex = g_frameIndex + 1; FrameResources* fr = &render_data->Resources[render_data->FrameIndex % g_numFramesInFlight];
FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight];
// Create and grow vertex/index buffers if needed // Create and grow vertex/index buffers if needed
if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount) if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
@ -599,15 +671,9 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
if (g_pRootSignature) { g_pRootSignature->Release(); g_pRootSignature = NULL; } if (g_pRootSignature) { g_pRootSignature->Release(); g_pRootSignature = NULL; }
if (g_pPipelineState) { g_pPipelineState->Release(); g_pPipelineState = NULL; } if (g_pPipelineState) { g_pPipelineState->Release(); g_pPipelineState = NULL; }
if (g_pFontTextureResource) { g_pFontTextureResource->Release(); g_pFontTextureResource = NULL; io.Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. if (g_pFontTextureResource) { g_pFontTextureResource->Release(); g_pFontTextureResource = NULL; io.Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
FrameResources* fr = &g_pFrameResources[i];
if (fr->IndexBuffer) { fr->IndexBuffer->Release(); fr->IndexBuffer = NULL; }
if (fr->VertexBuffer) { fr->VertexBuffer->Release(); fr->VertexBuffer = NULL; }
}
} }
bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
{ {
// Setup back-end capabilities flags // Setup back-end capabilities flags
@ -620,20 +686,14 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
g_RTVFormat = rtv_format; g_RTVFormat = rtv_format;
g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle; g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle;
g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle; g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle;
g_pFrameResources = new FrameResources[num_frames_in_flight];
g_numFramesInFlight = num_frames_in_flight; g_numFramesInFlight = num_frames_in_flight;
g_frameIndex = UINT_MAX; g_pd3dSrvDescHeap = cbv_srv_heap;
// Create buffers with a default size (they will later be grown as needed) ImGuiViewport* main_viewport = ImGui::GetMainViewport();
for (int i = 0; i < num_frames_in_flight; i++) main_viewport->RendererUserData = IM_NEW(ImGuiViewportDataDx12);
{
FrameResources* fr = &g_pFrameResources[i];
fr->IndexBuffer = NULL;
fr->VertexBuffer = NULL;
fr->IndexBufferSize = 10000;
fr->VertexBufferSize = 5000;
}
// Setup back-end capabilities flags
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
ImGui_ImplDX12_InitPlatformInterface(); ImGui_ImplDX12_InitPlatformInterface();
@ -644,13 +704,17 @@ void ImGui_ImplDX12_Shutdown()
{ {
ImGui_ImplDX12_ShutdownPlatformInterface(); ImGui_ImplDX12_ShutdownPlatformInterface();
ImGui_ImplDX12_InvalidateDeviceObjects(); ImGui_ImplDX12_InvalidateDeviceObjects();
delete[] g_pFrameResources;
g_pFrameResources = NULL;
g_pd3dDevice = NULL; g_pd3dDevice = NULL;
g_hFontSrvCpuDescHandle.ptr = 0; g_hFontSrvCpuDescHandle.ptr = 0;
g_hFontSrvGpuDescHandle.ptr = 0; g_hFontSrvGpuDescHandle.ptr = 0;
g_numFramesInFlight = 0; g_numFramesInFlight = 0;
g_frameIndex = UINT_MAX; g_pd3dSrvDescHeap = NULL;
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
if (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)main_viewport->RendererUserData)
IM_DELETE(data);
main_viewport->RendererUserData = NULL;
} }
void ImGui_ImplDX12_NewFrame() void ImGui_ImplDX12_NewFrame()
@ -665,54 +729,118 @@ void ImGui_ImplDX12_NewFrame()
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first.. // If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//-------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------
struct ImGuiViewportDataDx12
{
IDXGISwapChain3* SwapChain;
ImGuiViewportDataDx12() { SwapChain = NULL; }
~ImGuiViewportDataDx12() { IM_ASSERT(SwapChain == NULL); }
};
static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport) static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
{ {
ImGuiViewportDataDx12* data = IM_NEW(ImGuiViewportDataDx12)(); ImGuiViewportDataDx12* data = IM_NEW(ImGuiViewportDataDx12)();
viewport->RendererUserData = data; viewport->RendererUserData = data;
IM_ASSERT(0);
/*
// FIXME-PLATFORM
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*). // PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
// Some back-ends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND. // Some back-ends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle; HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
IM_ASSERT(hwnd != 0); IM_ASSERT(hwnd != 0);
data->FrameIndex = UINT_MAX;
// Create command queue.
D3D12_COMMAND_QUEUE_DESC queue_desc = {};
queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
HRESULT res = S_OK;
res = g_pd3dDevice->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&data->CommandQueue));
IM_ASSERT(res == S_OK);
// Create command allocator.
for (UINT i = 0; i < g_numFramesInFlight; ++i)
{
res = g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&data->FrameCtx[i].CommandAllocator));
IM_ASSERT(res == S_OK);
}
// Create command list.
res = g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, data->FrameCtx[0].CommandAllocator, NULL, IID_PPV_ARGS(&data->CommandList));
IM_ASSERT(res == S_OK);
data->CommandList->Close();
// Create fence.
res = g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&data->Fence));
IM_ASSERT(res == S_OK);
data->FenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
IM_ASSERT(data->FenceEvent != NULL);
// Create swap chain // Create swap chain
DXGI_SWAP_CHAIN_DESC sd; DXGI_SWAP_CHAIN_DESC1 sd1;
ZeroMemory(&sd, sizeof(sd)); ZeroMemory(&sd1, sizeof(sd1));
sd.BufferDesc.Width = (UINT)viewport->Size.x; sd1.BufferCount = g_numFramesInFlight;
sd.BufferDesc.Height = (UINT)viewport->Size.y; sd1.Width = (UINT)viewport->Size.x;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd1.Height = (UINT)viewport->Size.y;
sd.SampleDesc.Count = 1; sd1.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.SampleDesc.Quality = 0; sd1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd1.SampleDesc.Count = 1;
sd.BufferCount = 1; sd1.SampleDesc.Quality = 0;
sd.OutputWindow = hwnd; sd1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd.Windowed = TRUE; sd1.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd1.Scaling = DXGI_SCALING_STRETCH;
sd.Flags = 0; sd1.Stereo = FALSE;
IM_ASSERT(data->SwapChain == NULL && data->RTView == NULL); IM_ASSERT(data->SwapChain == NULL);
g_pFactory->CreateSwapChain(g_pd3dDevice, &sd, &data->SwapChain); IM_ASSERT(data->FrameCtx[0].RenderTarget == NULL && data->FrameCtx[1].RenderTarget == NULL && data->FrameCtx[2].RenderTarget == NULL);
// Create the render target IDXGIFactory4* dxgi_factory = nullptr;
res = CreateDXGIFactory1(IID_PPV_ARGS(&dxgi_factory));
IM_ASSERT(res == S_OK);
IDXGISwapChain1* swap_chain = nullptr;
res = dxgi_factory->CreateSwapChainForHwnd(data->CommandQueue, hwnd, &sd1, NULL, NULL, &swap_chain);
IM_ASSERT(res == S_OK);
dxgi_factory->Release();
// Or swapChain.As(&mSwapChain)
swap_chain->QueryInterface(IID_PPV_ARGS(&data->SwapChain));
// Create the render targets
if (data->SwapChain) if (data->SwapChain)
{ {
ID3D11Texture2D* pBackBuffer; D3D12_DESCRIPTOR_HEAP_DESC desc = {};
data->SwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &data->RTView); desc.NumDescriptors = g_numFramesInFlight;
pBackBuffer->Release(); desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
desc.NodeMask = 1;
IM_ASSERT(g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&data->RtvDescHeap)) == S_OK);
SIZE_T rtv_descriptor_size = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle = data->RtvDescHeap->GetCPUDescriptorHandleForHeapStart();
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
data->FrameCtx[i].RenderTargetCpuDescriptors = rtv_handle;
rtv_handle.ptr += rtv_descriptor_size;
} }
*/
ID3D12Resource* back_buffer;
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
data->SwapChain->GetBuffer(i, IID_PPV_ARGS(&back_buffer));
g_pd3dDevice->CreateRenderTargetView(back_buffer, NULL, data->FrameCtx[i].RenderTargetCpuDescriptors);
data->FrameCtx[i].RenderTarget = back_buffer;
}
}
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
if (data->Resources[i].IndexBuffer) { data->Resources[i].VertexBuffer->Release(); data->Resources[i].IndexBuffer = NULL; }
if (data->Resources[i].VertexBuffer) { data->Resources[i].VertexBuffer->Release(); data->Resources[i].VertexBuffer = NULL; }
}
}
template<typename D12Resource>
void SafeRelease(D12Resource*& res)
{
if (res)
res->Release();
res = NULL;
} }
static void ImGui_ImplDX12_DestroyWindow(ImGuiViewport* viewport) static void ImGui_ImplDX12_DestroyWindow(ImGuiViewport* viewport)
@ -720,16 +848,22 @@ static void ImGui_ImplDX12_DestroyWindow(ImGuiViewport* viewport)
// The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it. // The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
if (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData) if (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData)
{ {
IM_ASSERT(0); SafeRelease(data->CommandQueue);
/* SafeRelease(data->CommandList);
if (data->SwapChain) SafeRelease(data->SwapChain);
data->SwapChain->Release(); SafeRelease(data->RtvDescHeap);
data->SwapChain = NULL; SafeRelease(data->Fence);
if (data->RTView) CloseHandle(data->FenceEvent); data->FenceEvent = NULL;
data->RTView->Release();
data->RTView = NULL; for (UINT i = 0; i < g_numFramesInFlight; i++)
{
SafeRelease(data->FrameCtx[i].RenderTarget);
SafeRelease(data->FrameCtx[i].CommandAllocator);
SafeRelease(data->Resources[i].IndexBuffer);
SafeRelease(data->Resources[i].VertexBuffer);
}
IM_DELETE(data); IM_DELETE(data);
*/
} }
viewport->RendererUserData = NULL; viewport->RendererUserData = NULL;
} }
@ -737,51 +871,79 @@ static void ImGui_ImplDX12_DestroyWindow(ImGuiViewport* viewport)
static void ImGui_ImplDX12_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) static void ImGui_ImplDX12_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{ {
ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData; ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData;
IM_ASSERT(0);
(void)data; (void)size; for (UINT i = 0; i < g_numFramesInFlight; i++)
/*
if (data->RTView)
{ {
data->RTView->Release(); SafeRelease(data->FrameCtx[i].RenderTarget);
data->RTView = NULL;
} }
if (data->SwapChain) if (data->SwapChain)
{ {
ID3D11Texture2D* pBackBuffer = NULL; ID3D12Resource* back_buffer = NULL;
data->SwapChain->ResizeBuffers(0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0); data->SwapChain->ResizeBuffers(0, (UINT)size.x, (UINT)size.y, DXGI_FORMAT_UNKNOWN, 0);
data->SwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); for (UINT i = 0; i < g_numFramesInFlight; i++)
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &data->RTView); {
pBackBuffer->Release(); data->SwapChain->GetBuffer(i, IID_PPV_ARGS(&back_buffer));
g_pd3dDevice->CreateRenderTargetView(back_buffer, NULL, data->FrameCtx[i].RenderTargetCpuDescriptors);
data->FrameCtx[i].RenderTarget = back_buffer;
}
} }
*/
} }
// arg = ID3D12GraphicsCommandList* static void ImGui_ImplDX12_RenderWindow(ImGuiViewport* viewport, void*)
static void ImGui_ImplDX12_RenderWindow(ImGuiViewport* viewport, void* renderer_arg)
{ {
ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData; ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData;
IM_ASSERT(0);
(void)data;
ID3D12GraphicsCommandList* command_list = (ID3D12GraphicsCommandList*)renderer_arg;
/*
ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
g_pd3dDeviceContext->OMSetRenderTargets(1, &data->RTView, NULL);
//--
FrameContext* frame_context = &data->FrameCtx[data->FrameIndex % g_numFramesInFlight];
UINT back_buffer_idx = data->SwapChain->GetCurrentBackBufferIndex();
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = data->FrameCtx[back_buffer_idx].RenderTarget;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
//-- draw
ID3D12GraphicsCommandList* cmd_list = data->CommandList;
frame_context->CommandAllocator->Reset();
cmd_list->Reset(frame_context->CommandAllocator, NULL);
cmd_list->ResourceBarrier(1, &barrier);
cmd_list->OMSetRenderTargets(1, &data->FrameCtx[back_buffer_idx].RenderTargetCpuDescriptors, FALSE, NULL);
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear)) if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
g_pd3dDeviceContext->ClearRenderTargetView(data->RTView, (float*)&clear_color); cmd_list->ClearRenderTargetView(data->FrameCtx[back_buffer_idx].RenderTargetCpuDescriptors, (float*)&clear_color, 0, NULL);
*/ cmd_list->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap);
ImGui_ImplDX12_RenderDrawData(viewport->DrawData, command_list);
ImGui_ImplDX12_RenderDrawData(viewport->DrawData, cmd_list);
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
cmd_list->ResourceBarrier(1, &barrier);
cmd_list->Close();
//--
data->CommandQueue->Wait(data->Fence, data->FenceSignaledValue);
//--
data->CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmd_list);
//--
data->CommandQueue->Signal(data->Fence, ++data->FenceSignaledValue);
} }
static void ImGui_ImplDX12_SwapBuffers(ImGuiViewport* viewport, void*) static void ImGui_ImplDX12_SwapBuffers(ImGuiViewport* viewport, void*)
{ {
ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData; ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData;
IM_ASSERT(0);
(void)data; data->SwapChain->Present(0, 0);
/*
data->SwapChain->Present(0, 0); // Present without vsync while (data->Fence->GetCompletedValue() < data->FenceSignaledValue)
*/ {
SwitchToThread();
}
} }
void ImGui_ImplDX12_InitPlatformInterface() void ImGui_ImplDX12_InitPlatformInterface()

View File

@ -4,8 +4,8 @@
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// [X] Renderer: Multi-viewport.
// Missing features, issues: // Missing features, issues:
// [ ] Renderer: Missing multi-viewport support.
// [ ] 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)). See github.com/ocornut/imgui/pull/301 // [ ] 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)). See github.com/ocornut/imgui/pull/301
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
@ -16,6 +16,7 @@
enum DXGI_FORMAT; enum DXGI_FORMAT;
struct ID3D12Device; struct ID3D12Device;
struct ID3D12DescriptorHeap;
struct ID3D12GraphicsCommandList; struct ID3D12GraphicsCommandList;
struct D3D12_CPU_DESCRIPTOR_HANDLE; struct D3D12_CPU_DESCRIPTOR_HANDLE;
struct D3D12_GPU_DESCRIPTOR_HANDLE; struct D3D12_GPU_DESCRIPTOR_HANDLE;
@ -24,7 +25,7 @@ struct D3D12_GPU_DESCRIPTOR_HANDLE;
// Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate // Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate
// render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle. // render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle.
// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture. // font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture.
IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown(); IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown();
IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame(); IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame();