dep: Update imgui to v1.88

This commit is contained in:
Connor McLaughlin 2022-07-08 23:06:09 +10:00
parent b7fbde31a7
commit 0c0bd4c995
25 changed files with 10673 additions and 6813 deletions

View file

@ -20,28 +20,34 @@
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport ) //#define IMGUI_API __declspec( dllimport )
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
//---- Disable all of Dear ImGui or don't implement standard windows. //---- Disable all of Dear ImGui or don't implement standard windows/tools.
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty. //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
//---- Don't implement some functions to reduce linkage requirements. //---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Include imgui_user.h at the end of imgui.h as a convenience //---- Include imgui_user.h at the end of imgui.h as a convenience
//#define IMGUI_INCLUDE_IMGUI_USER_H //#define IMGUI_INCLUDE_IMGUI_USER_H
@ -56,16 +62,17 @@
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
// #define IMGUI_USE_STB_SPRINTF //#define IMGUI_USE_STB_SPRINTF
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
// On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'. // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE //#define IMGUI_ENABLE_FREETYPE
//---- Use stb_truetype to build and rasterize the font atlas (default) //---- Use stb_truetype to build and rasterize the font atlas (default)
@ -75,12 +82,12 @@
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
// This will be inlined as part of ImVec2 and ImVec4 class declarations. // This will be inlined as part of ImVec2 and ImVec4 class declarations.
/* /*
#define IM_VEC2_CLASS_EXTRA \ #define IM_VEC2_CLASS_EXTRA \
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
operator MyVec2() const { return MyVec2(x,y); } operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \ #define IM_VEC4_CLASS_EXTRA \
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); } operator MyVec4() const { return MyVec4(x,y,z,w); }
*/ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,6 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types. // This is also an example of how you may wrap your own similar types.
// Compatibility:
// - std::string support is only guaranteed to work from C++11.
// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture)
// Changelog: // Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string

View file

@ -1,10 +1,10 @@
// [DEAR IMGUI] // [DEAR IMGUI]
// This is a slightly modified version of stb_textedit.h 1.13. // This is a slightly modified version of stb_textedit.h 1.14.
// Those changes would need to be pushed into nothings/stb: // Those changes would need to be pushed into nothings/stb:
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
// stb_textedit.h - v1.13 - public domain - Sean Barrett // stb_textedit.h - v1.14 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools // Development of this library was sponsored by RAD Game Tools
// //
// This C header file implements the guts of a multi-line text-editing // This C header file implements the guts of a multi-line text-editing
@ -19,7 +19,7 @@
// texts, as its performance does not scale and it has limited undo). // texts, as its performance does not scale and it has limited undo).
// //
// Non-trivial behaviors are modelled after Windows text controls. // Non-trivial behaviors are modelled after Windows text controls.
// //
// //
// LICENSE // LICENSE
// //
@ -35,6 +35,7 @@
// //
// VERSION HISTORY // VERSION HISTORY
// //
// 1.14 (2021-07-11) page up/down, various fixes
// 1.13 (2019-02-07) fix bug in undo size management // 1.13 (2019-02-07) fix bug in undo size management
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash // 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield // 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
@ -58,6 +59,7 @@
// Ulf Winklemann: move-by-word in 1.1 // Ulf Winklemann: move-by-word in 1.1
// Fabian Giesen: secondary key inputs in 1.5 // Fabian Giesen: secondary key inputs in 1.5
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 // Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
// Louis Schnellbach: page up/down in 1.14
// //
// Bugfixes: // Bugfixes:
// Scott Graham // Scott Graham
@ -93,8 +95,8 @@
// moderate sizes. The undo system does no memory allocations, so // moderate sizes. The undo system does no memory allocations, so
// it grows STB_TexteditState by the worst-case storage which is (in bytes): // it grows STB_TexteditState by the worst-case storage which is (in bytes):
// //
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT // [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT // + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT
// //
// //
// Implementation mode: // Implementation mode:
@ -217,20 +219,20 @@
// call this with the mouse x,y on a mouse down; it will update the cursor // call this with the mouse x,y on a mouse down; it will update the cursor
// and reset the selection start/end to the cursor point. the x,y must // and reset the selection start/end to the cursor point. the x,y must
// be relative to the text widget, with (0,0) being the top left. // be relative to the text widget, with (0,0) being the top left.
// //
// drag: // drag:
// call this with the mouse x,y on a mouse drag/up; it will update the // call this with the mouse x,y on a mouse drag/up; it will update the
// cursor and the selection end point // cursor and the selection end point
// //
// cut: // cut:
// call this to delete the current selection; returns true if there was // call this to delete the current selection; returns true if there was
// one. you should FIRST copy the current selection to the system paste buffer. // one. you should FIRST copy the current selection to the system paste buffer.
// (To copy, just copy the current selection out of the string yourself.) // (To copy, just copy the current selection out of the string yourself.)
// //
// paste: // paste:
// call this to paste text at the current cursor point or over the current // call this to paste text at the current cursor point or over the current
// selection if there is one. // selection if there is one.
// //
// key: // key:
// call this for keyboard inputs sent to the textfield. you can use it // call this for keyboard inputs sent to the textfield. you can use it
// for "key down" events or for "translated" key events. if you need to // for "key down" events or for "translated" key events. if you need to
@ -241,7 +243,7 @@
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to // clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
// anything other type you wante before including. // anything other type you wante before including.
// //
// //
// When rendering, you can read the cursor position and selection state from // When rendering, you can read the cursor position and selection state from
// the STB_TexteditState. // the STB_TexteditState.
// //
@ -716,9 +718,7 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
state->has_preferred_x = 0; state->has_preferred_x = 0;
return 1; return 1;
} }
// remove the undo since we didn't actually insert the characters // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
if (state->undostate.undo_point)
--state->undostate.undo_point;
return 0; return 0;
} }
@ -764,7 +764,7 @@ retry:
state->insert_mode = !state->insert_mode; state->insert_mode = !state->insert_mode;
break; break;
#endif #endif
case STB_TEXTEDIT_K_UNDO: case STB_TEXTEDIT_K_UNDO:
stb_text_undo(str, state); stb_text_undo(str, state);
state->has_preferred_x = 0; state->has_preferred_x = 0;
@ -779,7 +779,7 @@ retry:
// if currently there's a selection, move cursor to start of selection // if currently there's a selection, move cursor to start of selection
if (STB_TEXT_HAS_SELECTION(state)) if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_first(state); stb_textedit_move_to_first(state);
else else
if (state->cursor > 0) if (state->cursor > 0)
--state->cursor; --state->cursor;
state->has_preferred_x = 0; state->has_preferred_x = 0;
@ -828,7 +828,7 @@ retry:
#ifdef STB_TEXTEDIT_MOVEWORDRIGHT #ifdef STB_TEXTEDIT_MOVEWORDRIGHT
case STB_TEXTEDIT_K_WORDRIGHT: case STB_TEXTEDIT_K_WORDRIGHT:
if (STB_TEXT_HAS_SELECTION(state)) if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_last(str, state); stb_textedit_move_to_last(str, state);
else { else {
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
@ -922,7 +922,7 @@ retry:
} }
break; break;
} }
case STB_TEXTEDIT_K_UP: case STB_TEXTEDIT_K_UP:
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGUP: case STB_TEXTEDIT_K_PGUP:
@ -1014,7 +1014,7 @@ retry:
} }
state->has_preferred_x = 0; state->has_preferred_x = 0;
break; break;
#ifdef STB_TEXTEDIT_K_TEXTSTART2 #ifdef STB_TEXTEDIT_K_TEXTSTART2
case STB_TEXTEDIT_K_TEXTSTART2: case STB_TEXTEDIT_K_TEXTSTART2:
#endif #endif
@ -1031,7 +1031,7 @@ retry:
state->select_start = state->select_end = 0; state->select_start = state->select_end = 0;
state->has_preferred_x = 0; state->has_preferred_x = 0;
break; break;
#ifdef STB_TEXTEDIT_K_TEXTSTART2 #ifdef STB_TEXTEDIT_K_TEXTSTART2
case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
#endif #endif
@ -1410,38 +1410,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
ALTERNATIVE A - MIT License ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org) ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose, software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means. commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law. this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*/ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,6 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types. // This is also an example of how you may wrap your own similar types.
// Compatibility:
// - std::string support is only guaranteed to work from C++11.
// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture)
// Changelog: // Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,15 +1,19 @@
// [DEAR IMGUI] // [DEAR IMGUI]
// This is a slightly modified version of stb_rect_pack.h 1.00. // This is a slightly modified version of stb_rect_pack.h 1.01.
// Those changes would need to be pushed into nothings/stb:
// - Added STBRP__CDECL
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
//
// stb_rect_pack.h - v1.00 - public domain - rectangle packing // stb_rect_pack.h - v1.01 - public domain - rectangle packing
// Sean Barrett 2014 // Sean Barrett 2014
// //
// Useful for e.g. packing rectangular textures into an atlas. // Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation. // Does not do rotation.
// //
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than // Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what // the totally naive one in stb_truetype (which is primarily what
// this is meant to replace). // this is meant to replace).
@ -34,13 +38,14 @@
// Minor features // Minor features
// Martins Mozeiko // Martins Mozeiko
// github:IntellectualKitty // github:IntellectualKitty
// //
// Bugfixes / warning fixes // Bugfixes / warning fixes
// Jeremy Jaussaud // Jeremy Jaussaud
// Fabian Giesen // Fabian Giesen
// //
// Version history: // Version history:
// //
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes // 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result // 0.11 (2017-03-03) return packing success/fail result
@ -81,11 +86,10 @@ typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node; typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect; typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord; typedef int stbrp_coord;
#else
typedef unsigned short stbrp_coord; #define STBRP__MAXVAL 0x7fffffff
#endif // Mostly for internal use, but this is the maximum supported coordinate value.
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type // Assign packed locations to rectangles. The rectangles are of type
@ -213,10 +217,9 @@ struct stbrp_context
#define STBRP_ASSERT assert #define STBRP_ASSERT assert
#endif #endif
// [DEAR IMGUI] Added STBRP__CDECL
#ifdef _MSC_VER #ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v) #define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl #define STBRP__CDECL __cdecl
#else #else
#define STBRP__NOTUSED(v) (void)sizeof(v) #define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL #define STBRP__CDECL
@ -262,9 +265,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{ {
int i; int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i) for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1]; nodes[i].next = &nodes[i+1];
@ -283,11 +283,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
context->extra[0].y = 0; context->extra[0].y = 0;
context->extra[0].next = &context->extra[1]; context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width; context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30); context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL; context->extra[1].next = NULL;
} }
@ -433,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
if (y <= best_y) { if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos; best_x = xpos;
STBRP_ASSERT(y <= best_y); //STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
best_y = y; best_y = y;
best_waste = waste; best_waste = waste;
best = prev; best = prev;
@ -441,7 +437,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
} }
} }
tail = tail->next; tail = tail->next;
} }
} }
fr.prev_link = best; fr.prev_link = best;
@ -529,7 +525,6 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res; return res;
} }
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_height_compare(const void *a, const void *b) static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{ {
const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *p = (const stbrp_rect *) a;
@ -541,7 +536,6 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w); return (p->w > q->w) ? -1 : (p->w < q->w);
} }
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_original_order(const void *a, const void *b) static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{ {
const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *p = (const stbrp_rect *) a;
@ -549,12 +543,6 @@ static int STBRP__CDECL rect_original_order(const void *a, const void *b)
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
} }
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{ {
int i, all_rects_packed = 1; int i, all_rects_packed = 1;
@ -602,38 +590,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
ALTERNATIVE A - MIT License ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions: so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org) ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose, software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means. commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law. this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*/ */

File diff suppressed because it is too large Load diff

View file

@ -294,7 +294,7 @@ void EndLayout()
bool IsCancelButtonPressed() bool IsCancelButtonPressed()
{ {
return ImGui::IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed); return ImGui::IsNavInputTest(ImGuiNavInput_Cancel, ImGuiNavReadMode_Pressed);
} }
bool BeginFullscreenColumns(const char* title) bool BeginFullscreenColumns(const char* title)
@ -466,7 +466,7 @@ static bool MenuButtonFrame(const char* str_id, bool enabled, float height, bool
} }
else else
{ {
if (ImGui::IsClippedEx(*bb, id, false)) if (ImGui::IsClippedEx(*bb, id))
{ {
*visible = false; *visible = false;
*hovered = false; *hovered = false;
@ -728,7 +728,7 @@ bool FloatingButton(const char* text, float x, float y, float width, float heigh
} }
else else
{ {
if (ImGui::IsClippedEx(bb, id, false)) if (ImGui::IsClippedEx(bb, id))
return false; return false;
} }
@ -1076,7 +1076,7 @@ void NavTitle(const char* title, float height /*= LAYOUT_MENU_BUTTON_HEIGHT_NO_S
ImGui::SameLine(); ImGui::SameLine();
ImRect bb(pos, pos + size); ImRect bb(pos, pos + size);
if (ImGui::IsClippedEx(bb, 0, false)) if (ImGui::IsClippedEx(bb, 0))
return; return;
bb.Min.y += style.FramePadding.y; bb.Min.y += style.FramePadding.y;
@ -1127,7 +1127,7 @@ bool NavButton(const char* title, bool is_active, bool enabled /* = true */, flo
} }
else else
{ {
if (ImGui::IsClippedEx(bb, id, false)) if (ImGui::IsClippedEx(bb, id))
return false; return false;
} }

View file

@ -632,8 +632,7 @@ bool D3D12HostDisplay::CreateImGuiContext()
ImGui::GetIO().DisplaySize.x = static_cast<float>(m_window_info.surface_width); ImGui::GetIO().DisplaySize.x = static_cast<float>(m_window_info.surface_width);
ImGui::GetIO().DisplaySize.y = static_cast<float>(m_window_info.surface_height); ImGui::GetIO().DisplaySize.y = static_cast<float>(m_window_info.surface_height);
return ImGui_ImplDX12_Init(g_d3d12_context->GetDevice(), D3D12::Context::NUM_COMMAND_LISTS, return ImGui_ImplDX12_Init(DXGI_FORMAT_R8G8B8A8_UNORM);
DXGI_FORMAT_R8G8B8A8_UNORM);
} }
void D3D12HostDisplay::DestroyImGuiContext() void D3D12HostDisplay::DestroyImGuiContext()
@ -729,7 +728,7 @@ bool D3D12HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector<u32>*
void D3D12HostDisplay::RenderImGui(ID3D12GraphicsCommandList* cmdlist) void D3D12HostDisplay::RenderImGui(ID3D12GraphicsCommandList* cmdlist)
{ {
ImGui::Render(); ImGui::Render();
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), cmdlist); ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData());
} }
void D3D12HostDisplay::RenderDisplay(ID3D12GraphicsCommandList* cmdlist) void D3D12HostDisplay::RenderDisplay(ID3D12GraphicsCommandList* cmdlist)

