mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-05 06:57:13 +08:00
Merge branch 'master' into examples_refactor
This commit is contained in:
commit
e6bc840f6f
@ -123,11 +123,10 @@ Languages: (third-party bindinds)
|
||||
- Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs)
|
||||
|
||||
Frameworks:
|
||||
- DirectX 9, DirectX 10, DirectX 11: [examples/](https://github.com/ocornut/imgui/tree/master/examples)
|
||||
- DirectX 9, DirectX 10, DirectX 11, DirectX 12: [examples/](https://github.com/ocornut/imgui/tree/master/examples)
|
||||
- OpenGL 2/3 (with GLFW or SDL): [examples/](https://github.com/ocornut/imgui/tree/master/examples)
|
||||
- Vulkan (with GLFW): [examples/](https://github.com/ocornut/imgui/tree/master/examples)
|
||||
- Allegro 5, iOS, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples)
|
||||
- Unmerged PR: DirectX12: [#301](https://github.com/ocornut/imgui/pull/301)
|
||||
- Unmerged PR: SDL2 + OpenGLES + Emscripten: [#336](https://github.com/ocornut/imgui/pull/336)
|
||||
- Unmerged PR: FreeGlut + OpenGL2: [#801](https://github.com/ocornut/imgui/pull/801)
|
||||
- Unmerged PR: Native Win32 and OSX: [#281](https://github.com/ocornut/imgui/pull/281)
|
||||
|
@ -4,8 +4,8 @@ Binaries of some of those demos: http://www.miracleworld.net/imgui/binaries
|
||||
Third party languages and frameworks bindings:
|
||||
https://github.com/ocornut/imgui/wiki/Links
|
||||
(languages: C, C#, ChaiScript, D, Go, Haxe, Odin, Python, Rust, Lua, Pascal)
|
||||
(frameworks: DX12, OpenGLES, FreeGlut, Cinder, Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht, Ogre,
|
||||
OpenSceneGraph, openFrameworks, LOVE, NanoRT, Qt3d, SFML, Unreal Engine 4, etc.)
|
||||
(other frameworks: OpenGLES, FreeGlut, Cinder, Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht,
|
||||
Ogre, OpenSceneGraph, openFrameworks, LOVE, NanoRT, Qt3d, SFML, Unreal Engine 4, etc.)
|
||||
(extras: RemoteImGui, ImWindow, imgui_wm, etc.)
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ TL;DR;
|
||||
- Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase.
|
||||
- If you are using of the backend provided here, so you can copy the imgui_impl_xxx.cpp/h files
|
||||
to your project and use them unmodified.
|
||||
- To LEARN how the library is setup, you may refer to 'opengl2_example' because is the simplest one to read.
|
||||
- To LEARN how to setup imgui, you may refer to 'opengl2_example' because is the simplest one to read.
|
||||
However, do NOT USE the 'opengl2_example' if your code is using any modern GL3+ calls.
|
||||
Mixing old fixed-pipeline OpenGL2 and modern OpenGL3+ is going to make everything more complicated.
|
||||
Read comments below for details. If you are not sure, in doubt, use 'opengl3_example'.
|
||||
@ -53,15 +53,15 @@ opengl2_example/
|
||||
**DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||
**Prefer using the code in the opengl3_example/ folder**
|
||||
GLFW + OpenGL example (legacy, fixed pipeline).
|
||||
This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
||||
If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
||||
complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
||||
confuse your GPU driver.
|
||||
This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter.
|
||||
If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
|
||||
make things more complicated, will require your code to several OpenGL attributes to their initial state,
|
||||
and might confuse your GPU driver.
|
||||
|
||||
opengl3_example/
|
||||
GLFW + OpenGL example (programmable pipeline, binding modern functions with GL3W).
|
||||
This uses more modern OpenGL calls and custom shaders.
|
||||
Prefer using that if you are using modern OpenGL in your application (anything with shaders, vbo, vao, etc.).
|
||||
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
|
||||
|
||||
directx9_example/
|
||||
DirectX9 example, Windows only.
|
||||
@ -74,6 +74,10 @@ directx11_example/
|
||||
DirectX11 example, Windows only.
|
||||
This is quite long and tedious, because: DirectX11.
|
||||
|
||||
directx12_example/
|
||||
DirectX12 example, Windows only.
|
||||
This is quite longer and tedious, because: DirectX12.
|
||||
|
||||
apple_example/
|
||||
OSX & iOS example.
|
||||
On iOS, Using Synergy to access keyboard/mouse data from server computer.
|
||||
@ -83,15 +87,15 @@ sdl_opengl2_example/
|
||||
**DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
|
||||
**Prefer using the code in the sdl_opengl3_example/ folder**
|
||||
SDL2 + OpenGL example (legacy, fixed pipeline).
|
||||
This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
|
||||
If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
|
||||
complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
|
||||
confuse your GPU driver.
|
||||
This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter.
|
||||
If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
|
||||
make things more complicated, will require your code to several OpenGL attributes to their initial state,
|
||||
and might confuse your GPU driver.
|
||||
|
||||
sdl_opengl3_example/
|
||||
SDL2 + OpenGL3 example.
|
||||
This uses more modern OpenGL calls and custom shaders.
|
||||
Prefer using that if you are using modern OpenGL in your application (anything with shaders, vbo, vao, etc.).
|
||||
Prefer using that if you are using modern OpenGL in your application (anything with shaders).
|
||||
|
||||
allegro5_example/
|
||||
Allegro 5 example.
|
||||
@ -100,7 +104,5 @@ marmalade_example/
|
||||
Marmalade example using IwGx
|
||||
|
||||
vulkan_example/
|
||||
Vulkan example.
|
||||
This is quite long and tedious, because: Vulkan.
|
||||
|
||||
TODO: Apple, SDL GL2/GL3, Allegro, Marmalade, Vulkan examples do not honor the io.WantMoveMouse flag.
|
||||
Vulkan example.
|
||||
This is quite longer and tedious, because: Vulkan.
|
||||
|
@ -17,17 +17,9 @@ static ID3D10RenderTargetView* g_mainRenderTargetView = NULL;
|
||||
|
||||
void CreateRenderTarget()
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
g_pSwapChain->GetDesc(&sd);
|
||||
|
||||
// Create the render target
|
||||
ID3D10Texture2D* pBackBuffer;
|
||||
D3D10_RENDER_TARGET_VIEW_DESC render_target_view_desc;
|
||||
ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc));
|
||||
render_target_view_desc.Format = sd.BufferDesc.Format;
|
||||
render_target_view_desc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
|
||||
g_pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer);
|
||||
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView);
|
||||
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
|
||||
pBackBuffer->Release();
|
||||
}
|
||||
|
||||
|
@ -17,17 +17,9 @@ static ID3D11RenderTargetView* g_mainRenderTargetView = NULL;
|
||||
|
||||
void CreateRenderTarget()
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
g_pSwapChain->GetDesc(&sd);
|
||||
|
||||
// Create the render target
|
||||
ID3D11Texture2D* pBackBuffer;
|
||||
D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc;
|
||||
ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc));
|
||||
render_target_view_desc.Format = sd.BufferDesc.Format;
|
||||
render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
|
||||
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView);
|
||||
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
|
||||
pBackBuffer->Release();
|
||||
}
|
||||
|
||||
|
4
examples/directx12_example/build_win32.bat
Normal file
4
examples/directx12_example/build_win32.bat
Normal file
@ -0,0 +1,4 @@
|
||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||
mkdir Debug
|
||||
cl /nologo /Zi /MD /I ..\.. /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /D UNICODE /D _UNICODE *.cpp ..\..\*.cpp /FeDebug/directx12_example.exe /FoDebug/ /link d3d12.lib d3dcompiler.lib dxgi.lib
|
||||
|
164
examples/directx12_example/directx12_example.vcxproj
Normal file
164
examples/directx12_example/directx12_example.vcxproj
Normal file
@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{b4cf9797-519d-4afe-a8f4-5141a6b521d3}</ProjectGuid>
|
||||
<RootNamespace>directx12_example</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\imconfig.h" />
|
||||
<ClInclude Include="..\..\imgui.h" />
|
||||
<ClInclude Include="..\..\imgui_internal.h" />
|
||||
<ClInclude Include="imgui_impl_dx12.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\imgui.cpp" />
|
||||
<ClCompile Include="..\..\imgui_demo.cpp" />
|
||||
<ClCompile Include="..\..\imgui_draw.cpp" />
|
||||
<ClCompile Include="imgui_impl_dx12.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
45
examples/directx12_example/directx12_example.vcxproj.filters
Normal file
45
examples/directx12_example/directx12_example.vcxproj.filters
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="imgui">
|
||||
<UniqueIdentifier>{fb3d294f-51ec-478e-a627-25831c80fefd}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sources">
|
||||
<UniqueIdentifier>{4f33ddea-9910-456d-b868-4267eb3c2b19}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\imconfig.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\imgui.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="imgui_impl_dx12.h">
|
||||
<Filter>sources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\imgui_internal.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\imgui.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="imgui_impl_dx12.cpp">
|
||||
<Filter>sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_demo.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_draw.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
811
examples/directx12_example/imgui_impl_dx12.cpp
Normal file
811
examples/directx12_example/imgui_impl_dx12.cpp
Normal file
@ -0,0 +1,811 @@
|
||||
// ImGui Win32 + DirectX12 binding
|
||||
// FIXME: 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*))
|
||||
|
||||
// Implemented features:
|
||||
// [X] User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2018-02-22: Merged into master with all Win32 code synchronized to other examples.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_dx12.h"
|
||||
|
||||
// DirectX
|
||||
#include <d3d12.h>
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
// Win32 data
|
||||
static HWND g_hWnd = 0;
|
||||
static INT64 g_Time = 0;
|
||||
static INT64 g_TicksPerSecond = 0;
|
||||
static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_;
|
||||
|
||||
// DirectX data
|
||||
static ID3D12Device* g_pd3dDevice = NULL;
|
||||
static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL;
|
||||
static ID3D10Blob* g_pVertexShaderBlob = NULL;
|
||||
static ID3D10Blob* g_pPixelShaderBlob = NULL;
|
||||
static ID3D12RootSignature* g_pRootSignature = NULL;
|
||||
static ID3D12PipelineState* g_pPipelineState = NULL;
|
||||
static DXGI_FORMAT g_RTVFormat = DXGI_FORMAT_UNKNOWN;
|
||||
static ID3D12Resource* g_pFontTextureResource = NULL;
|
||||
static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {};
|
||||
static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {};
|
||||
|
||||
struct FrameResources
|
||||
{
|
||||
ID3D12Resource* IB;
|
||||
ID3D12Resource* VB;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
};
|
||||
static FrameResources* g_pFrameResources = NULL;
|
||||
static UINT g_numFramesInFlight = 0;
|
||||
static UINT g_frameIndex = UINT_MAX;
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
{
|
||||
float mvp[4][4];
|
||||
};
|
||||
|
||||
// Render function
|
||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||
void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// NOTE: I'm assuming that this only get's called once per frame!
|
||||
// If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator.
|
||||
g_frameIndex = g_frameIndex + 1;
|
||||
FrameResources* frameResources = &g_pFrameResources[g_frameIndex % g_numFramesInFlight];
|
||||
ID3D12Resource* g_pVB = frameResources->VB;
|
||||
ID3D12Resource* g_pIB = frameResources->IB;
|
||||
int g_VertexBufferSize = frameResources->VertexBufferSize;
|
||||
int g_IndexBufferSize = frameResources->IndexBufferSize;
|
||||
ID3D12GraphicsCommandList* ctx = g_pd3dCommandList;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Width = g_VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE,
|
||||
&desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&g_pVB)) < 0)
|
||||
return;
|
||||
frameResources->VB = g_pVB;
|
||||
frameResources->VertexBufferSize = g_VertexBufferSize;
|
||||
}
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Width = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE,
|
||||
&desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&g_pIB)) < 0)
|
||||
return;
|
||||
frameResources->IB = g_pIB;
|
||||
frameResources->IndexBufferSize = g_IndexBufferSize;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
void* vtx_resource, *idx_resource;
|
||||
D3D12_RANGE range;
|
||||
memset(&range, 0, sizeof(D3D12_RANGE));
|
||||
if (g_pVB->Map(0, &range, &vtx_resource) != S_OK)
|
||||
return;
|
||||
if (g_pIB->Map(0, &range, &idx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource;
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
g_pVB->Unmap(0, &range);
|
||||
g_pIB->Unmap(0, &range);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
VERTEX_CONSTANT_BUFFER vertex_constant_buffer;
|
||||
{
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = &vertex_constant_buffer;
|
||||
float L = 0.0f;
|
||||
float R = ImGui::GetIO().DisplaySize.x;
|
||||
float B = ImGui::GetIO().DisplaySize.y;
|
||||
float T = 0.0f;
|
||||
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(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
}
|
||||
|
||||
// Setup viewport
|
||||
D3D12_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D12_VIEWPORT));
|
||||
vp.Width = ImGui::GetIO().DisplaySize.x;
|
||||
vp.Height = ImGui::GetIO().DisplaySize.y;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0.0f;
|
||||
ctx->RSSetViewports(1, &vp);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
D3D12_VERTEX_BUFFER_VIEW vbv;
|
||||
memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));
|
||||
vbv.BufferLocation = g_pVB->GetGPUVirtualAddress() + offset;
|
||||
vbv.SizeInBytes = g_VertexBufferSize * stride;
|
||||
vbv.StrideInBytes = stride;
|
||||
ctx->IASetVertexBuffers(0, 1, &vbv);
|
||||
D3D12_INDEX_BUFFER_VIEW ibv;
|
||||
memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW));
|
||||
ibv.BufferLocation = g_pIB->GetGPUVirtualAddress();
|
||||
ibv.SizeInBytes = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
|
||||
ctx->IASetIndexBuffer(&ibv);
|
||||
ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->SetPipelineState(g_pPipelineState);
|
||||
ctx->SetGraphicsRootSignature(g_pRootSignature);
|
||||
ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendFactor(blend_factor);
|
||||
|
||||
// Render command lists
|
||||
int vtx_offset = 0;
|
||||
int idx_offset = 0;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
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 };
|
||||
ctx->SetGraphicsRootDescriptorTable(1, *(D3D12_GPU_DESCRIPTOR_HANDLE*)&pcmd->TextureId);
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, idx_offset, vtx_offset, 0);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplWin32_UpdateMouseCursor()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||
if (imgui_cursor == ImGuiMouseCursor_None)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
::SetCursor(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hardware cursor type
|
||||
LPTSTR win32_cursor = IDC_ARROW;
|
||||
switch (imgui_cursor)
|
||||
{
|
||||
case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
|
||||
case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
|
||||
case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||
case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
|
||||
case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
|
||||
case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||
case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||
}
|
||||
::SetCursor(::LoadCursor(NULL, win32_cursor));
|
||||
}
|
||||
}
|
||||
|
||||
// Process Win32 mouse/keyboard inputs.
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds.
|
||||
// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
|
||||
IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (ImGui::GetCurrentContext() == NULL)
|
||||
return 0;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
switch (msg)
|
||||
{
|
||||
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
|
||||
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
|
||||
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
|
||||
{
|
||||
int button = 0;
|
||||
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0;
|
||||
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1;
|
||||
if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2;
|
||||
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
|
||||
::SetCapture(hwnd);
|
||||
io.MouseDown[button] = true;
|
||||
return 0;
|
||||
}
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
{
|
||||
int button = 0;
|
||||
if (msg == WM_LBUTTONUP) button = 0;
|
||||
if (msg == WM_RBUTTONUP) button = 1;
|
||||
if (msg == WM_MBUTTONUP) button = 2;
|
||||
io.MouseDown[button] = false;
|
||||
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd)
|
||||
::ReleaseCapture();
|
||||
return 0;
|
||||
}
|
||||
case WM_MOUSEWHEEL:
|
||||
io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
|
||||
return 0;
|
||||
case WM_MOUSEHWHEEL:
|
||||
io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
|
||||
return 0;
|
||||
case WM_MOUSEMOVE:
|
||||
io.MousePos.x = (signed short)(lParam);
|
||||
io.MousePos.y = (signed short)(lParam >> 16);
|
||||
return 0;
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 1;
|
||||
return 0;
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 0;
|
||||
return 0;
|
||||
case WM_CHAR:
|
||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||
if (wParam > 0 && wParam < 0x10000)
|
||||
io.AddInputCharacter((unsigned short)wParam);
|
||||
return 0;
|
||||
case WM_SETCURSOR:
|
||||
if (LOWORD(lParam) == HTCLIENT)
|
||||
{
|
||||
ImGui_ImplWin32_UpdateMouseCursor();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX12_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Upload texture to graphics system
|
||||
{
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(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* pTexture = NULL;
|
||||
g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture));
|
||||
|
||||
UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
|
||||
UINT uploadSize = height * uploadPitch;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = uploadSize;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
ID3D12Resource* uploadBuffer = NULL;
|
||||
HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
void* mapped = NULL;
|
||||
D3D12_RANGE range = { 0, uploadSize };
|
||||
hr = uploadBuffer->Map(0, &range, &mapped);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
for (int y = 0; y < height; y++)
|
||||
memcpy((void*) ((uintptr_t) mapped + y * uploadPitch), pixels + y * width * 4, width * 4);
|
||||
uploadBuffer->Unmap(0, &range);
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
|
||||
srcLocation.pResource = uploadBuffer;
|
||||
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srcLocation.PlacedFootprint.Footprint.Width = width;
|
||||
srcLocation.PlacedFootprint.Footprint.Height = height;
|
||||
srcLocation.PlacedFootprint.Footprint.Depth = 1;
|
||||
srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
|
||||
dstLocation.pResource = pTexture;
|
||||
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dstLocation.SubresourceIndex = 0;
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = pTexture;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
|
||||
ID3D12Fence* fence = NULL;
|
||||
hr = g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
HANDLE event = CreateEvent(0, 0, 0, 0);
|
||||
IM_ASSERT(event != NULL);
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.NodeMask = 1;
|
||||
|
||||
ID3D12CommandQueue* cmdQueue = NULL;
|
||||
hr = g_pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
ID3D12CommandAllocator* cmdAlloc = NULL;
|
||||
hr = g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
ID3D12GraphicsCommandList* cmdList = NULL;
|
||||
hr = g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL);
|
||||
cmdList->ResourceBarrier(1, &barrier);
|
||||
|
||||
hr = cmdList->Close();
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*) &cmdList);
|
||||
hr = cmdQueue->Signal(fence, 1);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
fence->SetEventOnCompletion(1, event);
|
||||
WaitForSingleObject(event, INFINITE);
|
||||
|
||||
cmdList->Release();
|
||||
cmdAlloc->Release();
|
||||
cmdQueue->Release();
|
||||
CloseHandle(event);
|
||||
fence->Release();
|
||||
uploadBuffer->Release();
|
||||
|
||||
// Create texture view
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, g_hFontSrvCpuDescHandle);
|
||||
if (g_pFontTextureResource != NULL)
|
||||
g_pFontTextureResource->Release();
|
||||
g_pFontTextureResource = pTexture;
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID");
|
||||
io.Fonts->TexID = (void *)g_hFontSrvGpuDescHandle.ptr;
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX12_CreateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
return false;
|
||||
if (g_pPipelineState)
|
||||
ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
|
||||
// Create the root signature
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE descRange = {};
|
||||
descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
descRange.NumDescriptors = 1;
|
||||
descRange.BaseShaderRegister = 0;
|
||||
descRange.RegisterSpace = 0;
|
||||
descRange.OffsetInDescriptorsFromTableStart = 0;
|
||||
|
||||
D3D12_ROOT_PARAMETER param[2] = {};
|
||||
|
||||
param[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
||||
param[0].Constants.ShaderRegister = 0;
|
||||
param[0].Constants.RegisterSpace = 0;
|
||||
param[0].Constants.Num32BitValues = 16;
|
||||
param[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
|
||||
|
||||
param[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
param[1].DescriptorTable.NumDescriptorRanges = 1;
|
||||
param[1].DescriptorTable.pDescriptorRanges = &descRange;
|
||||
param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
|
||||
D3D12_STATIC_SAMPLER_DESC staticSampler = {};
|
||||
staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
staticSampler.MipLODBias = 0.f;
|
||||
staticSampler.MaxAnisotropy = 0;
|
||||
staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
|
||||
staticSampler.MinLOD = 0.f;
|
||||
staticSampler.MaxLOD = 0.f;
|
||||
staticSampler.ShaderRegister = 0;
|
||||
staticSampler.RegisterSpace = 0;
|
||||
staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC desc = {};
|
||||
desc.NumParameters = _countof(param);
|
||||
desc.pParameters = param;
|
||||
desc.NumStaticSamplers = 1;
|
||||
desc.pStaticSamplers = &staticSampler;
|
||||
desc.Flags =
|
||||
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
|
||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
|
||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
|
||||
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
|
||||
|
||||
ID3DBlob* blob = NULL;
|
||||
if (D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK)
|
||||
return false;
|
||||
|
||||
g_pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&g_pRootSignature));
|
||||
blob->Release();
|
||||
}
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
// If you would like to use this DX12 sample code but remove this dependency you can:
|
||||
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
||||
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
||||
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
||||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
|
||||
memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
|
||||
psoDesc.NodeMask = 1;
|
||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
psoDesc.pRootSignature = g_pRootSignature;
|
||||
psoDesc.SampleMask = UINT_MAX;
|
||||
psoDesc.NumRenderTargets = 1;
|
||||
psoDesc.RTVFormats[0] = g_RTVFormat;
|
||||
psoDesc.SampleDesc.Count = 1;
|
||||
psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
|
||||
|
||||
// Create the vertex shader
|
||||
{
|
||||
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;\
|
||||
}";
|
||||
|
||||
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &g_pVertexShaderBlob, NULL);
|
||||
if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
psoDesc.VS = { g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize() };
|
||||
|
||||
// Create the input layout
|
||||
static D3D12_INPUT_ELEMENT_DESC local_layout[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_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 },
|
||||
};
|
||||
psoDesc.InputLayout = { local_layout, 3 };
|
||||
}
|
||||
|
||||
// Create the pixel shader
|
||||
{
|
||||
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; \
|
||||
}";
|
||||
|
||||
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &g_pPixelShaderBlob, NULL);
|
||||
if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
return false;
|
||||
psoDesc.PS = { g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize() };
|
||||
}
|
||||
|
||||
// Create the blending setup
|
||||
{
|
||||
D3D12_BLEND_DESC& desc = psoDesc.BlendState;
|
||||
desc.AlphaToCoverageEnable = false;
|
||||
desc.RenderTarget[0].BlendEnable = true;
|
||||
desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||
desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
|
||||
desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
{
|
||||
D3D12_RASTERIZER_DESC& desc = psoDesc.RasterizerState;
|
||||
desc.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
desc.CullMode = D3D12_CULL_MODE_NONE;
|
||||
desc.FrontCounterClockwise = FALSE;
|
||||
desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
|
||||
desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
|
||||
desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
||||
desc.DepthClipEnable = true;
|
||||
desc.MultisampleEnable = FALSE;
|
||||
desc.AntialiasedLineEnable = FALSE;
|
||||
desc.ForcedSampleCount = 0;
|
||||
desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
{
|
||||
D3D12_DEPTH_STENCIL_DESC& desc = psoDesc.DepthStencilState;
|
||||
desc.DepthEnable = false;
|
||||
desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
||||
desc.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
desc.StencilEnable = false;
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
}
|
||||
|
||||
if (g_pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&g_pPipelineState)) != S_OK)
|
||||
return false;
|
||||
|
||||
ImGui_ImplDX12_CreateFontsTexture();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX12_InvalidateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
return;
|
||||
|
||||
if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
|
||||
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
|
||||
if (g_pRootSignature) { g_pRootSignature->Release(); g_pRootSignature = NULL; }
|
||||
if (g_pPipelineState) { g_pPipelineState->Release(); g_pPipelineState = NULL; }
|
||||
if (g_pFontTextureResource) { g_pFontTextureResource->Release(); g_pFontTextureResource = NULL; ImGui::GetIO().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++)
|
||||
{
|
||||
if (g_pFrameResources[i].IB) { g_pFrameResources[i].IB->Release(); g_pFrameResources[i].IB = NULL; }
|
||||
if (g_pFrameResources[i].VB) { g_pFrameResources[i].VB->Release(); g_pFrameResources[i].VB = NULL; }
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight,
|
||||
ID3D12Device* device,
|
||||
DXGI_FORMAT rtv_format,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
|
||||
{
|
||||
g_hWnd = (HWND)hwnd;
|
||||
g_pd3dDevice = device;
|
||||
g_RTVFormat = rtv_format;
|
||||
g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle;
|
||||
g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle;
|
||||
g_pFrameResources = new FrameResources [num_frames_in_flight];
|
||||
g_numFramesInFlight = num_frames_in_flight;
|
||||
g_frameIndex = UINT_MAX;
|
||||
|
||||
for (int i = 0; i < num_frames_in_flight; i++)
|
||||
{
|
||||
g_pFrameResources[i].IB = NULL;
|
||||
g_pFrameResources[i].VB = NULL;
|
||||
g_pFrameResources[i].VertexBufferSize = 5000;
|
||||
g_pFrameResources[i].IndexBufferSize = 10000;
|
||||
}
|
||||
|
||||
if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond))
|
||||
return false;
|
||||
if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time))
|
||||
return false;
|
||||
|
||||
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_Insert] = VK_INSERT;
|
||||
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
|
||||
io.KeyMap[ImGuiKey_Space] = VK_SPACE;
|
||||
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.ImeWindowHandle = g_hWnd;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX12_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
delete[] g_pFrameResources;
|
||||
g_pd3dDevice = NULL;
|
||||
g_hWnd = (HWND)0;
|
||||
g_pd3dCommandList = NULL;
|
||||
g_hFontSrvCpuDescHandle.ptr = 0;
|
||||
g_hFontSrvGpuDescHandle.ptr = 0;
|
||||
g_pFrameResources = NULL;
|
||||
g_numFramesInFlight = 0;
|
||||
g_frameIndex = UINT_MAX;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* command_list)
|
||||
{
|
||||
if (!g_pPipelineState)
|
||||
ImGui_ImplDX12_CreateDeviceObjects();
|
||||
|
||||
g_pd3dCommandList = command_list;
|
||||
|
||||
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.KeySuper = false;
|
||||
// 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
|
||||
|
||||
// Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation)
|
||||
if (io.WantMoveMouse)
|
||||
{
|
||||
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||
ClientToScreen(g_hWnd, &pos);
|
||||
SetCursorPos(pos.x, pos.y);
|
||||
}
|
||||
|
||||
// Update OS mouse cursor with the cursor requested by imgui
|
||||
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||
if (g_LastMouseCursor != mouse_cursor)
|
||||
{
|
||||
g_LastMouseCursor = mouse_cursor;
|
||||
ImGui_ImplWin32_UpdateMouseCursor();
|
||||
}
|
||||
|
||||
// Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
|
||||
ImGui::NewFrame();
|
||||
}
|
40
examples/directx12_example/imgui_impl_dx12.h
Normal file
40
examples/directx12_example/imgui_impl_dx12.h
Normal file
@ -0,0 +1,40 @@
|
||||
// ImGui Win32 + DirectX12 binding
|
||||
// FIXME: 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*))
|
||||
|
||||
// Implemented features:
|
||||
// [X] User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
||||
// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown().
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// https://github.com/ocornut/imgui
|
||||
|
||||
enum DXGI_FORMAT;
|
||||
struct ID3D12Device;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
struct D3D12_CPU_DESCRIPTOR_HANDLE;
|
||||
struct D3D12_GPU_DESCRIPTOR_HANDLE;
|
||||
|
||||
// cmd_list is the command list that the implementation will use to render imgui draw lists.
|
||||
// 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.
|
||||
// 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_API bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight,
|
||||
ID3D12Device* device,
|
||||
DXGI_FORMAT rtv_format,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
|
||||
IMGUI_API void ImGui_ImplDX12_Shutdown();
|
||||
IMGUI_API void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* cmd_list);
|
||||
IMGUI_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing ImGui state.
|
||||
IMGUI_API void ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
IMGUI_API bool ImGui_ImplDX12_CreateDeviceObjects();
|
||||
|
||||
// Handler for Win32 messages, update mouse/keyboard data.
|
||||
// You may or not need this for your implementation, but it can serve as reference for handling inputs.
|
||||
// Commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
|
||||
/*
|
||||
IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
*/
|
417
examples/directx12_example/main.cpp
Normal file
417
examples/directx12_example/main.cpp
Normal file
@ -0,0 +1,417 @@
|
||||
// ImGui - standalone example application for DirectX 12
|
||||
// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp.
|
||||
// FIXME: 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*))
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_dx12.h"
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#define DX12_ENABLE_DEBUG_LAYER 0
|
||||
|
||||
struct FrameContext
|
||||
{
|
||||
ID3D12CommandAllocator* CommandAllocator;
|
||||
UINT64 FenceValue;
|
||||
};
|
||||
|
||||
// Data
|
||||
static int const NUM_FRAMES_IN_FLIGHT = 3;
|
||||
static FrameContext g_frameContext[NUM_FRAMES_IN_FLIGHT] = {};
|
||||
static UINT g_frameIndex = 0;
|
||||
|
||||
static int const NUM_BACK_BUFFERS = 3;
|
||||
static ID3D12Device* g_pd3dDevice = NULL;
|
||||
static ID3D12DescriptorHeap* g_pd3dRtvDescHeap = NULL;
|
||||
static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = NULL;
|
||||
static ID3D12CommandQueue* g_pd3dCommandQueue = NULL;
|
||||
static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL;
|
||||
static ID3D12Fence* g_fence = NULL;
|
||||
static HANDLE g_fenceEvent = NULL;
|
||||
static UINT64 g_fenceLastSignaledValue = 0;
|
||||
static IDXGISwapChain3* g_pSwapChain = NULL;
|
||||
static HANDLE g_hSwapChainWaitableObject = NULL;
|
||||
static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
|
||||
static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
|
||||
|
||||
void CreateRenderTarget()
|
||||
{
|
||||
ID3D12Resource* pBackBuffer;
|
||||
for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
|
||||
{
|
||||
g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
|
||||
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, g_mainRenderTargetDescriptor[i]);
|
||||
g_mainRenderTargetResource[i] = pBackBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
void WaitForLastSubmittedFrame()
|
||||
{
|
||||
FrameContext* frameCtxt = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT];
|
||||
|
||||
UINT64 fenceValue = frameCtxt->FenceValue;
|
||||
if (fenceValue == 0)
|
||||
return; // No fence was signaled
|
||||
|
||||
frameCtxt->FenceValue = 0;
|
||||
if (g_fence->GetCompletedValue() >= fenceValue)
|
||||
return;
|
||||
|
||||
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
|
||||
WaitForSingleObject(g_fenceEvent, INFINITE);
|
||||
}
|
||||
|
||||
FrameContext* WaitForNextFrameResources()
|
||||
{
|
||||
UINT nextFrameIndex = g_frameIndex + 1;
|
||||
g_frameIndex = nextFrameIndex;
|
||||
|
||||
HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, NULL };
|
||||
DWORD numWaitableObjects = 1;
|
||||
|
||||
FrameContext* frameCtxt = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT];
|
||||
UINT64 fenceValue = frameCtxt->FenceValue;
|
||||
if (fenceValue != 0) // means no fence was signaled
|
||||
{
|
||||
frameCtxt->FenceValue = 0;
|
||||
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
|
||||
waitableObjects[1] = g_fenceEvent;
|
||||
numWaitableObjects = 2;
|
||||
}
|
||||
|
||||
WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE);
|
||||
|
||||
return frameCtxt;
|
||||
}
|
||||
|
||||
void ResizeSwapChain(HWND hWnd, int width, int height)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC1 sd;
|
||||
g_pSwapChain->GetDesc1(&sd);
|
||||
sd.Width = width;
|
||||
sd.Height = height;
|
||||
|
||||
IDXGIFactory4* dxgiFactory = nullptr;
|
||||
g_pSwapChain->GetParent(IID_PPV_ARGS(&dxgiFactory));
|
||||
|
||||
g_pSwapChain->Release();
|
||||
CloseHandle(g_hSwapChainWaitableObject);
|
||||
|
||||
IDXGISwapChain1* swapChain1 = NULL;
|
||||
dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1);
|
||||
swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain));
|
||||
swapChain1->Release();
|
||||
dxgiFactory->Release();
|
||||
|
||||
g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
|
||||
|
||||
g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
|
||||
assert(g_hSwapChainWaitableObject != NULL);
|
||||
}
|
||||
|
||||
void CleanupRenderTarget()
|
||||
{
|
||||
WaitForLastSubmittedFrame();
|
||||
|
||||
for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
|
||||
if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; }
|
||||
}
|
||||
|
||||
HRESULT CreateDeviceD3D(HWND hWnd)
|
||||
{
|
||||
// Setup swap chain
|
||||
DXGI_SWAP_CHAIN_DESC1 sd;
|
||||
{
|
||||
ZeroMemory(&sd, sizeof(sd));
|
||||
sd.BufferCount = NUM_BACK_BUFFERS;
|
||||
sd.Width = 0;
|
||||
sd.Height = 0;
|
||||
sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
sd.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.SampleDesc.Count = 1;
|
||||
sd.SampleDesc.Quality = 0;
|
||||
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
sd.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||
sd.Scaling = DXGI_SCALING_STRETCH;
|
||||
sd.Stereo = FALSE;
|
||||
}
|
||||
|
||||
if (DX12_ENABLE_DEBUG_LAYER)
|
||||
{
|
||||
ID3D12Debug* dx12Debug = NULL;
|
||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&dx12Debug))))
|
||||
{
|
||||
dx12Debug->EnableDebugLayer();
|
||||
dx12Debug->Release();
|
||||
}
|
||||
}
|
||||
|
||||
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
if (D3D12CreateDevice(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
desc.NumDescriptors = NUM_BACK_BUFFERS;
|
||||
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
desc.NodeMask = 1;
|
||||
if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dRtvDescHeap)) != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
|
||||
{
|
||||
g_mainRenderTargetDescriptor[i] = rtvHandle;
|
||||
rtvHandle.ptr += rtvDescriptorSize;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
desc.NumDescriptors = 1;
|
||||
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dSrvDescHeap)) != S_OK)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
{
|
||||
D3D12_COMMAND_QUEUE_DESC desc = {};
|
||||
desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
desc.NodeMask = 1;
|
||||
if (g_pd3dDevice->CreateCommandQueue(&desc, IID_PPV_ARGS(&g_pd3dCommandQueue)) != S_OK)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
|
||||
if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
if (g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, g_frameContext[0].CommandAllocator, NULL, IID_PPV_ARGS(&g_pd3dCommandList)) != S_OK ||
|
||||
g_pd3dCommandList->Close() != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
if (g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&g_fence)) != S_OK)
|
||||
return E_FAIL;
|
||||
|
||||
g_fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (g_fenceEvent == NULL)
|
||||
return E_FAIL;
|
||||
|
||||
{
|
||||
IDXGIFactory4* dxgiFactory = NULL;
|
||||
IDXGISwapChain1* swapChain1 = NULL;
|
||||
if (CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)) != S_OK ||
|
||||
dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1) != S_OK ||
|
||||
swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain)) != S_OK)
|
||||
return E_FAIL;
|
||||
swapChain1->Release();
|
||||
dxgiFactory->Release();
|
||||
g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
|
||||
g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
|
||||
}
|
||||
|
||||
CreateRenderTarget();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CleanupDeviceD3D()
|
||||
{
|
||||
CleanupRenderTarget();
|
||||
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
|
||||
if (g_hSwapChainWaitableObject != NULL) { CloseHandle(g_hSwapChainWaitableObject); }
|
||||
for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
|
||||
if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = NULL; }
|
||||
if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = NULL; }
|
||||
if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = NULL; }
|
||||
if (g_pd3dRtvDescHeap) { g_pd3dRtvDescHeap->Release(); g_pd3dRtvDescHeap = NULL; }
|
||||
if (g_pd3dSrvDescHeap) { g_pd3dSrvDescHeap->Release(); g_pd3dSrvDescHeap = NULL; }
|
||||
if (g_fence) { g_fence->Release(); g_fence = NULL; }
|
||||
if (g_fenceEvent) { CloseHandle(g_fenceEvent); g_fenceEvent = NULL; }
|
||||
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
||||
}
|
||||
|
||||
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||
return true;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_SIZE:
|
||||
if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
|
||||
{
|
||||
ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
CleanupRenderTarget();
|
||||
ResizeSwapChain(hWnd, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam));
|
||||
CreateRenderTarget();
|
||||
ImGui_ImplDX12_CreateDeviceObjects();
|
||||
}
|
||||
return 0;
|
||||
case WM_SYSCOMMAND:
|
||||
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
|
||||
return 0;
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Create application window
|
||||
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
|
||||
RegisterClassEx(&wc);
|
||||
HWND hwnd = CreateWindow(_T("ImGui Example"), _T("ImGui DirectX12 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
|
||||
|
||||
// Initialize Direct3D
|
||||
if (CreateDeviceD3D(hwnd) < 0)
|
||||
{
|
||||
CleanupDeviceD3D();
|
||||
UnregisterClass(_T("ImGui Example"), wc.hInstance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Show the window
|
||||
ShowWindow(hwnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
// Setup ImGui binding
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls
|
||||
ImGui_ImplDX12_Init(hwnd, NUM_FRAMES_IN_FLIGHT, g_pd3dDevice,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(),
|
||||
g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
// Setup style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Load Fonts
|
||||
// - 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.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - 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.
|
||||
// - Read 'misc/fonts/README.txt' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
MSG msg;
|
||||
ZeroMemory(&msg, sizeof(msg));
|
||||
while (msg.message != WM_QUIT)
|
||||
{
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
continue;
|
||||
}
|
||||
ImGui_ImplDX12_NewFrame(g_pd3dCommandList);
|
||||
|
||||
// 1. Show a simple window.
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
}
|
||||
|
||||
// 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui!
|
||||
if (show_demo_window)
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
}
|
||||
|
||||
// Rendering
|
||||
FrameContext* frameCtxt = WaitForNextFrameResources();
|
||||
UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex();
|
||||
frameCtxt->CommandAllocator->Reset();
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = g_mainRenderTargetResource[backBufferIdx];
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
|
||||
g_pd3dCommandList->Reset(frameCtxt->CommandAllocator, NULL);
|
||||
g_pd3dCommandList->ResourceBarrier(1, &barrier);
|
||||
g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], (float*)&clear_color, 0, NULL);
|
||||
g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL);
|
||||
g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap);
|
||||
ImGui::Render();
|
||||
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData());
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
g_pd3dCommandList->ResourceBarrier(1, &barrier);
|
||||
g_pd3dCommandList->Close();
|
||||
|
||||
g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList);
|
||||
|
||||
g_pSwapChain->Present(1, 0); // Present with vsync
|
||||
//g_pSwapChain->Present(0, 0); // Present without vsync
|
||||
|
||||
UINT64 fenceValue = g_fenceLastSignaledValue + 1;
|
||||
g_pd3dCommandQueue->Signal(g_fence, fenceValue);
|
||||
g_fenceLastSignaledValue = fenceValue;
|
||||
frameCtxt->FenceValue = fenceValue;
|
||||
}
|
||||
|
||||
WaitForLastSubmittedFrame();
|
||||
ImGui_ImplDX12_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
CleanupDeviceD3D();
|
||||
UnregisterClass(_T("ImGui Example"), wc.hInstance);
|
||||
|
||||
return 0;
|
||||
}
|
11
imgui.cpp
11
imgui.cpp
@ -951,14 +951,13 @@ ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p)
|
||||
{
|
||||
ImVec2 ap = p - a;
|
||||
ImVec2 ab_dir = b - a;
|
||||
float ab_len = sqrtf(ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y);
|
||||
ab_dir *= 1.0f / ab_len;
|
||||
float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
|
||||
if (dot < 0.0f)
|
||||
return a;
|
||||
if (dot > ab_len)
|
||||
float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
|
||||
if (dot > ab_len_sqr)
|
||||
return b;
|
||||
return a + ab_dir * dot;
|
||||
return a + ab_dir * dot / ab_len_sqr;
|
||||
}
|
||||
|
||||
bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
|
||||
@ -2349,7 +2348,7 @@ static bool NavMoveRequestButNoResultYet()
|
||||
return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
|
||||
}
|
||||
|
||||
static void NavMoveRequestCancel()
|
||||
void ImGui::NavMoveRequestCancel()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.NavMoveRequest = false;
|
||||
@ -5006,7 +5005,7 @@ static void NavProcessMoveRequestWrapAround(ImGuiWindow* window)
|
||||
if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == 0)
|
||||
{
|
||||
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
|
||||
NavMoveRequestCancel();
|
||||
ImGui::NavMoveRequestCancel();
|
||||
g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = ((g.NavMoveDir == ImGuiDir_Up) ? ImMax(window->SizeFull.y, window->SizeContents.y) : 0.0f) - window->Scroll.y;
|
||||
}
|
||||
}
|
||||
|
2
imgui.h
2
imgui.h
@ -1506,7 +1506,7 @@ struct ImDrawList
|
||||
IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
|
||||
IMGUI_API void PushClipRectFullScreen();
|
||||
IMGUI_API void PopClipRect();
|
||||
IMGUI_API void PushTextureID(const ImTextureID& texture_id);
|
||||
IMGUI_API void PushTextureID(ImTextureID texture_id);
|
||||
IMGUI_API void PopTextureID();
|
||||
inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); }
|
||||
inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); }
|
||||
|
@ -450,7 +450,7 @@ void ImDrawList::PopClipRect()
|
||||
UpdateClipRect();
|
||||
}
|
||||
|
||||
void ImDrawList::PushTextureID(const ImTextureID& texture_id)
|
||||
void ImDrawList::PushTextureID(ImTextureID texture_id)
|
||||
{
|
||||
_TextureIdStack.push_back(texture_id);
|
||||
UpdateTextureID();
|
||||
|
@ -1066,6 +1066,7 @@ namespace ImGui
|
||||
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true);
|
||||
|
||||
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
|
||||
IMGUI_API void NavMoveRequestCancel();
|
||||
IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
|
||||
|
||||
IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode);
|
||||
|
Loading…
Reference in New Issue
Block a user