diff --git a/examples/directx12_example/directx12_example.vcxproj b/examples/directx12_example/directx12_example.vcxproj
new file mode 100644
index 000000000000..418959bab6a2
--- /dev/null
+++ b/examples/directx12_example/directx12_example.vcxproj
@@ -0,0 +1,162 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {DD502977-4B3C-459F-9CA0-A0E75937EA6E}
+ Win32Proj
+ directx12_example
+ 8.1
+
+
+
+ Application
+ true
+ v140
+ Unicode
+
+
+ Application
+ false
+ v140
+ true
+ Unicode
+
+
+ Application
+ true
+ v140
+ Unicode
+
+
+ Application
+ false
+ v140
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ true
+ ..\..;%(AdditionalIncludeDirectories);C:\Program Files (x86)\Windows Kits\10\Include\10.0.10158.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.10158.0\shared
+
+
+ Console
+ true
+ d3dcompiler.lib;dxgi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _DEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ true
+ ..\..;%(AdditionalIncludeDirectories);C:\Program Files (x86)\Windows Kits\10\Include\10.0.10158.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.10158.0\shared
+
+
+ Console
+ true
+ true
+ true
+ d3dcompiler.lib;dxgi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/directx12_example/directx12_example.vcxproj.filters b/examples/directx12_example/directx12_example.vcxproj.filters
new file mode 100644
index 000000000000..9b32ceebfdb2
--- /dev/null
+++ b/examples/directx12_example/directx12_example.vcxproj.filters
@@ -0,0 +1,30 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp
new file mode 100644
index 000000000000..ffba2a99d1a0
--- /dev/null
+++ b/examples/directx12_example/imgui_impl_dx12.cpp
@@ -0,0 +1,472 @@
+#include "imgui.h"
+#include "imgui_impl_dx12.h"
+
+#include
+
+#include
+#include
+#include
+
+ID3D12GraphicsCommandList* g_commandList;
+D3D12_CPU_DESCRIPTOR_HANDLE g_renderTarget;
+ID3D12Resource* g_uploadBuffer;
+ID3D12PipelineState* g_pipelineState;
+
+// Data
+static INT64 g_Time = 0;
+static INT64 g_TicksPerSecond = 0;
+static HWND g_hwnd;
+
+
+// dxgi, device, cmd queue, cmd allocator
+// command lists genereation with vsh,psh
+#define IMGUI_GPU_BUFFER_SIZE 1024*1024
+
+// For creation of resources in the GPU
+struct HeapProperty
+{
+ enum Enum
+ {
+ Default,
+ Upload,
+ ReadBack,
+
+ Count
+ };
+
+ D3D12_HEAP_PROPERTIES m_properties;
+ D3D12_RESOURCE_STATES m_state;
+};
+
+static const HeapProperty s_heapProperties[] =
+{
+ { { D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 1, 1 }, D3D12_RESOURCE_STATE_COMMON },
+ { { D3D12_HEAP_TYPE_UPLOAD, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 1, 1 }, D3D12_RESOURCE_STATE_GENERIC_READ },
+ { { D3D12_HEAP_TYPE_READBACK, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 1, 1 }, D3D12_RESOURCE_STATE_COPY_DEST },
+};
+
+static ID3D12Resource* createCommittedResource(ID3D12Device* _device, HeapProperty::Enum _heapProperty, D3D12_RESOURCE_DESC* _resourceDesc, D3D12_CLEAR_VALUE* _clearValue)
+{
+ const HeapProperty& heapProperty = s_heapProperties[_heapProperty];
+ ID3D12Resource* resource;
+ _device->CreateCommittedResource(&heapProperty.m_properties
+ , D3D12_HEAP_FLAG_NONE
+ , _resourceDesc
+ , heapProperty.m_state
+ , _clearValue
+ , __uuidof(ID3D12Resource)
+ , (void**)&resource
+ );
+
+ return resource;
+}
+
+static ID3D12Resource* createCommittedResource(ID3D12Device* _device, HeapProperty::Enum _heapProperty, uint64_t _size, D3D12_RESOURCE_FLAGS _flags = D3D12_RESOURCE_FLAG_NONE)
+{
+ D3D12_RESOURCE_DESC resourceDesc;
+ resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ resourceDesc.Alignment = 0;
+ resourceDesc.Width = _size;
+ resourceDesc.Height = 1;
+ resourceDesc.DepthOrArraySize = 1;
+ resourceDesc.MipLevels = 1;
+ resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
+ resourceDesc.SampleDesc.Count = 1;
+ resourceDesc.SampleDesc.Quality = 0;
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ resourceDesc.Flags = _flags;
+
+ return createCommittedResource(_device, _heapProperty, &resourceDesc, NULL);
+}
+
+static void setResourceBarrier(ID3D12GraphicsCommandList* _commandList, ID3D12Resource* _resource, D3D12_RESOURCE_STATES _stateBefore, D3D12_RESOURCE_STATES _stateAfter)
+{
+ D3D12_RESOURCE_BARRIER barrier;
+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier.Transition.pResource = _resource;
+ barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ barrier.Transition.StateBefore = _stateBefore;
+ barrier.Transition.StateAfter = _stateAfter;
+ _commandList->ResourceBarrier(1, &barrier);
+}
+
+void ImGui_ImplDX12_CreateDeviceObjects(ID3D12Device* _device
+ , ID3D12GraphicsCommandList* _commandList
+ , ID3D12CommandQueue* _commandQueue
+ , ID3D12Fence* _fence
+ , D3D12_CPU_DESCRIPTOR_HANDLE _srvHandle
+ , ID3D12RootSignature* _rootSignature)
+
+{
+ static const char* vertexShader =
+ "cbuffer vertexBuffer : register(b0) \
+ {\
+ float4x4 ProjectionMatrix; \
+ };\
+ struct VS_INPUT\
+ {\
+ float2 pos : POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ PS_INPUT main(VS_INPUT input)\
+ {\
+ PS_INPUT output;\
+ output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
+ output.col = input.col;\
+ output.uv = input.uv;\
+ return output;\
+ }";
+
+ static const char* pixelShader =
+ "struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ SamplerState sampler0 : register(s0);\
+ Texture2D texture0 : register(t0);\
+ \
+ float4 main(PS_INPUT input) : SV_Target\
+ {\
+ float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
+ return out_col; \
+ }";
+
+ ID3DBlob* vshBlob = 0;
+ ID3DBlob* pshBlob = 0;
+ ID3DBlob* errorBlob = 0;
+
+ // Define the vertex input layout.
+ D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ };
+
+
+ D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", D3DCOMPILE_DEBUG, 0, &vshBlob, &errorBlob);
+ D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", D3DCOMPILE_DEBUG, 0, &pshBlob, &errorBlob);
+
+ D3D12_RASTERIZER_DESC rasterizerDesc = {};
+ rasterizerDesc.FillMode = D3D12_FILL_MODE_SOLID;
+ rasterizerDesc.CullMode = D3D12_CULL_MODE_NONE;
+ rasterizerDesc.FrontCounterClockwise = true;
+ rasterizerDesc.DepthBias = 0;
+ rasterizerDesc.DepthBiasClamp = 0.f;
+ rasterizerDesc.SlopeScaledDepthBias = 0.f;
+ rasterizerDesc.DepthClipEnable = true;
+ rasterizerDesc.MultisampleEnable = false;
+ rasterizerDesc.AntialiasedLineEnable = true;
+ rasterizerDesc.ForcedSampleCount = 1;
+ rasterizerDesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+
+ D3D12_BLEND_DESC blendDesc;
+ blendDesc.AlphaToCoverageEnable = false;
+ blendDesc.IndependentBlendEnable = false;
+ blendDesc.RenderTarget[0].BlendEnable = true;
+ blendDesc.RenderTarget[0].LogicOpEnable = false;
+ blendDesc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
+ blendDesc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
+ blendDesc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
+ blendDesc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
+ blendDesc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
+ blendDesc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
+ blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+
+ // Create the graphics pipeline state object (PSO).
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
+ psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
+ psoDesc.pRootSignature = _rootSignature;
+ psoDesc.VS = { (uint8_t*)(vshBlob->GetBufferPointer()), vshBlob->GetBufferSize() };
+ psoDesc.PS = { (uint8_t*)(pshBlob->GetBufferPointer()), pshBlob->GetBufferSize() };
+ psoDesc.RasterizerState = rasterizerDesc;
+ psoDesc.BlendState = blendDesc;
+ psoDesc.DepthStencilState.DepthEnable = FALSE;
+ psoDesc.DepthStencilState.StencilEnable = FALSE;
+ psoDesc.SampleMask = UINT_MAX;
+ psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ psoDesc.NumRenderTargets = 1;
+ psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
+ psoDesc.SampleDesc.Count = 1;
+ _device->CreateGraphicsPipelineState(&psoDesc, __uuidof(ID3D12PipelineState), (void**)&g_pipelineState);
+
+ // Create upload ring buffer, which we'll also use as staging buffer for the texture
+ g_uploadBuffer = createCommittedResource(_device, HeapProperty::Upload, IMGUI_GPU_BUFFER_SIZE * 8);
+
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ srvDesc.Texture2D.MipLevels = 1;
+ srvDesc.Texture2D.PlaneSlice = 0;
+ srvDesc.Texture2D.ResourceMinLODClamp = 0.f;
+
+ // Create fonts texture and SRV descriptor for it
+ unsigned char* pixels = 0;
+ int width, height;
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // Create fonts texture
+ D3D12_RESOURCE_DESC desc;
+ desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ desc.Alignment = 0;
+ desc.Width = width;
+ desc.Height = height;
+ desc.DepthOrArraySize = 1;
+ desc.MipLevels = 1;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ ID3D12Resource* fontResource = createCommittedResource(_device, HeapProperty::Default, &desc, 0);
+
+ // Upload the fonts texture
+ uint32_t subres = 0;
+ uint32_t numRows;
+ uint64_t rowPitch;
+ uint64_t totalBytes;
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;
+ _device->GetCopyableFootprints(&desc
+ , subres
+ , 1
+ , 0
+ , &layout
+ , &numRows
+ , &rowPitch
+ , &totalBytes
+ );
+
+ uint8_t* mappedBuffer;
+
+ // Upload the font
+ g_uploadBuffer->Map(0, NULL, (void**)&mappedBuffer);
+ memcpy(mappedBuffer, pixels, (size_t)totalBytes);
+ g_uploadBuffer->Unmap(0, NULL);
+
+ D3D12_BOX box;
+ box.left = 0;
+ box.top = 0;
+ box.right = (UINT)desc.Width;
+ box.bottom = (UINT)desc.Height;
+ box.front = 0;
+ box.back = 1;
+
+ D3D12_TEXTURE_COPY_LOCATION dst = { fontResource, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, { subres } };
+ D3D12_TEXTURE_COPY_LOCATION src = { g_uploadBuffer, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, layout };
+ _commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, &box);
+ _commandList->Close();
+
+ ID3D12CommandList* ppCommandLists[] = { _commandList };
+ _commandQueue->ExecuteCommandLists(1, ppCommandLists);
+ _commandQueue->Signal(_fence, 0);
+
+ _device->CreateShaderResourceView(fontResource, &srvDesc, _srvHandle);
+}
+
+void ImGui_ImplDX12_SetRenderData(ID3D12GraphicsCommandList* _commandList, D3D12_CPU_DESCRIPTOR_HANDLE _renderTarget)
+{
+ g_commandList = _commandList;
+ g_renderTarget = _renderTarget;
+}
+
+void ImGui_ImplDX12_RenderDrawLists(ImDrawData* _draw_data)
+{
+ // Range CPU will read from mapping the upload buffer
+ // End < Begin specifies CPU will not read the mapped buffer
+ D3D12_RANGE readRange;
+ readRange.End = 0;
+ readRange.Begin = 1;
+
+ char* mappedBuffer = 0;
+ g_uploadBuffer->Map(0, &readRange, (void**)&mappedBuffer);
+ if (mappedBuffer == NULL)
+ return;
+
+ char* writeCursor = mappedBuffer;
+
+ // Copy the projection matrix at the beginning of the buffer
+ {
+ float translate = -0.5f * 2.f;
+ const float L = 0.f;
+ const float R = ImGui::GetIO().DisplaySize.x;
+ const float B = ImGui::GetIO().DisplaySize.y;
+ const float T = 0.f;
+ const float mvp[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f},
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f,},
+ { 0.0f, 0.0f, 0.5f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
+ };
+
+ memcpy(writeCursor, &mvp[0], sizeof(mvp));
+ writeCursor += sizeof(mvp);
+ }
+
+ // Copy the vertices and indices for each command list
+ for (int n = 0; n < _draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = _draw_data->CmdLists[n];
+ size_t verticesCount = cmd_list->VtxBuffer.size();
+ size_t indicesCount = cmd_list->IdxBuffer.size();
+ size_t verticesSize = verticesCount * sizeof(ImDrawVert);
+ size_t indicesSize = indicesCount * sizeof(ImDrawIdx);
+
+ // Copy the vertex data
+ memcpy(writeCursor, &cmd_list->VtxBuffer[0], verticesSize);
+ writeCursor += verticesSize;
+
+ // Copy the index data
+ memcpy(writeCursor, &cmd_list->IdxBuffer[0], indicesSize);
+ writeCursor += indicesSize;
+ }
+
+ ID3D12GraphicsCommandList* commandList = g_commandList;
+
+ D3D12_VIEWPORT viewport;
+ viewport.Width = ImGui::GetIO().DisplaySize.x;
+ viewport.Height = ImGui::GetIO().DisplaySize.y;
+ viewport.MinDepth = 0.f;
+ viewport.MaxDepth = 1.f;
+ viewport.TopLeftX = 0.f;
+ viewport.TopLeftY = 0.f;
+
+ commandList->RSSetViewports(1, &viewport);
+ commandList->OMSetRenderTargets(1, &g_renderTarget, FALSE, nullptr);
+ commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ commandList->SetPipelineState(g_pipelineState);
+
+ D3D12_GPU_VIRTUAL_ADDRESS bufferAddress = g_uploadBuffer->GetGPUVirtualAddress();
+ commandList->SetGraphicsRootConstantBufferView(1, bufferAddress);
+
+ uint64_t readCursor = 64; // Our constant buffer takes 64 bytes - one mat4x4
+
+ for (int n = 0; n < _draw_data->CmdListsCount; n++)
+ {
+ // Render command lists
+ int vtx_offset = 0;
+ int idx_offset = 0;
+
+ const ImDrawList* cmd_list = _draw_data->CmdLists[n];
+ size_t verticesCount = cmd_list->VtxBuffer.size();
+ size_t indicesCount = cmd_list->IdxBuffer.size();
+ size_t verticesSize = verticesCount * sizeof(ImDrawVert);
+ size_t indicesSize = indicesCount * sizeof(ImDrawIdx);
+
+ D3D12_VERTEX_BUFFER_VIEW vertexBufferView;
+ vertexBufferView.BufferLocation = bufferAddress + readCursor;
+ vertexBufferView.StrideInBytes = sizeof(ImDrawVert);
+ vertexBufferView.SizeInBytes = verticesSize;
+ readCursor += verticesSize;
+
+ D3D12_INDEX_BUFFER_VIEW indexBufferView;
+ indexBufferView.BufferLocation = bufferAddress + readCursor;
+ indexBufferView.SizeInBytes = indicesSize;
+ indexBufferView.Format = DXGI_FORMAT_R16_UINT;
+ readCursor += indicesSize;
+
+ commandList->IASetVertexBuffers(0, 1, &vertexBufferView);
+ commandList->IASetIndexBuffer(&indexBufferView);
+
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ const D3D12_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
+ commandList->RSSetScissorRects(1, &r);
+ commandList->DrawIndexedInstanced(pcmd->ElemCount, 1, idx_offset, vtx_offset, 0);
+ }
+ idx_offset += pcmd->ElemCount;
+ }
+ vtx_offset += verticesCount;
+ }
+}
+
+
+void ImGui_ImplDX12_NewFrame()
+{
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Setup display size (every frame to accommodate for window resizing)
+ RECT rect;
+ GetClientRect(g_hwnd, &rect);
+ io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
+
+ // Setup time step
+ INT64 current_time;
+ QueryPerformanceCounter((LARGE_INTEGER *)¤t_time);
+ io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
+ g_Time = current_time;
+
+ // Read keyboard modifiers inputs
+ io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
+ io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
+ io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
+ // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events
+ // io.MousePos : filled by WM_MOUSEMOVE events
+ // io.MouseDown : filled by WM_*BUTTON* events
+ // io.MouseWheel : filled by WM_MOUSEWHEEL events
+
+ // Hide OS mouse cursor if ImGui is drawing it
+ SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW));
+
+ // Start the frame
+ ImGui::NewFrame();
+}
+
+bool ImGui_ImplDX12_Init(void* _hwnd)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime.
+ io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
+ io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
+ io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
+ io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
+ io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
+ io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
+ io.KeyMap[ImGuiKey_Home] = VK_HOME;
+ io.KeyMap[ImGuiKey_End] = VK_END;
+ io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
+ io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
+ io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
+ io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
+ io.KeyMap[ImGuiKey_A] = 'A';
+ io.KeyMap[ImGuiKey_C] = 'C';
+ io.KeyMap[ImGuiKey_V] = 'V';
+ io.KeyMap[ImGuiKey_X] = 'X';
+ io.KeyMap[ImGuiKey_Y] = 'Y';
+ io.KeyMap[ImGuiKey_Z] = 'Z';
+
+ io.RenderDrawListsFn = ImGui_ImplDX12_RenderDrawLists;
+ io.ImeWindowHandle = _hwnd;
+
+ g_hwnd = (HWND)_hwnd;
+
+ if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond))
+ return false;
+ if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time))
+ return false;
+
+ return true;
+}
\ No newline at end of file
diff --git a/examples/directx12_example/imgui_impl_dx12.h b/examples/directx12_example/imgui_impl_dx12.h
new file mode 100644
index 000000000000..385e79a2b76e
--- /dev/null
+++ b/examples/directx12_example/imgui_impl_dx12.h
@@ -0,0 +1,23 @@
+struct ID3D12Device;
+struct ID3D12GraphicsCommandList;
+struct ID3D12CommandQueue;
+struct ID3D12Fence;
+struct D3D12_CPU_DESCRIPTOR_HANDLE;
+struct ID3D12RootSignature;
+
+#define FRAME_COUNT 3
+
+bool ImGui_ImplDX12_Init(void* _hwnd);
+void ImGui_ImplDX12_RenderDrawLists(ImDrawData* _draw_data);
+
+void ImGui_ImplDX12_CreateDeviceObjects(ID3D12Device* _device
+ , ID3D12GraphicsCommandList* _commandList
+ , ID3D12CommandQueue* _commandQueue
+ , ID3D12Fence* _fence
+ , D3D12_CPU_DESCRIPTOR_HANDLE _srvHandle
+ , ID3D12RootSignature* _rootSignature);
+
+void ImGui_ImplDX12_SetRenderData(ID3D12GraphicsCommandList* _commandList
+ , D3D12_CPU_DESCRIPTOR_HANDLE _renderTarget);
+
+void ImGui_ImplDX12_NewFrame();
\ No newline at end of file
diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp
new file mode 100644
index 000000000000..44d661c01624
--- /dev/null
+++ b/examples/directx12_example/main.cpp
@@ -0,0 +1,520 @@
+/*
+ * Copyright 2015 Onat Turkcuoglu. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include
+
+#include "imgui.cpp"
+#include "imgui_demo.cpp"
+#include "imgui_draw.cpp"
+
+#include
+#include
+#include
+
+#include "imgui_impl_dx12.h"
+
+bool InitD3D12(ID3D12Device** _device
+ , ID3D12CommandQueue** _commandQueue
+ , ID3D12CommandAllocator** _commandAllocator
+ , IDXGISwapChain3** _swapChain
+ , ID3D12DescriptorHeap** _rtvHeap
+ , ID3D12DescriptorHeap** _srvHeap
+ , ID3D12RootSignature** _rootSignature
+ , uint32_t _width
+ , uint32_t _height
+ , HWND _hwnd)
+{
+ // Load the DLLs and lookup function pointers
+ HMODULE d3d12dll = LoadLibraryA("d3d12.dll");
+ if (NULL == d3d12dll)
+ {
+ return false;
+ }
+
+ PFN_D3D12_CREATE_DEVICE D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)GetProcAddress(d3d12dll, "D3D12CreateDevice");
+ PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(d3d12dll, "D3D12GetDebugInterface");
+ PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)GetProcAddress(d3d12dll, "D3D12SerializeRootSignature");
+ if (NULL == D3D12CreateDevice
+ || NULL == D3D12GetDebugInterface
+ || NULL == D3D12SerializeRootSignature)
+ {
+ return false;
+ }
+
+ ID3D12Debug* debug;
+ HRESULT hr = D3D12GetDebugInterface(__uuidof(ID3D12Debug), (void**)&debug);
+
+ if (SUCCEEDED(hr) )
+ {
+ debug->EnableDebugLayer();
+ }
+
+ IDXGIFactory2* dxgiFactory;
+ // Create DXGI factory to create the swap chain later
+ hr = CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, __uuidof(IDXGIFactory2), (void**)&dxgiFactory);
+ if (FAILED(hr) )
+ {
+ return false;
+ }
+
+ // Create device
+ ID3D12Device* device = 0;
+ hr = D3D12CreateDevice(
+ NULL // NULL => Default adapter
+ , D3D_FEATURE_LEVEL_11_0 // Feature level
+ , __uuidof(ID3D12Device)
+ , (void**)&device
+ );
+
+ *_device = device;
+
+ // Create command queue
+ ID3D12CommandQueue* commandQueue = 0;
+ D3D12_COMMAND_QUEUE_DESC queueDesc;
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+ queueDesc.Priority = 0;
+ queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
+ queueDesc.NodeMask = 0; // Single GPU operation
+ device->CreateCommandQueue(&queueDesc
+ , __uuidof(ID3D12CommandQueue)
+ , (void**)_commandQueue
+ );
+
+ // Create command allocator
+ ID3D12CommandAllocator* commandAllocator = 0;
+ device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT
+ , __uuidof(ID3D12CommandAllocator)
+ , (void**)_commandAllocator
+ );
+
+ // Describe and create the swap chain.
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = FRAME_COUNT;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.BufferDesc.Width = _width;
+ swapChainDesc.BufferDesc.Height = _height;
+ swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
+ swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.OutputWindow = _hwnd;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.Windowed = TRUE;
+ swapChainDesc.Flags = 0;
+
+ hr = dxgiFactory->CreateSwapChain(*_commandQueue
+ , &swapChainDesc
+ , (IDXGISwapChain**)_swapChain
+ );
+
+ // Create #FRAME_COUNT render target descriptors (stored in descriptor heap)
+ D3D12_DESCRIPTOR_HEAP_DESC rtvDescHeap;
+ rtvDescHeap.NumDescriptors = FRAME_COUNT;
+ rtvDescHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
+ rtvDescHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
+ rtvDescHeap.NodeMask = 0;
+ device->CreateDescriptorHeap(&rtvDescHeap
+ , __uuidof(ID3D12DescriptorHeap)
+ , (void**)_rtvHeap
+ );
+
+ // Create one shader resource descriptor for the font texture
+ D3D12_DESCRIPTOR_HEAP_DESC srvDescHeap;
+ srvDescHeap.NumDescriptors = 1;
+ srvDescHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ srvDescHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ srvDescHeap.NodeMask = 0;
+ device->CreateDescriptorHeap(&srvDescHeap
+ , __uuidof(ID3D12DescriptorHeap)
+ , (void**)_srvHeap
+ );
+
+ // A root parameter describes one slot of a root signature
+ // Parameter types are: DESCRIPTOR_TABLE, 32BIT_CONSTANTS, CBV, SRV, UAV
+ //
+ // Root Descriptor Table: { uint NumDescriptorRanges, const DescriptorRange* pDescriptorRanges }
+ // Root Descriptor: { uint ShaderRegister, uint RegisterSpace }
+ // Root Constants: { uint ShaderRegister, uint RegisterSpace, uint Num32BitValues
+
+ D3D12_DESCRIPTOR_RANGE descRange[] =
+ {
+ { D3D12_DESCRIPTOR_RANGE_TYPE_SRV, // Range Type
+ 1, // Number of descriptors
+ 0, // Base shader register
+ 0, // Register space
+ D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, // Offset in descriptors from the start of the root signature
+ };
+
+ // This root signature will have two parameters, one descriptor table for SRVs and one constant buffer descriptor
+ D3D12_ROOT_PARAMETER rootParameter[] =
+ {
+ { D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, {1,descRange}, D3D12_SHADER_VISIBILITY_ALL },
+ { D3D12_ROOT_PARAMETER_TYPE_CBV, {0,0}, D3D12_SHADER_VISIBILITY_VERTEX },
+ };
+
+ rootParameter[1].Descriptor.RegisterSpace = 0;
+ rootParameter[1].Descriptor.ShaderRegister = 0;
+
+ // Include a statci sampler
+ D3D12_STATIC_SAMPLER_DESC samplerDesc;
+ memset(&samplerDesc, 0, sizeof(samplerDesc));
+ samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
+ samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ samplerDesc.MipLODBias = 0.f;
+ samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
+ samplerDesc.MinLOD = 0.f;
+ samplerDesc.MaxLOD = 0.f;
+ samplerDesc.ShaderRegister = 0;
+ samplerDesc.RegisterSpace = 0;
+ samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+
+ // Root signature description
+ D3D12_ROOT_SIGNATURE_DESC descRootSignature;
+ descRootSignature.NumParameters = 2;
+ descRootSignature.pParameters = rootParameter;
+ descRootSignature.NumStaticSamplers = 1;
+ descRootSignature.pStaticSamplers = &samplerDesc;
+ descRootSignature.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
+
+ // Serialise the root signature into memory
+ ID3DBlob* outBlob;
+ ID3DBlob* errorBlob;
+ D3D12SerializeRootSignature(&descRootSignature
+ , D3D_ROOT_SIGNATURE_VERSION_1
+ , &outBlob
+ , &errorBlob
+ );
+
+ // Create the root signature using the binary blob
+ device->CreateRootSignature(0
+ , outBlob->GetBufferPointer()
+ , outBlob->GetBufferSize()
+ , __uuidof(ID3D12RootSignature)
+ , (void**)_rootSignature
+ );
+
+ outBlob->Release();
+ return true;
+}
+
+LRESULT ImGui_ImplDX12_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ switch (msg)
+ {
+ case WM_LBUTTONDOWN:
+ io.MouseDown[0] = true;
+ return true;
+ case WM_LBUTTONUP:
+ io.MouseDown[0] = false;
+ return true;
+ case WM_RBUTTONDOWN:
+ io.MouseDown[1] = true;
+ return true;
+ case WM_RBUTTONUP:
+ io.MouseDown[1] = false;
+ return true;
+ case WM_MOUSEWHEEL:
+ io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
+ return true;
+ case WM_MOUSEMOVE:
+ io.MousePos.x = (signed short)(lParam);
+ io.MousePos.y = (signed short)(lParam >> 16);
+ return true;
+ case WM_KEYDOWN:
+ if (wParam < 256)
+ io.KeysDown[wParam] = 1;
+ return true;
+ case WM_KEYUP:
+ if (wParam < 256)
+ io.KeysDown[wParam] = 0;
+ return true;
+ case WM_CHAR:
+ // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
+ if (wParam > 0 && wParam < 0x10000)
+ io.AddInputCharacter((unsigned short)wParam);
+ return true;
+ }
+ return 0;
+}
+
+static bool s_resizeRenderTargets = false;
+static UINT s_resizedWidth;
+static UINT s_resizedHeight;
+
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (ImGui_ImplDX12_WndProcHandler(hWnd, msg, wParam, lParam))
+ return true;
+
+ switch (msg)
+ {
+ case WM_SIZE:
+ // Resize
+ s_resizedWidth = (UINT)LOWORD(lParam);
+ s_resizedHeight = (UINT)HIWORD(lParam);
+ s_resizeRenderTargets = true;
+ return 0;
+ case WM_SYSCOMMAND:
+ if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
+ return 0;
+ break;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return 0;
+ case WM_LBUTTONDOWN:
+ return 1;
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+static void setResourceBarrier(ID3D12GraphicsCommandList* _commandList, ID3D12Resource* _resource, D3D12_RESOURCE_STATES _stateBefore, D3D12_RESOURCE_STATES _stateAfter)
+{
+ D3D12_RESOURCE_BARRIER barrier;
+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier.Transition.pResource = _resource;
+ barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ barrier.Transition.StateBefore = _stateBefore;
+ barrier.Transition.StateAfter = _stateAfter;
+ _commandList->ResourceBarrier(1, &barrier);
+}
+
+int main(int, char**)
+{
+ // Create application window
+ WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL };
+ RegisterClassEx(&wc);
+ HWND hwnd = CreateWindow(L"ImGui Example", L"ImGui DirectX12 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
+
+ // D3D12 interfaces
+ ID3D12Device* device = 0;
+ ID3D12CommandQueue* commandQueue = 0;
+ ID3D12CommandAllocator* commandAllocator = 0;
+ IDXGISwapChain3* swapChain = 0;
+ ID3D12DescriptorHeap* rtvHeap = 0;
+ ID3D12DescriptorHeap* srvHeap = 0;
+ ID3D12GraphicsCommandList* commandList = 0;
+ ID3D12RootSignature* rootSignature = 0;
+ ID3D12Resource* renderTargets[FRAME_COUNT];
+
+ // Show the window
+ ShowWindow(hwnd, SW_SHOWDEFAULT);
+ UpdateWindow(hwnd);
+
+ ImGui_ImplDX12_Init(hwnd);
+
+ RECT rect;
+ GetClientRect(hwnd, &rect);
+
+ InitD3D12(&device
+ , &commandQueue
+ , &commandAllocator
+ , &swapChain
+ , &rtvHeap
+ , &srvHeap
+ , &rootSignature
+ , rect.right - rect.left
+ , rect.bottom - rect.top
+ , hwnd);
+
+ // Initialize render targets
+ // Create one RTV for each frame
+ uint32_t rtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
+ D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap->GetCPUDescriptorHandleForHeapStart();
+ for (uint32_t n = 0; n < FRAME_COUNT; n++)
+ {
+ swapChain->GetBuffer(n
+ , __uuidof(ID3D12Resource)
+ , (void**)&renderTargets[n]);
+ device->CreateRenderTargetView(renderTargets[n]
+ , nullptr
+ , rtvHandle);
+ rtvHandle.ptr += rtvDescriptorSize;
+ }
+
+ // Create the command list for uploading the font texture and rendering
+ device->CreateCommandList(0
+ , D3D12_COMMAND_LIST_TYPE_DIRECT
+ , commandAllocator
+ , NULL
+ , __uuidof(ID3D12GraphicsCommandList)
+ , (void**)&commandList
+ );
+
+ // Data for sync
+ ID3D12Fence* fence;
+ uint32_t frameIndex = 0;
+ uint32_t fenceValue = 1;
+
+ // Create an event handle to use for frame synchronization.
+ HANDLE fenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
+ device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
+
+ D3D12_CPU_DESCRIPTOR_HANDLE srvHandle = srvHeap->GetCPUDescriptorHandleForHeapStart();
+ ImGui_ImplDX12_CreateDeviceObjects(device, commandList, commandQueue, fence, srvHandle, rootSignature);
+
+ // The fence will be signalled when the command queue finishes uploading the fonts texture (see CreateDeviceObjects)
+ // which will signal the fenceEvent and execution continues
+ fence->SetEventOnCompletion(0, fenceEvent);
+ WaitForSingleObject(fenceEvent, INFINITE);
+
+ // Load Fonts
+ // (see extra_fonts/README.txt for more details)
+ //ImGuiIO& io = ImGui::GetIO();
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
+ //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
+ //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+
+ // Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
+ //ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
+ //ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
+ //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
+ //io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);
+
+ bool show_test_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_col = ImColor(114, 144, 154);
+
+ // Main loop
+ MSG msg;
+ ZeroMemory(&msg, sizeof(msg));
+ while (msg.message != WM_QUIT)
+ {
+ if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ continue;
+ }
+
+ // Resizing logic
+ if (s_resizeRenderTargets)
+ {
+ for (uint32_t n = 0; n < FRAME_COUNT; n++)
+ {
+ renderTargets[n]->Release(); // Have to release the resources before calling ResizeBuffers
+ }
+ swapChain->ResizeBuffers(0, s_resizedWidth, s_resizedHeight, DXGI_FORMAT_UNKNOWN, 0);
+
+ rtvHandle = rtvHeap->GetCPUDescriptorHandleForHeapStart();
+ for (uint32_t n = 0; n < FRAME_COUNT; n++)
+ {
+ swapChain->GetBuffer(n
+ , __uuidof(ID3D12Resource)
+ , (void**)&renderTargets[n]);
+ device->CreateRenderTargetView(renderTargets[n]
+ , nullptr
+ , rtvHandle);
+ rtvHandle.ptr += rtvDescriptorSize;
+ }
+
+ s_resizeRenderTargets = false;
+ frameIndex = 0;
+ }
+
+
+ ImGui_ImplDX12_NewFrame();
+
+ // 1. Show a simple window
+ // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
+ {
+ static float f = 0.0f;
+ ImGui::Text("Hello, world!");
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
+ ImGui::ColorEdit3("clear color", (float*)&clear_col);
+ if (ImGui::Button("Test Window")) show_test_window ^= 1;
+ if (ImGui::Button("Another Window")) show_another_window ^= 1;
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ }
+
+ // 2. Show another simple window, this time using an explicit Begin/End pair
+ if (show_another_window)
+ {
+ ImGui::SetNextWindowSize(ImVec2(200, 100), ImGuiSetCond_FirstUseEver);
+ ImGui::Begin("Another Window", &show_another_window);
+ ImGui::Text("Hello");
+ ImGui::End();
+ }
+
+ // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
+ if (show_test_window)
+ {
+ ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
+ ImGui::ShowTestWindow(&show_test_window);
+ }
+
+ // This is where rendering starts
+ commandAllocator->Reset();
+ commandList->Reset(commandAllocator, 0);
+ ID3D12CommandList* ppCommandLists[] = { commandList };
+
+ // Clear render target
+ D3D12_CPU_DESCRIPTOR_HANDLE renderTarget = rtvHeap->GetCPUDescriptorHandleForHeapStart();
+ {
+ renderTarget.ptr += frameIndex * rtvDescriptorSize;
+
+ setResourceBarrier(commandList
+ , renderTargets[frameIndex]
+ , D3D12_RESOURCE_STATE_PRESENT
+ , D3D12_RESOURCE_STATE_RENDER_TARGET);
+
+ // Set necessary state.
+ const float clearColor[] = { 0.8f, 0.8f, 0.8f, 0.8f };
+ commandList->ClearRenderTargetView(renderTarget, clearColor, 0, nullptr);
+ commandList->Close();
+
+ commandQueue->ExecuteCommandLists(1, ppCommandLists);
+ }
+
+ // Setup imgui cmd list and render
+ {
+ commandList->Reset(commandAllocator, 0);
+ commandList->SetGraphicsRootSignature(rootSignature);
+ commandList->SetDescriptorHeaps(1, &srvHeap);
+ D3D12_GPU_DESCRIPTOR_HANDLE srvHandle = srvHeap->GetGPUDescriptorHandleForHeapStart();
+ commandList->SetGraphicsRootDescriptorTable(0, srvHandle);
+
+ // Pass command queue, command list and CPU descriptor handle to the render target
+ // to ImGui before rendering
+ ImGui_ImplDX12_SetRenderData(commandList, renderTarget);
+ ImGui::Render();
+
+ // Closing the command list and executing it is the apps responsibility
+ // ImGui only fills the command list
+ }
+
+ setResourceBarrier(commandList
+ , renderTargets[frameIndex]
+ , D3D12_RESOURCE_STATE_RENDER_TARGET
+ , D3D12_RESOURCE_STATE_PRESENT);
+ commandList->Close();
+
+ commandQueue->ExecuteCommandLists(1, ppCommandLists);
+ commandQueue->Signal(fence, fenceValue);
+
+ // Wait until the resource transition to present is completed
+ if (fence->GetCompletedValue() < fenceValue)
+ {
+ fence->SetEventOnCompletion(fenceValue, fenceEvent);
+ WaitForSingleObject(fenceEvent, INFINITE);
+ }
+
+ // Present
+ swapChain->Present(0, DXGI_PRESENT_RESTART);
+ frameIndex = swapChain->GetCurrentBackBufferIndex();
+ fenceValue++;
+ }
+
+ // Shutdown!!
+ //
+ UnregisterClass(L"ImGui Example", wc.hInstance);
+ return 0;
+}