View file

@ -1277,13 +1277,13 @@ void DrawSettingsWindow()
BeginNavBar(); BeginNavBar();
if (ImGui::IsNavInputTest(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_Pressed)) if (ImGui::IsNavInputTest(ImGuiNavInput_FocusPrev, ImGuiNavReadMode_Pressed))
{ {
s_settings_page = static_cast<SettingsPage>((s_settings_page == static_cast<SettingsPage>(0)) ? s_settings_page = static_cast<SettingsPage>((s_settings_page == static_cast<SettingsPage>(0)) ?
(static_cast<u32>(SettingsPage::Count) - 1) : (static_cast<u32>(SettingsPage::Count) - 1) :
(static_cast<u32>(s_settings_page) - 1)); (static_cast<u32>(s_settings_page) - 1));
} }
else if (ImGui::IsNavInputTest(ImGuiNavInput_FocusNext, ImGuiInputReadMode_Pressed)) else if (ImGui::IsNavInputTest(ImGuiNavInput_FocusNext, ImGuiNavReadMode_Pressed))
{ {
s_settings_page = s_settings_page =
static_cast<SettingsPage>((static_cast<u32>(s_settings_page) + 1) % static_cast<u32>(SettingsPage::Count)); static_cast<SettingsPage>((static_cast<u32>(s_settings_page) + 1) % static_cast<u32>(SettingsPage::Count));
@ -1315,7 +1315,7 @@ void DrawSettingsWindow()
ImVec2(io.DisplaySize.x, io.DisplaySize.y - heading_size.y - ImGuiFullscreen::g_menu_bar_size), ImVec2(io.DisplaySize.x, io.DisplaySize.y - heading_size.y - ImGuiFullscreen::g_menu_bar_size),
"settings_parent")) "settings_parent"))
{ {
if (ImGui::IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed)) if (ImGui::IsNavInputTest(ImGuiNavInput_Cancel, ImGuiNavReadMode_Pressed))
{ {
if (ImGui::IsWindowFocused()) if (ImGui::IsWindowFocused())
ReturnToMainWindow(); ReturnToMainWindow();

View file

@ -1,17 +1,24 @@
// dear imgui: Renderer for DirectX11 // dear imgui: Renderer Backend for DirectX11
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Backend (e.g. Win32)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// https://github.com/ocornut/imgui // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. // 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility.
@ -33,73 +40,123 @@
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
#endif #endif
// DirectX data // DirectX11 data
static ID3D11Device* g_pd3dDevice = NULL; struct ImGui_ImplDX11_Data
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; {
static ID3D11Buffer* g_pVB = NULL; ID3D11Device* pd3dDevice;
static ID3D11Buffer* g_pIB = NULL; ID3D11DeviceContext* pd3dDeviceContext;
static ID3D10Blob* g_pVertexShaderBlob = NULL; IDXGIFactory* pFactory;
static ID3D11VertexShader* g_pVertexShader = NULL; ID3D11Buffer* pVB;
static ID3D11InputLayout* g_pInputLayout = NULL; ID3D11Buffer* pIB;
static ID3D11Buffer* g_pVertexConstantBuffer = NULL; ID3D11VertexShader* pVertexShader;
static ID3D10Blob* g_pPixelShaderBlob = NULL; ID3D11InputLayout* pInputLayout;
static ID3D11PixelShader* g_pPixelShader = NULL; ID3D11Buffer* pVertexConstantBuffer;
static ID3D11SamplerState* g_pFontSampler = NULL; ID3D11PixelShader* pPixelShader;
static ID3D11ShaderResourceView*g_pFontTextureView = NULL; ID3D11SamplerState* pFontSampler;
static ID3D11RasterizerState* g_pRasterizerState = NULL; ID3D11ShaderResourceView* pFontTextureView;
static ID3D11BlendState* g_pBlendState = NULL; ID3D11RasterizerState* pRasterizerState;
static ID3D11DepthStencilState* g_pDepthStencilState = NULL; ID3D11BlendState* pBlendState;
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; ID3D11DepthStencilState* pDepthStencilState;
int VertexBufferSize;
int IndexBufferSize;
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
};
struct VERTEX_CONSTANT_BUFFER struct VERTEX_CONSTANT_BUFFER
{ {
float mvp[4][4]; float mvp[4][4];
}; };
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
}
// Functions
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
// Setup viewport
D3D11_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
ctx->RSSetViewports(1, &vp);
// Setup shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
ctx->IASetInputLayout(bd->pInputLayout);
ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->VSSetShader(bd->pVertexShader, NULL, 0);
ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
ctx->PSSetShader(bd->pPixelShader, NULL, 0);
ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
ctx->GSSetShader(NULL, NULL, 0);
ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
// Setup blend state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
ctx->RSSetState(bd->pRasterizerState);
}
// Render function // 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_ImplDX11_RenderDrawData(ImDrawData* draw_data) void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
{ {
// Avoid rendering when minimized // Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return; return;
ID3D11DeviceContext* ctx = g_pd3dDeviceContext; ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
ID3D11DeviceContext* ctx = bd->pd3dDeviceContext;
// Create and grow vertex/index buffers if needed // Create and grow vertex/index buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
{ {
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
g_VertexBufferSize = draw_data->TotalVtxCount + 5000; bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D11_BUFFER_DESC desc; D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC; desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0; desc.MiscFlags = 0;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVB) < 0)
return; return;
} }
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
{ {
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000; bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D11_BUFFER_DESC desc; D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC; desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pIB) < 0)
return; return;
} }
// Upload vertex/index data into a single contiguous GPU buffer // Upload vertex/index data into a single contiguous GPU buffer
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
return; return;
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
return; return;
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
@ -111,14 +168,14 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
vtx_dst += cmd_list->VtxBuffer.Size; vtx_dst += cmd_list->VtxBuffer.Size;
idx_dst += cmd_list->IdxBuffer.Size; idx_dst += cmd_list->IdxBuffer.Size;
} }
ctx->Unmap(g_pVB, 0); ctx->Unmap(bd->pVB, 0);
ctx->Unmap(g_pIB, 0); ctx->Unmap(bd->pIB, 0);
// Setup orthographic projection matrix into our constant buffer // Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is (0,0) for single viewport apps. // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
{ {
D3D11_MAPPED_SUBRESOURCE mapped_resource; D3D11_MAPPED_SUBRESOURCE mapped_resource;
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
return; return;
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
float L = draw_data->DisplayPos.x; float L = draw_data->DisplayPos.x;
@ -133,82 +190,16 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
}; };
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
ctx->Unmap(g_pVertexConstantBuffer, 0); ctx->Unmap(bd->pVertexConstantBuffer, 0);
} }
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) // Setup desired DX state
struct BACKUP_DX11_STATE ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
{
UINT ScissorRectsCount, ViewportsCount;
D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
ID3D11RasterizerState* RS;
ID3D11BlendState* BlendState;
FLOAT BlendFactor[4];
UINT SampleMask;
UINT StencilRef;
ID3D11DepthStencilState* DepthStencilState;
ID3D11ShaderResourceView* PSShaderResource;
ID3D11SamplerState* PSSampler;
ID3D11PixelShader* PS;
ID3D11VertexShader* VS;
UINT PSInstancesCount, VSInstancesCount;
ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
DXGI_FORMAT IndexBufferFormat;
ID3D11InputLayout* InputLayout;
};
BACKUP_DX11_STATE old;
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
ctx->RSGetState(&old.RS);
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
ctx->PSGetSamplers(0, 1, &old.PSSampler);
old.PSInstancesCount = old.VSInstancesCount = 256;
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
ctx->IAGetInputLayout(&old.InputLayout);
// Setup viewport
D3D11_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
ctx->RSSetViewports(1, &vp);
// Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
ctx->IASetInputLayout(g_pInputLayout);
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->VSSetShader(g_pVertexShader, NULL, 0);
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
ctx->PSSetShader(g_pPixelShader, NULL, 0);
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
// Setup render state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
ctx->RSSetState(g_pRasterizerState);
// Render command lists // Render command lists
int vtx_offset = 0; // (Because we merged all buffers into a single one, we maintain our own offset into them)
int idx_offset = 0; int global_idx_offset = 0;
int global_vtx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos; ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
@ -216,60 +207,51 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{ {
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback) if (pcmd->UserCallback != NULL)
{ {
// User callback (registered via ImDrawList::AddCallback) // User callback, registered via ImDrawList::AddCallback()
pcmd->UserCallback(cmd_list, pcmd); // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
else
pcmd->UserCallback(cmd_list, pcmd);
} }
else else
{ {
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle // Apply scissor/clipping rectangle
const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
ctx->RSSetScissorRects(1, &r); ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw // Bind texture, Draw
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId; ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
ctx->PSSetShaderResources(0, 1, &texture_srv); ctx->PSSetShaderResources(0, 1, &texture_srv);
ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
} }
idx_offset += pcmd->ElemCount;
} }
vtx_offset += cmd_list->VtxBuffer.Size; global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
} }
// Restore modified DX state
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
} }
void ImGui_ImplDX11_CreateFontsTexture() void ImGui_ImplDX11_CreateFontsTexture()
{ {
// Build texture atlas // Build texture atlas
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
unsigned char* pixels; unsigned char* pixels;
int width, height; int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
if (bd->pFontTextureView)
bd->pFontTextureView->Release();
// Upload texture to graphics system // Upload texture to graphics system
if (g_pFontTextureView)
{
g_pFontTextureView->Release();
g_pFontTextureView = nullptr;
}
{ {
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
@ -283,12 +265,13 @@ void ImGui_ImplDX11_CreateFontsTexture()
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0; desc.CPUAccessFlags = 0;
ID3D11Texture2D *pTexture = NULL; ID3D11Texture2D* pTexture = NULL;
D3D11_SUBRESOURCE_DATA subResource; D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels; subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4; subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0; subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
IM_ASSERT(pTexture != NULL);
// Create texture view // Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
@ -297,37 +280,37 @@ void ImGui_ImplDX11_CreateFontsTexture()
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MostDetailedMip = 0;
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
pTexture->Release(); pTexture->Release();
} }
// Store our identifier // Store our identifier
io.Fonts->TexID = (ImTextureID)g_pFontTextureView; io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
// Create texture sampler // Create texture sampler
if (!g_pFontSampler) // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
if (!bd->pFontSampler)
{ {
D3D11_SAMPLER_DESC desc; D3D11_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(desc)); ZeroMemory(&desc, sizeof(desc));
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
desc.MipLODBias = 0.f; desc.MipLODBias = 0.f;
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
desc.MinLOD = 0.f; desc.MinLOD = 0.f;
desc.MaxLOD = 0.f; desc.MaxLOD = 0.f;
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
} }
io.Fonts->ClearTexData();
} }
bool ImGui_ImplDX11_CreateDeviceObjects() bool ImGui_ImplDX11_CreateDeviceObjects()
{ {
if (!g_pd3dDevice) ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
if (!bd->pd3dDevice)
return false; return false;
if (g_pFontSampler) if (bd->pFontSampler)
ImGui_ImplDX11_InvalidateDeviceObjects(); ImGui_ImplDX11_InvalidateDeviceObjects();
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
@ -341,46 +324,53 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
static const char* vertexShader = static const char* vertexShader =
"cbuffer vertexBuffer : register(b0) \ "cbuffer vertexBuffer : register(b0) \
{\ {\
float4x4 ProjectionMatrix; \ float4x4 ProjectionMatrix; \
};\ };\
struct VS_INPUT\ struct VS_INPUT\
{\ {\
float2 pos : POSITION;\ float2 pos : POSITION;\
float4 col : COLOR0;\ float4 col : COLOR0;\
float2 uv : TEXCOORD0;\ float2 uv : TEXCOORD0;\
};\ };\
\ \
struct PS_INPUT\ struct PS_INPUT\
{\ {\
float4 pos : SV_POSITION;\ float4 pos : SV_POSITION;\
float4 col : COLOR0;\ float4 col : COLOR0;\
float2 uv : TEXCOORD0;\ float2 uv : TEXCOORD0;\
};\ };\
\ \
PS_INPUT main(VS_INPUT input)\ PS_INPUT main(VS_INPUT input)\
{\ {\
PS_INPUT output;\ PS_INPUT output;\
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
output.col = input.col;\ output.col = input.col;\
output.uv = input.uv;\ output.uv = input.uv;\
return output;\ return output;\
}"; }";
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL); ID3DBlob* vertexShaderBlob;
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! if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
return false; return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK) if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &bd->pVertexShader) != S_OK)
{
vertexShaderBlob->Release();
return false; return false;
}
// Create the input layout // Create the input layout
D3D11_INPUT_ELEMENT_DESC local_layout[] = D3D11_INPUT_ELEMENT_DESC local_layout[] =
{ {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
}; };
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
{
vertexShaderBlob->Release();
return false; return false;
}
vertexShaderBlob->Release();
// Create the constant buffer // Create the constant buffer
{ {
@ -390,7 +380,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0; desc.MiscFlags = 0;
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVertexConstantBuffer);
} }
} }
@ -412,11 +402,15 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
return out_col; \ return out_col; \
}"; }";
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL); ID3DBlob* pixelShaderBlob;
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! if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
return false; return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK) if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &bd->pPixelShader) != S_OK)
{
pixelShaderBlob->Release();
return false; return false;
}
pixelShaderBlob->Release();
} }
// Create the blending setup // Create the blending setup
@ -428,11 +422,11 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
} }
// Create the rasterizer state // Create the rasterizer state
@ -443,7 +437,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
desc.CullMode = D3D11_CULL_NONE; desc.CullMode = D3D11_CULL_NONE;
desc.ScissorEnable = true; desc.ScissorEnable = true;
desc.DepthClipEnable = true; desc.DepthClipEnable = true;
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
} }
// Create depth-stencil State // Create depth-stencil State
@ -457,47 +451,79 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
desc.BackFace = desc.FrontFace; desc.BackFace = desc.FrontFace;
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
} }
ImGui_ImplDX11_CreateFontsTexture();
return true; return true;
} }
void ImGui_ImplDX11_InvalidateDeviceObjects() void ImGui_ImplDX11_InvalidateDeviceObjects()
{ {
if (!g_pd3dDevice) ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
if (!bd->pd3dDevice)
return; return;
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = NULL; }
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = NULL; }
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = NULL; }
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = NULL; }
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = NULL; }
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = NULL; }
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = NULL; }
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = NULL; }
if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
} }
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
{ {
// Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_dx11"; io.BackendRendererName = "imgui_impl_dx11";
g_pd3dDevice = device; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
g_pd3dDeviceContext = device_context;
// Get factory from device
IDXGIDevice* pDXGIDevice = NULL;
IDXGIAdapter* pDXGIAdapter = NULL;
IDXGIFactory* pFactory = NULL;
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
{
bd->pd3dDevice = device;
bd->pd3dDeviceContext = device_context;
bd->pFactory = pFactory;
}
if (pDXGIDevice) pDXGIDevice->Release();
if (pDXGIAdapter) pDXGIAdapter->Release();
bd->pd3dDevice->AddRef();
bd->pd3dDeviceContext->AddRef();
return ImGui_ImplDX11_CreateDeviceObjects(); return ImGui_ImplDX11_CreateDeviceObjects();
} }
void ImGui_ImplDX11_Shutdown() void ImGui_ImplDX11_Shutdown()
{ {
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
if (bd == NULL)
return;
ImGui_ImplDX11_InvalidateDeviceObjects(); ImGui_ImplDX11_InvalidateDeviceObjects();
g_pd3dDevice = NULL; if (bd->pFactory) { bd->pFactory->Release(); }
g_pd3dDeviceContext = NULL; if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = NULL;
io.BackendRendererUserData = NULL;
IM_DELETE(bd);
} }

