mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-05 06:57:13 +08:00
Add multi-viewports for DX12. (#2851)
(cherry picked from commit 899e48565d1ecefde06063f99c75e702adcef175)
This commit is contained in:
parent
7feccf9ab2
commit
05c1f2795a
@ -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());
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user