The bgfx renderer uses the bgfx library to do rendering operations in an API-agnostic manner.
Testing the bgfx renderer
Building
In your root project directory, clone bgfx.cmake with submodules:
user $ git clone https://github.com/bkaradzic/bgfx.cmake --recursive
Next, in your Config/cmake/UImGuiDemo.cmake, make sure your custom setup and compile steps look like this:
function(custom_setup_step)
# bgfx.cmake declares these with option(), and CMP0077 makes option() defer to a variable that already
# exists, so setting them here wins without editing anything inside the bgfx.cmake checkout
set(BGFX_CONFIG_MULTITHREADED OFF CACHE BOOL "" FORCE)
set(BGFX_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
set(BGFX_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BGFX_INSTALL OFF CACHE BOOL "" FORCE)
add_subdirectory(bgfx.cmake/ EXCLUDE_FROM_ALL)
if(EMSCRIPTEN)
# bx.cmake adds -msse4.2 as PUBLIC, which propagates to bimg_encode via
# its public bx link. That defines __SSE4_1__, causing ProcessRGB.cpp to
# include <x86intrin.h>, which pulls in ia32intrin.h with non-WASM builtins
# (RDPMC, WBINVD, EFLAGS, etc.) that have no WebAssembly equivalent.
# Strip the flag from bx's propagated interface; bx itself retains it in
# its own COMPILE_OPTIONS for internal SIMD math.
get_target_property(_bx_iface_opts bx INTERFACE_COMPILE_OPTIONS)
if(_bx_iface_opts)
list(REMOVE_ITEM _bx_iface_opts "$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-msse4.2>")
set_target_properties(bx PROPERTIES INTERFACE_COMPILE_OPTIONS "${_bx_iface_opts}")
endif()
target_compile_options(bx PUBLIC -msimd128)
endif()
endfunction()
function(custom_compile_step)
if (EMSCRIPTEN)
target_link_libraries(UImGuiDemo bgfx)
elseif (WIN32)
target_link_libraries(UntitledImGuiFramework bgfx)
target_compile_options(UntitledImGuiFramework PRIVATE "/Zc:preprocessor")
else ()
target_link_libraries(UImGuiDemoLib bgfx)
endif ()
include_directories(bgfx.cmake/bgfx/include bgfx.cmake/bx/include bgfx.cmake/bimg/include)
endfunction()
Caution
BGFX_CONFIG_MULTITHREADED must be OFF. Leaving it enabled will result in nothing being output to the
screen, as the example backend code is not written to be used in a multithreaded configuration.
Tip
BGFX_BUILD_TOOLS, BGFX_BUILD_EXAMPLES and BGFX_INSTALL are turned off purely to save build time.
The example backend renders dear imgui with the pre-compiled shader blobs in vs_ocornut_imgui.bin.h and
fs_ocornut_imgui.bin.h through BGFX_EMBEDDED_SHADER, so shaderc is never needed to build it.
Important
EXCLUDE_FROM_ALL on the add_subdirectory call is what keeps the build to the targets you actually
link. Without it, the default all target additionally builds bimg_decode and bimg_encode, which
nothing here uses - they exist for the texturec tool and the bgfx examples, both disabled above.
That is not only wasted build time. bimg_decode compiles bimg’s vendored copy of libavif, whose
src/io.c uses static_assert without including <assert.h>. static_assert only became a keyword in
C23, so on a libc that does not pull assert.h in transitively the way glibc does - notably emscripten’s -
the file fails to compile and takes the whole build down with it. Clang builds on macOS hit the same thing.
Integrating the renderer
In Source/Instance.hpp, include the bgfx renderer:
#include <UImGuiRendererExamples/bgfx/bgfx.hpp>
And create an instance of the UImGuiRendererExamples::BGFXRenderer class as a member variable inside the UImGuiDemo::Instance class.
Important
Setting renderer: custom also points the texture backend at the custom slot, because
RendererInternal::loadConfig sets textureRendererType from rendererType. If you register a custom
renderer without also registering a custom texture, every UImGui::Texture fails with
“Invalid custom renderer backend!”. Unless you redirect UImGui::Renderer::data().textureRendererType at
one of the built-in backends, follow the “Integrating the custom texture” section below as well.
After that, in Source/Instance.cpp, make sure your constructor looks like this:
UImGuiDemo::Instance::Instance() noexcept
{
initInfo =
{
.titlebarComponents = { reinterpret_cast<UImGui::TitlebarComponent*>(&title) },
.windowComponents = { reinterpret_cast<UImGui::WindowComponent*>(&demoWindow) },
.customRenderer = &bgfxRenderer,
UIMGUI_INIT_INFO_DEFAULT_DIRS,
};
}
Integrating the custom texture
A custom texture renderer is also provided. To use it, include the following in Source/Instance.hpp:
#include <UImGuiRendererExamples/bgfx/bgfx.hpp>
#include <UImGuiRendererExamples/bgfx/bgfx_texture.hpp>
Create an instance of UImGuiRendererExamples::BGFXTexture as a member variable inside the UImGuiDemo::Instance class and then pass the instance to the init info:
UImGuiDemo::Instance::Instance() noexcept
{
initInfo =
{
.titlebarComponents = { reinterpret_cast<UImGui::TitlebarComponent*>(&title) },
.windowComponents = { reinterpret_cast<UImGui::WindowComponent*>(&demoWindow) },
.customRenderer = &bgfxRenderer,
.customTexture = &bgfxTexture,
UIMGUI_INIT_INFO_DEFAULT_DIRS,
};
}
Testing
The example bgfx renderer can run on any operating system that is supported by the framework. It can also be compiled with Emscripten for targeting WASM.