View file

@ -1,24 +1,17 @@
// dear imgui: Renderer for DirectX11 // dear imgui: Renderer Backend for DirectX11
// This needs to be used along with a Platform Binding (e.g. Win32) // This needs to be used along with a Platform Backend (e.g. Win32)
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
#pragma once #pragma once
#include "imgui.h" // IMGUI_IMPL_API
struct ID3D11Device; struct ID3D11Device;
struct ID3D11DeviceContext; struct ID3D11DeviceContext;
IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); void ImGui_ImplDX11_Shutdown();
IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing ImGui state. // Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); void ImGui_ImplDX11_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); bool ImGui_ImplDX11_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplDX11_CreateFontsTexture(); void ImGui_ImplDX11_CreateFontsTexture();

View file

@ -7,14 +7,22 @@
// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'. // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. // To build this on 32-bit systems:
// - [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in the 'example_win32_direct12/example_win32_direct12.vcxproj' project file)
// - [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
// - [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
// - [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in the example_win32_direct12/build_win32.bat file)
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer.
// 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically. // 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically.
// 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning. // 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning.
// 2020-09-08: DirectX12: Clarified support for building on 32-bit systems by redefining ImTextureID. // 2020-09-08: DirectX12: Clarified support for building on 32-bit systems by redefining ImTextureID.
@ -29,6 +37,13 @@
// 2018-06-08: DirectX12: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle (to ease support for future multi-viewport). // 2018-06-08: DirectX12: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle (to ease support for future multi-viewport).
// 2018-02-22: Merged into master with all Win32 code synchronized to other examples. // 2018-02-22: Merged into master with all Win32 code synchronized to other examples.
#include "common/windows_headers.h"
#include "common/assert.h"
#include "common/d3d12/context.h"
#include "common/d3d12/texture.h"
#include "common/d3d12/stream_buffer.h"
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_dx12.h" #include "imgui_impl_dx12.h"
@ -40,325 +55,323 @@
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
#endif #endif
#include "common/d3d12/texture.h" // If we're doing more than this... wtf?
#include "common/d3d12/context.h" static constexpr u32 VERTEX_BUFFER_SIZE = 8 * 1024 * 1024;
static constexpr u32 INDEX_BUFFER_SIZE = 4 * 1024 * 1024;
// DirectX data struct ImGui_ImplDX12_Data
static ID3D12Device* g_pd3dDevice = NULL;
static ID3D12RootSignature* g_pRootSignature = NULL;
static ID3D12PipelineState* g_pPipelineState = NULL;
static DXGI_FORMAT g_RTVFormat = DXGI_FORMAT_UNKNOWN;
static D3D12::Texture g_FontTexture;
struct FrameResources
{ {
ID3D12Resource* IndexBuffer; D3D12::StreamBuffer VertexStreamBuffer;
ID3D12Resource* VertexBuffer; D3D12::StreamBuffer IndexStreamBuffer;
int IndexBufferSize; D3D12::Texture FontTexture;
int VertexBufferSize; ID3D12RootSignature* pRootSignature = nullptr;
ID3D12PipelineState* pPipelineState = nullptr;
DXGI_FORMAT RTVFormat = DXGI_FORMAT_UNKNOWN;
}; };
static FrameResources* g_pFrameResources = NULL;
static UINT g_numFramesInFlight = 0;
static UINT g_frameIndex = UINT_MAX;
template<typename T>
static void SafeRelease(T*& res)
{
if (res)
res->Release();
res = NULL;
}
struct VERTEX_CONSTANT_BUFFER struct VERTEX_CONSTANT_BUFFER
{ {
float mvp[4][4]; float mvp[4][4];
}; };
static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, FrameResources* fr) // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()
{ {
// Setup orthographic projection matrix into our constant buffer return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). }
VERTEX_CONSTANT_BUFFER vertex_constant_buffer;
{ // Functions
float L = draw_data->DisplayPos.x; static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx)
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; {
float T = draw_data->DisplayPos.y; ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
float mvp[4][4] = // Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
VERTEX_CONSTANT_BUFFER vertex_constant_buffer;
{ {
{ 2.0f / (R - L), 0.0f, 0.0f, 0.0f }, float L = draw_data->DisplayPos.x;
{ 0.0f, 2.0f / (T - B), 0.0f, 0.0f }, float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
{ 0.0f, 0.0f, 0.5f, 0.0f }, float T = draw_data->DisplayPos.y;
{ (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f }, float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
}; float mvp[4][4] =
memcpy(&vertex_constant_buffer.mvp, mvp, sizeof(mvp)); {
} { 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(&vertex_constant_buffer.mvp, mvp, sizeof(mvp));
}
// Setup viewport // Setup viewport
D3D12_VIEWPORT vp; D3D12_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D12_VIEWPORT)); memset(&vp, 0, sizeof(D3D12_VIEWPORT));
vp.Width = draw_data->DisplaySize.x; vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y; vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f; vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f; vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0.0f; vp.TopLeftX = vp.TopLeftY = 0.0f;
ctx->RSSetViewports(1, &vp); ctx->RSSetViewports(1, &vp);
// Bind shader and vertex buffers // Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert); unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0; D3D12_VERTEX_BUFFER_VIEW vbv;
D3D12_VERTEX_BUFFER_VIEW vbv; memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));
memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW)); vbv.BufferLocation = bd->VertexStreamBuffer.GetCurrentGPUPointer();
vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset; vbv.SizeInBytes = bd->VertexStreamBuffer.GetCurrentSpace();
vbv.SizeInBytes = fr->VertexBufferSize * stride; vbv.StrideInBytes = stride;
vbv.StrideInBytes = stride; ctx->IASetVertexBuffers(0, 1, &vbv);
ctx->IASetVertexBuffers(0, 1, &vbv); D3D12_INDEX_BUFFER_VIEW ibv;
D3D12_INDEX_BUFFER_VIEW ibv; memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW));
memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW)); ibv.BufferLocation = bd->IndexStreamBuffer.GetCurrentGPUPointer();
ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress(); ibv.SizeInBytes = bd->IndexStreamBuffer.GetCurrentSpace();
ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx); ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; ctx->IASetIndexBuffer(&ibv);
ctx->IASetIndexBuffer(&ibv); ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ctx->SetPipelineState(bd->pPipelineState);
ctx->SetPipelineState(g_pPipelineState); ctx->SetGraphicsRootSignature(bd->pRootSignature);
ctx->SetGraphicsRootSignature(g_pRootSignature); ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
// Setup blend factor // Setup blend factor
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendFactor(blend_factor); ctx->OMSetBlendFactor(blend_factor);
}
template<typename T>
static inline void SafeRelease(T*& res)
{
if (res)
res->Release();
res = NULL;
} }
// Render function // Render function
void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx) void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data)
{ {
// Avoid rendering when minimized // Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return; return;
// FIXME: I'm assuming that this only gets called once per frame! // FIXME: I'm assuming that this only gets called once per frame!
// If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. // 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; ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight];
// Create and grow vertex/index buffers if needed const u32 needed_vb = draw_data->TotalVtxCount * sizeof(ImDrawVert);
if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount) const u32 needed_ib = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
{
SafeRelease(fr->VertexBuffer);
fr->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 = fr->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(&fr->VertexBuffer)) < 0)
return;
}
if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount)
{
SafeRelease(fr->IndexBuffer);
fr->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 = fr->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(&fr->IndexBuffer)) < 0)
return;
}
// Upload vertex/index data into a single contiguous GPU buffer if (!bd->VertexStreamBuffer.ReserveMemory(needed_vb, sizeof(ImDrawVert)) ||
void* vtx_resource, * idx_resource; !bd->IndexStreamBuffer.ReserveMemory(needed_ib, sizeof(ImDrawIdx)))
D3D12_RANGE range;
memset(&range, 0, sizeof(D3D12_RANGE));
if (fr->VertexBuffer->Map(0, &range, &vtx_resource) != S_OK)
return;
if (fr->IndexBuffer->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;
}
fr->VertexBuffer->Unmap(0, &range);
fr->IndexBuffer->Unmap(0, &range);
// Setup desired DX state
ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0;
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
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]; g_d3d12_context->ExecuteCommandList(false);
if (pcmd->UserCallback != NULL) if (!bd->VertexStreamBuffer.ReserveMemory(needed_vb, sizeof(ImDrawVert)) ||
{ !bd->IndexStreamBuffer.ReserveMemory(needed_ib, sizeof(ImDrawIdx)))
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Apply Scissor, Bind texture, Draw
const D3D12_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
if (r.right > r.left && r.bottom > r.top)
{ {
ctx->SetGraphicsRootDescriptorTable(1, reinterpret_cast<D3D12::Texture*>(pcmd->TextureId)->GetSRVDescriptor()); Panic("Failed to allocate space for imgui vertices/indices");
ctx->RSSetScissorRects(1, &r);
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
} }
}
} }
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size; // Upload vertex/index data into a single contiguous GPU buffer
} ImDrawVert* vtx_dst = (ImDrawVert*)bd->VertexStreamBuffer.GetCurrentHostPointer();
ImDrawIdx* idx_dst = (ImDrawIdx*)bd->IndexStreamBuffer.GetCurrentHostPointer();
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;
}
// Setup desired DX state (must happen before commit, because it uses the offsets)
ID3D12GraphicsCommandList* ctx = g_d3d12_context->GetCommandList();
ImGui_ImplDX12_SetupRenderState(draw_data, ctx);
bd->VertexStreamBuffer.CommitMemory(needed_vb);
bd->IndexStreamBuffer.CommitMemory(needed_ib);
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0;
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
const D3D12::Texture* last_texture = nullptr;
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 != NULL)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX12_SetupRenderState(draw_data, ctx);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply Scissor/clipping rectangle, Bind texture, Draw
const D3D12_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
const D3D12::Texture* tex = (D3D12::Texture*)pcmd->GetTexID();
if (tex && last_texture != tex)
{
#if 0
// for when we redo the descriptor stuff
D3D12::DescriptorHandle handle;
if (!g_d3d12_context->GetDescriptorAllocator().Allocate(1, &handle))
{
// ugh.
g_d3d12_context->ExecuteCommandList(false);
ctx = g_d3d12_context->GetCommandList();
ImGui_ImplDX12_SetupRenderState(draw_data, ctx);
if (!g_d3d12_context->GetDescriptorAllocator().Allocate(1, &handle))
Panic("Failed to allocate descriptor after cmdlist kick");
}
g_d3d12_context->GetDevice()->CopyDescriptorsSimple(1, handle, tex->GetSRVDescriptor(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
ctx->SetGraphicsRootDescriptorTable(1, handle);
#else
ctx->SetGraphicsRootDescriptorTable(1, tex->GetSRVDescriptor());
#endif
last_texture = tex;
}
ctx->RSSetScissorRects(1, &r);
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
}
}
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
} }
bool ImGui_ImplDX12_CreateFontsTexture() bool ImGui_ImplDX12_CreateFontsTexture()
{ {
// Build texture atlas // Build texture atlas
ImGuiIO & io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels; ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
int width, height; unsigned char* pixels;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system
D3D12::Texture texture;
if (!texture.Create(width, height, 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_RESOURCE_FLAG_NONE) ||
!texture.LoadData(0, 0, width, height, pixels, width * sizeof(u32)))
{
return false;
}
g_FontTexture = std::move(texture); // Upload texture to graphics system
if (bd->FontTexture.GetWidth() != static_cast<u32>(width) || bd->FontTexture.GetHeight() != static_cast<u32>(height))
// Store our identifier {
io.Fonts->TexID = reinterpret_cast<ImTextureID>(&g_FontTexture); if (!bd->FontTexture.Create(width, height, 1, DXGI_FORMAT_R8G8B8A8_UNORM,
return true; DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
D3D12_RESOURCE_FLAG_NONE))
{
return false;
}
}
#if 0
if (!bd->FontTexture.LoadData(g_d3d12_context->GetInitCommandList(), 0, 0, 0, width, height, pixels, width * sizeof(u32)))
return false;
#else
if (!bd->FontTexture.LoadData(0, 0, width, height, pixels, width * sizeof(u32)))
return false;
#endif
io.Fonts->SetTexID((ImTextureID)&bd->FontTexture);
return true;
} }
bool ImGui_ImplDX12_CreateDeviceObjects() bool ImGui_ImplDX12_CreateDeviceObjects()
{ {
if (!g_pd3dDevice) ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
return false; if (bd->pPipelineState)
if (g_pPipelineState) ImGui_ImplDX12_DestroyDeviceObjects();
ImGui_ImplDX12_InvalidateDeviceObjects();
// Create the root signature // Create the root signature
{ {
D3D12_DESCRIPTOR_RANGE descRange = {}; D3D12_DESCRIPTOR_RANGE descRange = {};
descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
descRange.NumDescriptors = 1; descRange.NumDescriptors = 1;
descRange.BaseShaderRegister = 0; descRange.BaseShaderRegister = 0;
descRange.RegisterSpace = 0; descRange.RegisterSpace = 0;
descRange.OffsetInDescriptorsFromTableStart = 0; descRange.OffsetInDescriptorsFromTableStart = 0;
D3D12_ROOT_PARAMETER param[2] = {}; D3D12_ROOT_PARAMETER param[2] = {};
param[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; param[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
param[0].Constants.ShaderRegister = 0; param[0].Constants.ShaderRegister = 0;
param[0].Constants.RegisterSpace = 0; param[0].Constants.RegisterSpace = 0;
param[0].Constants.Num32BitValues = 16; param[0].Constants.Num32BitValues = 16;
param[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; param[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
param[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; param[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
param[1].DescriptorTable.NumDescriptorRanges = 1; param[1].DescriptorTable.NumDescriptorRanges = 1;
param[1].DescriptorTable.pDescriptorRanges = &descRange; param[1].DescriptorTable.pDescriptorRanges = &descRange;
param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_STATIC_SAMPLER_DESC staticSampler = {}; // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; D3D12_STATIC_SAMPLER_DESC staticSampler = {};
staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler.MipLODBias = 0.f; staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler.MaxAnisotropy = 0; staticSampler.MipLODBias = 0.f;
staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; staticSampler.MaxAnisotropy = 0;
staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
staticSampler.MinLOD = 0.f; staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
staticSampler.MaxLOD = 0.f; staticSampler.MinLOD = 0.f;
staticSampler.ShaderRegister = 0; staticSampler.MaxLOD = 0.f;
staticSampler.RegisterSpace = 0; staticSampler.ShaderRegister = 0;
staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; staticSampler.RegisterSpace = 0;
staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_ROOT_SIGNATURE_DESC desc = {}; D3D12_ROOT_SIGNATURE_DESC desc = {};
desc.NumParameters = _countof(param); desc.NumParameters = _countof(param);
desc.pParameters = param; desc.pParameters = param;
desc.NumStaticSamplers = 1; desc.NumStaticSamplers = 1;
desc.pStaticSamplers = &staticSampler; desc.pStaticSamplers = &staticSampler;
desc.Flags = desc.Flags =
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
auto blob = g_d3d12_context->SerializeRootSignature(&desc); auto blob = g_d3d12_context->SerializeRootSignature(&desc);
if (!blob) if (!blob)
return false; return false;
g_pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&g_pRootSignature)); g_d3d12_context->GetDevice()->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature));
} }
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) // 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: // 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] // 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. // 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. // See https://github.com/ocornut/imgui/pull/638 for sources and details.
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc; D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC)); memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
psoDesc.NodeMask = 1; psoDesc.NodeMask = 1;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.pRootSignature = g_pRootSignature; psoDesc.pRootSignature = bd->pRootSignature;
psoDesc.SampleMask = UINT_MAX; psoDesc.SampleMask = UINT_MAX;
psoDesc.NumRenderTargets = 1; psoDesc.NumRenderTargets = 1;
psoDesc.RTVFormats[0] = g_RTVFormat; psoDesc.RTVFormats[0] = bd->RTVFormat;
psoDesc.SampleDesc.Count = 1; psoDesc.SampleDesc.Count = 1;
psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
ID3DBlob* vertexShaderBlob; ID3DBlob* vertexShaderBlob;
ID3DBlob* pixelShaderBlob; ID3DBlob* pixelShaderBlob;
// Create the vertex shader // Create the vertex shader
{ {
static const char* vertexShader = static const char* vertexShader =
"cbuffer vertexBuffer : register(b0) \ "cbuffer vertexBuffer : register(b0) \
{\ {\
float4x4 ProjectionMatrix; \ float4x4 ProjectionMatrix; \
};\ };\
@ -385,24 +398,24 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
return output;\ return output;\
}"; }";
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &vertexShaderBlob, NULL))) if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &vertexShaderBlob, NULL)))
return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
psoDesc.VS = { vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() }; psoDesc.VS = { vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() };
// Create the input layout // Create the input layout
static D3D12_INPUT_ELEMENT_DESC local_layout[] = static D3D12_INPUT_ELEMENT_DESC local_layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
};
psoDesc.InputLayout = { local_layout, 3 };
}
// Create the pixel shader
{ {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, static const char* pixelShader =
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, "struct PS_INPUT\
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, 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 pos : SV_POSITION;\
float4 col : COLOR0;\ float4 col : COLOR0;\
@ -417,117 +430,116 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
return out_col; \ return out_col; \
}"; }";
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &pixelShaderBlob, NULL))) if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &pixelShaderBlob, NULL)))
{ {
vertexShaderBlob->Release(); vertexShaderBlob->Release();
return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
}
psoDesc.PS = { pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() };
} }
psoDesc.PS = { pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() };
}
// Create the blending setup // Create the blending setup
{ {
D3D12_BLEND_DESC& desc = psoDesc.BlendState; D3D12_BLEND_DESC& desc = psoDesc.BlendState;
desc.AlphaToCoverageEnable = false; desc.AlphaToCoverageEnable = false;
desc.RenderTarget[0].BlendEnable = true; desc.RenderTarget[0].BlendEnable = true;
desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA; desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
} }
// Create the rasterizer state // Create the rasterizer state
{ {
D3D12_RASTERIZER_DESC& desc = psoDesc.RasterizerState; D3D12_RASTERIZER_DESC& desc = psoDesc.RasterizerState;
desc.FillMode = D3D12_FILL_MODE_SOLID; desc.FillMode = D3D12_FILL_MODE_SOLID;
desc.CullMode = D3D12_CULL_MODE_NONE; desc.CullMode = D3D12_CULL_MODE_NONE;
desc.FrontCounterClockwise = FALSE; desc.FrontCounterClockwise = FALSE;
desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
desc.DepthClipEnable = true; desc.DepthClipEnable = true;
desc.MultisampleEnable = FALSE; desc.MultisampleEnable = FALSE;
desc.AntialiasedLineEnable = FALSE; desc.AntialiasedLineEnable = FALSE;
desc.ForcedSampleCount = 0; desc.ForcedSampleCount = 0;
desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
} }
// Create depth-stencil State // Create depth-stencil State
{ {
D3D12_DEPTH_STENCIL_DESC& desc = psoDesc.DepthStencilState; D3D12_DEPTH_STENCIL_DESC& desc = psoDesc.DepthStencilState;
desc.DepthEnable = false; desc.DepthEnable = false;
desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
desc.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; desc.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
desc.StencilEnable = false; desc.StencilEnable = false;
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP; desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP;
desc.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; desc.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
desc.BackFace = desc.FrontFace; desc.BackFace = desc.FrontFace;
} }
HRESULT result_pipeline_state = g_pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&g_pPipelineState)); HRESULT result_pipeline_state = g_d3d12_context->GetDevice()->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineState));
vertexShaderBlob->Release(); vertexShaderBlob->Release();
pixelShaderBlob->Release(); pixelShaderBlob->Release();
if (result_pipeline_state != S_OK) if (result_pipeline_state != S_OK)
return false; return false;
return true; return true;
} }
void ImGui_ImplDX12_InvalidateDeviceObjects() void ImGui_ImplDX12_DestroyDeviceObjects()
{ {
if (!g_pd3dDevice) ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
return; if (!bd)
return;
ImGuiIO& io = ImGui::GetIO();
SafeRelease(g_pRootSignature); SafeRelease(bd->pRootSignature);
SafeRelease(g_pPipelineState); SafeRelease(bd->pPipelineState);
g_FontTexture.Destroy(true); bd->FontTexture.Destroy(false);
bd->VertexStreamBuffer.Destroy(false);
ImGuiIO& io = ImGui::GetIO(); bd->IndexStreamBuffer.Destroy(false);
io.Fonts->SetTexID(NULL); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. io.Fonts->SetTexID(NULL); // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
for (UINT i = 0; i < g_numFramesInFlight; i++)
{
FrameResources* fr = &g_pFrameResources[i];
SafeRelease(fr->IndexBuffer);
SafeRelease(fr->VertexBuffer);
}
} }
bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format) bool ImGui_ImplDX12_Init(DXGI_FORMAT rtv_format)
{ {
// Setup backend capabilities flags ImGuiIO& io = ImGui::GetIO();
ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
io.BackendRendererName = "imgui_impl_dx12";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
g_pd3dDevice = device; // Setup backend capabilities flags
g_RTVFormat = rtv_format; ImGui_ImplDX12_Data* bd = IM_NEW(ImGui_ImplDX12_Data)();
g_pFrameResources = new FrameResources[num_frames_in_flight]; io.BackendRendererUserData = (void*)bd;
g_numFramesInFlight = num_frames_in_flight; io.BackendRendererName = "imgui_impl_dx12";
g_frameIndex = UINT_MAX; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
// Create buffers with a default size (they will later be grown as needed) bd->RTVFormat = rtv_format;
for (int i = 0; i < num_frames_in_flight; i++)
{
FrameResources* fr = &g_pFrameResources[i];
fr->IndexBuffer = NULL;
fr->VertexBuffer = NULL;
fr->IndexBufferSize = 10000;
fr->VertexBufferSize = 5000;
}
return ImGui_ImplDX12_CreateDeviceObjects(); if (!bd->VertexStreamBuffer.Create(VERTEX_BUFFER_SIZE) || !bd->IndexStreamBuffer.Create(INDEX_BUFFER_SIZE))
return false;
return ImGui_ImplDX12_CreateDeviceObjects();
} }
void ImGui_ImplDX12_Shutdown() void ImGui_ImplDX12_Shutdown()
{ {
ImGui_ImplDX12_InvalidateDeviceObjects(); ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
delete[] g_pFrameResources; IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
g_pFrameResources = NULL; ImGuiIO& io = ImGui::GetIO();
g_pd3dDevice = NULL;
g_numFramesInFlight = 0; ImGui_ImplDX12_DestroyDeviceObjects();
g_frameIndex = UINT_MAX; io.BackendRendererName = NULL;
io.BackendRendererUserData = NULL;
IM_DELETE(bd);
}
void ImGui_ImplDX12_NewFrame()
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX12_Init()?");
if (!bd->pPipelineState)
ImGui_ImplDX12_CreateDeviceObjects();
} }

View file

@ -1,47 +1,14 @@
// dear imgui: Renderer Backend for DirectX12 // dear imgui: Renderer Backend for DirectX12
// This needs to be used along with a Platform Backend (e.g. Win32) // This needs to be used along with a Platform Backend (e.g. Win32)
// Implemented features:
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once #pragma once
#include "imgui.h" // IMGUI_IMPL_API #include "imgui.h" // IMGUI_IMPL_API
#ifdef _MSC_VER bool ImGui_ImplDX12_Init(DXGI_FORMAT rtv_format);
#pragma warning (push) void ImGui_ImplDX12_Shutdown();
#pragma warning (disable: 4471) // a forward declaration of an unscoped enumeration must have an underlying type void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data);
#endif
enum DXGI_FORMAT;
struct ID3D12Device;
struct ID3D12DescriptorHeap;
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_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format);
IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown();
IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list);
// Use if you want to reset your rendering device without losing Dear ImGui state. // Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects(); void ImGui_ImplDX12_DestroyDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects(); bool ImGui_ImplDX12_CreateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateFontsTexture(); bool ImGui_ImplDX12_CreateFontsTexture();
#ifdef _MSC_VER
#pragma warning (pop)
#endif

View file

@ -1,26 +1,47 @@
// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
// - Desktop GL: 2.x 3.x 4.x // - Desktop GL: 2.x 3.x 4.x
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features: // Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// https://github.com/ocornut/imgui // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2022-05-13: OpenGL: Fix state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states.
// 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.
// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state.
// 2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader.
// 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version.
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater.
// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
// 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix.
// 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset.
// 2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader.
// 2020-01-07: OpenGL: Added support for glbinding 3.x OpenGL loader.
// 2019-10-25: OpenGL: Using a combination of GL define and runtime GL version to decide whether to use glDrawElementsBaseVertex(). Fix building with pre-3.2 GL loaders.
// 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility. // 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility.
// 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call. // 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call.
// 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop. // 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop.
// 2019-03-15: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early. // 2019-03-15: OpenGL: Added a GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
// 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0). // 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0).
// 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader. // 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
@ -71,91 +92,110 @@
#else #else
#include <stdint.h> // intptr_t #include <stdint.h> // intptr_t
#endif #endif
#if defined(__APPLE__)
#include "TargetConditionals.h" // Clang warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#if __has_warning("-Wzero-as-null-pointer-constant")
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif
#endif #endif
// GL includes // GL includes
#include "common/gl/loader.h" #include "common/gl/loader.h"
// OpenGL Data // OpenGL Data
static char g_GlslVersionString[32] = ""; struct ImGui_ImplOpenGL3_Data
static GLuint g_FontTexture = 0; {
static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; GLuint GlVersion; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location char GlslVersionString[32]; // Specified by user or detected based on compile time GL settings.
static int g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location GLuint FontTexture;
static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; GLuint ShaderHandle;
static bool g_IsGLES = false; GLint AttribLocationTex; // Uniforms location
static bool g_IsGLES2 = false; GLint AttribLocationProjMtx;
GLuint AttribLocationVtxPos; // Vertex attributes location
GLuint AttribLocationVtxUV;
GLuint AttribLocationVtxColor;
unsigned int VboHandle, ElementsHandle, VaoHandle;
GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize;
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
}
// Functions // Functions
bool ImGui_ImplOpenGL3_Init(const char* glsl_version) bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{ {
// Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_opengl3"; io.BackendRendererName = "imgui_impl_opengl3";
// Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. // Query for GL version (e.g. 320 for GL 3.2)
if (GLAD_GL_ES_VERSION_3_0) GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major == 0 && minor == 0)
{ {
if (glsl_version == NULL) // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
glsl_version = "#version 300 es"; const char* gl_version = (const char*)glGetString(GL_VERSION);
g_IsGLES = true; sscanf(gl_version, "%d.%d", &major, &minor);
g_IsGLES2 = false;
} }
else if (GLAD_GL_ES_VERSION_2_0) bd->GlVersion = (GLuint)(major * 100 + minor * 10);
{
if (glsl_version == NULL) if (bd->GlVersion >= 320)
glsl_version = "#version 100"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
g_IsGLES = true;
g_IsGLES2 = true; // Store GLSL version string so we can refer to it later in case we recreate shaders.
} // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
else if (glsl_version == NULL)
{
if (glsl_version == NULL)
glsl_version = "#version 130"; glsl_version = "#version 130";
g_IsGLES = false;
g_IsGLES2 = false;
}
if (!g_IsGLES) IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. strcpy(bd->GlslVersionString, glsl_version);
strcat(bd->GlslVersionString, "\n");
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString));
#ifndef _MSC_VER
strcpy(g_GlslVersionString, glsl_version);
strcat(g_GlslVersionString, "\n");
#else
strncpy_s(g_GlslVersionString, sizeof(g_GlslVersionString), glsl_version, _TRUNCATE);
strncat_s(g_GlslVersionString, sizeof(g_GlslVersionString), "\n", _TRUNCATE);
#endif
return ImGui_ImplOpenGL3_CreateDeviceObjects(); return ImGui_ImplOpenGL3_CreateDeviceObjects();
} }
void ImGui_ImplOpenGL3_Shutdown() void ImGui_ImplOpenGL3_Shutdown()
{ {
ImGui_ImplOpenGL3_DestroyDeviceObjects(); ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
} IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
void ImGui_ImplOpenGL3_NewFrame() ImGui_ImplOpenGL3_DestroyDeviceObjects();
{ io.BackendRendererName = NULL;
if (!g_ShaderHandle) io.BackendRendererUserData = NULL;
ImGui_ImplOpenGL3_CreateDeviceObjects(); IM_DELETE(bd);
} }
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height) static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
{ {
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD); glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
#ifdef GL_POLYGON_MODE if (glPolygonMode)
if (!g_IsGLES)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// Setup viewport, orthographic projection matrix // Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
@ -171,47 +211,41 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
{ 0.0f, 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
}; };
glUseProgram(g_ShaderHandle); glUseProgram(bd->ShaderHandle);
glUniform1i(g_AttribLocationTex, 0); glUniform1i(bd->AttribLocationTex, 0);
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
if (!g_IsGLES2) // Bind vertex/index buffers and setup attributes for ImDrawVert
{ glBindVertexArray(bd->VaoHandle);
glBindVertexArray(g_VaoHandle); glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle);
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); glEnableVertexAttribArray(bd->AttribLocationVtxPos);
} glEnableVertexAttribArray(bd->AttribLocationVtxUV);
else glEnableVertexAttribArray(bd->AttribLocationVtxColor);
{ glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
glEnableVertexAttribArray(g_AttribLocationVtxPos);
glEnableVertexAttribArray(g_AttribLocationVtxUV);
glEnableVertexAttribArray(g_AttribLocationVtxColor);
glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
(GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
(GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert),
(GLvoid*)IM_OFFSETOF(ImDrawVert, col));
}
} }
// OpenGL3 Render function. // OpenGL3 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) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. // This is in order to be able to run within an OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
{ {
// Avoid rendering when minimized // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x); int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
if (fb_width <= 0 || fb_height <= 0) if (fb_width <= 0 || fb_height <= 0)
return; return;
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
// Setup desired GL state
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height); ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height);
// Will project scissor/clipping rectangles into framebuffer space // Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists // Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
@ -219,8 +253,20 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
// Upload vertex/index buffers // Upload vertex/index buffers
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
if (bd->VertexBufferSize < vtx_buffer_size)
{
bd->VertexBufferSize = vtx_buffer_size;
glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW);
}
if (bd->IndexBufferSize < idx_buffer_size)
{
bd->IndexBufferSize = idx_buffer_size;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW);
}
glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data);
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{ {
@ -237,92 +283,73 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
else else
{ {
// Project scissor/clipping rectangles into framebuffer space // Project scissor/clipping rectangles into framebuffer space
ImVec4 clip_rect; ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
clip_rect.x = pcmd->ClipRect.x - clip_off.x; ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
clip_rect.y = pcmd->ClipRect.y - clip_off.y; if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
clip_rect.z = pcmd->ClipRect.z - clip_off.x; continue;
clip_rect.w = pcmd->ClipRect.w - clip_off.y;
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
{ glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
// Apply scissor/clipping rectangle
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
// Bind texture, Draw // Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
if (!g_IsGLES)
glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
else
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)));
}
} }
} }
} }
if (!g_IsGLES2) glBindVertexArray(0);
{
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
else
{
glDisableVertexAttribArray(g_AttribLocationVtxPos);
glDisableVertexAttribArray(g_AttribLocationVtxUV);
glDisableVertexAttribArray(g_AttribLocationVtxColor);
}
} }
bool ImGui_ImplOpenGL3_CreateFontsTexture() bool ImGui_ImplOpenGL3_CreateFontsTexture()
{ {
// Build texture atlas
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
// Build texture atlas
unsigned char* pixels; unsigned char* pixels;
int width, height; int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
// Upload texture to graphics system // Upload texture to graphics system
GLint last_texture; // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); if (bd->FontTexture == 0)
glGenTextures(1, &g_FontTexture); glGenTextures(1, &bd->FontTexture);
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
glBindTexture(GL_TEXTURE_2D, bd->FontTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#ifdef GL_UNPACK_ROW_LENGTH glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier // Store our identifier
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture; io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
// Restore state
glBindTexture(GL_TEXTURE_2D, last_texture);
io.Fonts->ClearTexData();
return true; return true;
} }
void ImGui_ImplOpenGL3_DestroyFontsTexture() void ImGui_ImplOpenGL3_DestroyFontsTexture()
{ {
if (g_FontTexture) ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
if (bd->FontTexture)
{ {
ImGuiIO& io = ImGui::GetIO(); glDeleteTextures(1, &bd->FontTexture);
glDeleteTextures(1, &g_FontTexture); io.Fonts->SetTexID(0);
io.Fonts->TexID = 0; bd->FontTexture = 0;
g_FontTexture = 0;
} }
} }
// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
static bool CheckShader(GLuint handle, const char* desc) static bool CheckShader(GLuint handle, const char* desc)
{ {
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
GLint status = 0, log_length = 0; GLint status = 0, log_length = 0;
glGetShaderiv(handle, GL_COMPILE_STATUS, &status); glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
if ((GLboolean)status == GL_FALSE) if ((GLboolean)status == GL_FALSE)
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc); fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString);
if (log_length > 1) if (log_length > 1)
{ {
ImVector<char> buf; ImVector<char> buf;
@ -336,11 +363,12 @@ static bool CheckShader(GLuint handle, const char* desc)
// If you get an error please report on GitHub. You may try different GL context version or GLSL version. // If you get an error please report on GitHub. You may try different GL context version or GLSL version.
static bool CheckProgram(GLuint handle, const char* desc) static bool CheckProgram(GLuint handle, const char* desc)
{ {
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
GLint status = 0, log_length = 0; GLint status = 0, log_length = 0;
glGetProgramiv(handle, GL_LINK_STATUS, &status); glGetProgramiv(handle, GL_LINK_STATUS, &status);
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
if ((GLboolean)status == GL_FALSE) if ((GLboolean)status == GL_FALSE)
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString); fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString);
if (log_length > 1) if (log_length > 1)
{ {
ImVector<char> buf; ImVector<char> buf;
@ -353,22 +381,11 @@ static bool CheckProgram(GLuint handle, const char* desc)
bool ImGui_ImplOpenGL3_CreateDeviceObjects() bool ImGui_ImplOpenGL3_CreateDeviceObjects()
{ {
// Backup GL state ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
GLint last_texture, last_array_buffer;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
#ifndef IMGUI_IMPL_OPENGL_ES2
GLint last_vertex_array;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
#endif
// Parse GLSL version string // Parse GLSL version string
int glsl_version = 130; int glsl_version = 130;
#ifndef _MSC_VER sscanf(bd->GlslVersionString, "#version %d", &glsl_version);
sscanf(g_GlslVersionString, "#version %d", &glsl_version);
#else
sscanf_s(g_GlslVersionString, "#version %d", &glsl_version);
#endif
const GLchar* vertex_shader_glsl_120 = const GLchar* vertex_shader_glsl_120 =
"uniform mat4 ProjMtx;\n" "uniform mat4 ProjMtx;\n"
@ -399,7 +416,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
"}\n"; "}\n";
const GLchar* vertex_shader_glsl_300_es = const GLchar* vertex_shader_glsl_300_es =
"precision mediump float;\n" "precision highp float;\n"
"layout (location = 0) in vec2 Position;\n" "layout (location = 0) in vec2 Position;\n"
"layout (location = 1) in vec2 UV;\n" "layout (location = 1) in vec2 UV;\n"
"layout (location = 2) in vec4 Color;\n" "layout (location = 2) in vec4 Color;\n"
@ -495,73 +512,54 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
} }
// Create shaders // Create shaders
const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader }; const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
g_VertHandle = glCreateShader(GL_VERTEX_SHADER); GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL); glShaderSource(vert_handle, 2, vertex_shader_with_version, NULL);
glCompileShader(g_VertHandle); glCompileShader(vert_handle);
CheckShader(g_VertHandle, "vertex shader"); CheckShader(vert_handle, "vertex shader");
const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader }; const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL); glShaderSource(frag_handle, 2, fragment_shader_with_version, NULL);
glCompileShader(g_FragHandle); glCompileShader(frag_handle);
CheckShader(g_FragHandle, "fragment shader"); CheckShader(frag_handle, "fragment shader");
g_ShaderHandle = glCreateProgram(); // Link
glAttachShader(g_ShaderHandle, g_VertHandle); bd->ShaderHandle = glCreateProgram();
glAttachShader(g_ShaderHandle, g_FragHandle); glAttachShader(bd->ShaderHandle, vert_handle);
glLinkProgram(g_ShaderHandle); glAttachShader(bd->ShaderHandle, frag_handle);
CheckProgram(g_ShaderHandle, "shader program"); glLinkProgram(bd->ShaderHandle);
CheckProgram(bd->ShaderHandle, "shader program");
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); glDetachShader(bd->ShaderHandle, vert_handle);
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); glDetachShader(bd->ShaderHandle, frag_handle);
g_AttribLocationVtxPos = glGetAttribLocation(g_ShaderHandle, "Position"); glDeleteShader(vert_handle);
g_AttribLocationVtxUV = glGetAttribLocation(g_ShaderHandle, "UV"); glDeleteShader(frag_handle);
g_AttribLocationVtxColor = glGetAttribLocation(g_ShaderHandle, "Color");
bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture");
bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx");
bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position");
bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV");
bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color");
// Create buffers // Create buffers
glGenBuffers(1, &g_VboHandle); glGenBuffers(1, &bd->VboHandle);
glGenBuffers(1, &g_ElementsHandle); glGenBuffers(1, &bd->ElementsHandle);
glGenVertexArrays(1, &bd->VaoHandle);
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
glBufferData(GL_ARRAY_BUFFER, sizeof(ImDrawVert), nullptr, GL_STREAM_DRAW);
if (!g_IsGLES2)
{
glGenVertexArrays(1, &g_VaoHandle);
glBindVertexArray(g_VaoHandle);
glEnableVertexAttribArray(g_AttribLocationVtxPos);
glEnableVertexAttribArray(g_AttribLocationVtxUV);
glEnableVertexAttribArray(g_AttribLocationVtxColor);
glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
(GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
(GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert),
(GLvoid*)IM_OFFSETOF(ImDrawVert, col));
}
// Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
if (!g_IsGLES2)
glBindVertexArray(last_vertex_array);
return true; return true;
} }
void ImGui_ImplOpenGL3_DestroyDeviceObjects() void ImGui_ImplOpenGL3_DestroyDeviceObjects()
{ {
if (g_VaoHandle) { glDeleteVertexArrays(1, &g_VaoHandle); g_VaoHandle = 0; } ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
if (g_VboHandle) { glDeleteBuffers(1, &g_VboHandle); g_VboHandle = 0; } if (bd->VaoHandle) { glDeleteVertexArrays(1, &bd->VaoHandle); bd->VaoHandle = 0; }
if (g_ElementsHandle) { glDeleteBuffers(1, &g_ElementsHandle); g_ElementsHandle = 0; } if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
if (g_ShaderHandle && g_VertHandle) { glDetachShader(g_ShaderHandle, g_VertHandle); } if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
if (g_ShaderHandle && g_FragHandle) { glDetachShader(g_ShaderHandle, g_FragHandle); } if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
if (g_VertHandle) { glDeleteShader(g_VertHandle); g_VertHandle = 0; }
if (g_FragHandle) { glDeleteShader(g_FragHandle); g_FragHandle = 0; }
if (g_ShaderHandle) { glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; }
ImGui_ImplOpenGL3_DestroyFontsTexture(); ImGui_ImplOpenGL3_DestroyFontsTexture();
} }
#if defined(__clang__)
#pragma clang diagnostic pop
#endif

View file

@ -1,36 +1,16 @@
// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
// - Desktop GL: 2.x 3.x 4.x // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices.
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// About Desktop OpenGL function loaders:
// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
// About GLSL version:
// The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string.
// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
#pragma once #pragma once
#include "imgui.h" // IMGUI_IMPL_API
// Backend API // Backend API
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); void ImGui_ImplOpenGL3_Shutdown();
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
// (Optional) Called by Init/NewFrame/Shutdown // (Optional) Called by Init/NewFrame/Shutdown
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); bool ImGui_ImplOpenGL3_CreateFontsTexture();
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); void ImGui_ImplOpenGL3_DestroyFontsTexture();
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); bool ImGui_ImplOpenGL3_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); void ImGui_ImplOpenGL3_DestroyDeviceObjects();

File diff suppressed because it is too large Load diff

View file

@ -1,124 +1,12 @@
// dear imgui: Renderer for Vulkan // dear imgui: Renderer Backend for Vulkan
// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..) // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
// Missing features:
// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
// https://github.com/ocornut/imgui
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
// You will use those if you want to use this rendering back-end in your engine/app.
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
// Read comments in imgui_impl_vulkan.h.
#pragma once #pragma once
#include "imgui.h" // IMGUI_IMPL_API
#include "common/vulkan/loader.h" #include "common/vulkan/loader.h"
// Initialization data, for ImGui_ImplVulkan_Init()
// [Please zero-clear before use!]
struct ImGui_ImplVulkan_InitInfo
{
VkInstance Instance;
VkPhysicalDevice PhysicalDevice;
VkDevice Device;
uint32_t QueueFamily;
VkQueue Queue;
VkPipelineCache PipelineCache;
uint32_t MinImageCount; // >= 2
uint32_t ImageCount; // >= MinImageCount
VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
const VkAllocationCallbacks* Allocator;
void (*CheckVkResultFn)(VkResult err);
};
// Called by user code // Called by user code
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass); bool ImGui_ImplVulkan_Init(VkRenderPass render_pass);
IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); void ImGui_ImplVulkan_Shutdown();
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer); void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); bool ImGui_ImplVulkan_CreateFontsTexture();
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)
//-------------------------------------------------------------------------
// You probably do NOT need to use or care about those functions.
// Those functions only exist because:
// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
// 2) the upcoming multi-viewport feature will need them internally.
// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
// but it is too much code to duplicate everywhere so we exceptionally expose them.
//
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
//-------------------------------------------------------------------------
struct ImGui_ImplVulkanH_Frame;
struct ImGui_ImplVulkanH_Window;
// Helpers
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator);
IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);
// Helper structure to hold the data needed by one rendering frame
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
// [Please zero-clear before use!]
struct ImGui_ImplVulkanH_Frame
{
VkCommandPool CommandPool;
VkCommandBuffer CommandBuffer;
VkFence Fence;
VkImage Backbuffer;
VkImageView BackbufferView;
VkFramebuffer Framebuffer;
};
struct ImGui_ImplVulkanH_FrameSemaphores
{
VkSemaphore ImageAcquiredSemaphore;
VkSemaphore RenderCompleteSemaphore;
};
// Helper structure to hold the data needed by one rendering context into one OS window
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
struct ImGui_ImplVulkanH_Window
{
int Width;
int Height;
VkSwapchainKHR Swapchain;
VkSurfaceKHR Surface;
VkSurfaceFormatKHR SurfaceFormat;
VkPresentModeKHR PresentMode;
VkRenderPass RenderPass;
bool ClearEnable;
VkClearValue ClearValue;
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
ImGui_ImplVulkanH_Frame* Frames;
ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores;
ImGui_ImplVulkanH_Window()
{
memset(this, 0, sizeof(*this));
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
ClearEnable = true;
}
};

View file

@ -532,18 +532,7 @@ void VulkanHostDisplay::DestroyResources()
bool VulkanHostDisplay::CreateImGuiContext() bool VulkanHostDisplay::CreateImGuiContext()
{ {
ImGui_ImplVulkan_InitInfo vii = {}; return ImGui_ImplVulkan_Init(m_swap_chain->GetClearRenderPass());
vii.Instance = g_vulkan_context->GetVulkanInstance();
vii.PhysicalDevice = g_vulkan_context->GetPhysicalDevice();
vii.Device = g_vulkan_context->GetDevice();
vii.QueueFamily = g_vulkan_context->GetGraphicsQueueFamilyIndex();
vii.Queue = g_vulkan_context->GetGraphicsQueue();
vii.PipelineCache = g_vulkan_shader_cache->GetPipelineCache();
vii.MinImageCount = m_swap_chain->GetImageCount();
vii.ImageCount = m_swap_chain->GetImageCount();
vii.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
return ImGui_ImplVulkan_Init(&vii, m_swap_chain->GetClearRenderPass());
} }
void VulkanHostDisplay::DestroyImGuiContext() void VulkanHostDisplay::DestroyImGuiContext()
@ -556,8 +545,7 @@ bool VulkanHostDisplay::UpdateImGuiFontTexture()
{ {
// Just in case we were drawing something. // Just in case we were drawing something.
g_vulkan_context->ExecuteCommandBuffer(true); g_vulkan_context->ExecuteCommandBuffer(true);
ImGui_ImplVulkan_DestroyFontUploadObjects(); return ImGui_ImplVulkan_CreateFontsTexture();
return ImGui_ImplVulkan_CreateFontsTexture(g_vulkan_context->GetCurrentCommandBuffer());
} }
void VulkanHostDisplay::DestroyRenderDevice() void VulkanHostDisplay::DestroyRenderDevice()
@ -846,7 +834,7 @@ void VulkanHostDisplay::RenderImGui()
{ {
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(), "Imgui"); const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(), "Imgui");
ImGui::Render(); ImGui::Render();
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), g_vulkan_context->GetCurrentCommandBuffer()); ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData());
} }
void VulkanHostDisplay::RenderSoftwareCursor() void VulkanHostDisplay::RenderSoftwareCursor()