aurora: imgui over SDL/WebGPU

This commit is contained in:
Luke Street 2022-02-17 01:03:00 -05:00
parent e866245f60
commit dcc040c7e0
7 changed files with 155 additions and 26 deletions

View File

@ -14,7 +14,10 @@ add_library(aurora STATIC
lib/imgui.cpp lib/imgui.cpp
lib/dawn/BackendBinding.cpp lib/dawn/BackendBinding.cpp
lib/gfx/common.cpp lib/gfx/common.cpp
../extern/imgui/backends/imgui_impl_sdl.cpp
../extern/imgui/backends/imgui_impl_wgpu.cpp
) )
target_compile_definitions(aurora PRIVATE IMGUI_USER_CONFIG="imconfig_user.h") # IMGUI_USE_WCHAR32
target_include_directories(aurora PUBLIC include ../Runtime) target_include_directories(aurora PUBLIC include ../Runtime)
target_include_directories(aurora PRIVATE ../imgui ../extern/imgui) target_include_directories(aurora PRIVATE ../imgui ../extern/imgui)
target_link_libraries(aurora PRIVATE dawn_native dawncpp webgpu_dawn zeus logvisor SDL2-static) target_link_libraries(aurora PRIVATE dawn_native dawncpp webgpu_dawn zeus logvisor SDL2-static)

View File

@ -21,6 +21,10 @@
#include "dawn/BackendBinding.hpp" #include "dawn/BackendBinding.hpp"
// imgui
#include <backends/imgui_impl_sdl.h>
#include <backends/imgui_impl_wgpu.h>
namespace aurora { namespace aurora {
// TODO: Move global state to a class/struct? // TODO: Move global state to a class/struct?
static logvisor::Module Log("aurora"); static logvisor::Module Log("aurora");
@ -42,8 +46,8 @@ static wgpu::BackendType preferredBackendType = wgpu::BackendType::OpenGL;
static std::unique_ptr<dawn::native::Instance> g_Instance; static std::unique_ptr<dawn::native::Instance> g_Instance;
static dawn::native::Adapter g_Adapter; static dawn::native::Adapter g_Adapter;
static wgpu::AdapterProperties g_AdapterProperties; static wgpu::AdapterProperties g_AdapterProperties;
static wgpu::Device g_Device; wgpu::Device g_Device;
static wgpu::Queue g_Queue; wgpu::Queue g_Queue;
static wgpu::SwapChain g_SwapChain; static wgpu::SwapChain g_SwapChain;
static std::unique_ptr<utils::BackendBinding> g_BackendBinding; static std::unique_ptr<utils::BackendBinding> g_BackendBinding;
@ -65,6 +69,8 @@ static void set_window_icon(Icon icon) noexcept {
static bool poll_events() noexcept { static bool poll_events() noexcept {
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event) != 0) { while (SDL_PollEvent(&event) != 0) {
ImGui_ImplSDL2_ProcessEvent(&event);
switch (event.type) { switch (event.type) {
case SDL_WINDOWEVENT: { case SDL_WINDOWEVENT: {
switch (event.window.event) { switch (event.window.event) {
@ -75,14 +81,6 @@ static bool poll_events() noexcept {
break; break;
} }
case SDL_WINDOWEVENT_EXPOSED: { case SDL_WINDOWEVENT_EXPOSED: {
/* TODO: ImGui code? */
/* TODO: Frame Time */
// g_AppDelegate->onAppIdle(1/60.f);
/* TODO: Render Texture */
// g_AppDelegate->onAppDraw();
/* TODO: ImGui present code? */
/* TODO: Present */
// g_AppDelegate->onAppPostDraw();
break; break;
} }
case SDL_WINDOWEVENT_MOVED: { case SDL_WINDOWEVENT_MOVED: {
@ -90,6 +88,8 @@ static bool poll_events() noexcept {
break; break;
} }
case SDL_WINDOWEVENT_RESIZED: { case SDL_WINDOWEVENT_RESIZED: {
auto format = static_cast<wgpu::TextureFormat>(g_BackendBinding->GetPreferredSwapChainTextureFormat());
g_SwapChain.Configure(format, wgpu::TextureUsage::RenderAttachment, event.window.data1, event.window.data2);
g_AppDelegate->onAppWindowResized( g_AppDelegate->onAppWindowResized(
{static_cast<uint32_t>(event.window.data1), static_cast<uint32_t>(event.window.data2)}); {static_cast<uint32_t>(event.window.data1), static_cast<uint32_t>(event.window.data2)});
break; break;
@ -162,12 +162,21 @@ static bool poll_events() noexcept {
break; break;
} }
case SDL_KEYDOWN: { case SDL_KEYDOWN: {
if (!ImGui::GetIO().WantCaptureKeyboard) {
// TODO
}
break; break;
} }
case SDL_KEYUP: { case SDL_KEYUP: {
if (!ImGui::GetIO().WantCaptureKeyboard) {
// TODO
}
break; break;
} }
case SDL_TEXTINPUT: { case SDL_TEXTINPUT: {
if (!ImGui::GetIO().WantCaptureKeyboard) {
// TODO
}
break; break;
} }
case SDL_QUIT: case SDL_QUIT:
@ -176,12 +185,12 @@ static bool poll_events() noexcept {
return false; return false;
} }
// TODO why doesn't this work? // TODO why doesn't this work?
const auto typedEvent = magic_enum::enum_cast<SDL_EventType>(event.type); // const auto typedEvent = magic_enum::enum_cast<SDL_EventType>(event.type);
if (typedEvent) { // if (typedEvent) {
Log.report(logvisor::Info, FMT_STRING("Received SDL event: {}"), magic_enum::enum_name(typedEvent.value())); // Log.report(logvisor::Info, FMT_STRING("Received SDL event: {}"), magic_enum::enum_name(typedEvent.value()));
} else { // } else {
Log.report(logvisor::Info, FMT_STRING("Received SDL event: {}"), event.type); // Log.report(logvisor::Info, FMT_STRING("Received SDL event: {}"), event.type);
} // }
} }
return true; return true;
} }
@ -262,16 +271,40 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
g_SwapChain.Configure(format, wgpu::TextureUsage::RenderAttachment, size.width, size.height); g_SwapChain.Configure(format, wgpu::TextureUsage::RenderAttachment, size.width, size.height);
} }
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = nullptr;
g_AppDelegate->onImGuiInit(1.f); // TODO scale
ImGui_ImplSDL2_InitForMetal(g_Window);
ImGui_ImplWGPU_Init(g_Device.Get(), 1, g_BackendBinding->GetPreferredSwapChainTextureFormat());
g_AppDelegate->onImGuiAddTextures();
g_AppDelegate->onAppLaunched(); g_AppDelegate->onAppLaunched();
g_AppDelegate->onAppWindowResized(get_window_size()); g_AppDelegate->onAppWindowResized(get_window_size());
bool showDemo = true;
while (poll_events()) { while (poll_events()) {
ImGui_ImplWGPU_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
g_AppDelegate->onAppIdle(ImGui::GetIO().DeltaTime);
const wgpu::TextureView view = g_SwapChain.GetCurrentTextureView();
g_AppDelegate->onAppDraw();
if (showDemo) {
ImGui::ShowDemoWindow(&showDemo);
}
ImGui::Render();
auto encoder = g_Device.CreateCommandEncoder(); auto encoder = g_Device.CreateCommandEncoder();
{ {
std::array<wgpu::RenderPassColorAttachment, 1> attachments{wgpu::RenderPassColorAttachment{ std::array<wgpu::RenderPassColorAttachment, 1> attachments{wgpu::RenderPassColorAttachment{
.view = g_SwapChain.GetCurrentTextureView(), .view = view,
.loadOp = wgpu::LoadOp::Clear, .loadOp = wgpu::LoadOp::Clear,
.storeOp = wgpu::StoreOp::Store, .storeOp = wgpu::StoreOp::Store,
.clearColor = {0.5f, 0.5f, 0.5f, 1.f}, .clearColor = {0.f, 0.f, 0.f, 0.f},
}}; }};
auto renderPassDescriptor = wgpu::RenderPassDescriptor{ auto renderPassDescriptor = wgpu::RenderPassDescriptor{
.label = "Render Pass", .label = "Render Pass",
@ -279,13 +312,18 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
.colorAttachments = attachments.data(), .colorAttachments = attachments.data(),
}; };
auto pass = encoder.BeginRenderPass(&renderPassDescriptor); auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass.Get());
pass.End(); pass.End();
} }
const auto buffer = encoder.Finish(); const auto buffer = encoder.Finish();
g_Queue.Submit(1, &buffer); g_Queue.Submit(1, &buffer);
g_SwapChain.Present(); g_SwapChain.Present();
g_AppDelegate->onAppPostDraw();
} }
g_AppDelegate->onAppExiting();
wgpuSwapChainRelease(g_SwapChain.Release()); wgpuSwapChainRelease(g_SwapChain.Release());
wgpuQueueRelease(g_Queue.Release()); wgpuQueueRelease(g_Queue.Release());
g_BackendBinding.reset(); g_BackendBinding.reset();

View File

@ -1,7 +1,44 @@
#include <aurora/imgui.hpp> #include <aurora/imgui.hpp>
#include <dawn/webgpu_cpp.h>
namespace aurora {
extern wgpu::Device g_Device;
extern wgpu::Queue g_Queue;
} // namespace aurora
namespace aurora::imgui { namespace aurora::imgui {
ImTextureID add_texture(uint32_t width, uint32_t height, ArrayRef<uint8_t> data) noexcept { ImTextureID add_texture(uint32_t width, uint32_t height, ArrayRef<uint8_t> data) noexcept {
return 0; // TODO const auto size = wgpu::Extent3D{
.width = width,
.height = height,
};
const auto textureDescriptor = wgpu::TextureDescriptor{
.label = "imgui texture",
.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst,
.size = size,
.format = wgpu::TextureFormat::RGBA8Unorm,
};
const auto textureViewDescriptor = wgpu::TextureViewDescriptor{
.label = "imgui texture view",
.format = wgpu::TextureFormat::RGBA8Unorm,
.dimension = wgpu::TextureViewDimension::e2D,
.mipLevelCount = 1,
.arrayLayerCount = 1,
};
auto texture = g_Device.CreateTexture(&textureDescriptor);
auto textureView = texture.CreateView(&textureViewDescriptor);
{
const auto dstView = wgpu::ImageCopyTexture{
.texture = texture,
};
const auto dataLayout = wgpu::TextureDataLayout{
.bytesPerRow = 4 * width,
.rowsPerImage = height,
};
g_Queue.WriteTexture(&dstView, data.data(), data.size(), &dataLayout, &size);
}
texture.Release(); // leak some memory!
return textureView.Release();
} }
} // namespace aurora::imgui } // namespace aurora::imgui

2
extern/imgui vendored

@ -1 +1 @@
Subproject commit e3e1fbcf025cf83413815751f7c33500e1314d57 Subproject commit 5c8f8d031166765d2f1e2ac2de27df6d3691c05a

View File

@ -5,14 +5,14 @@ add_library(imgui
../extern/imgui/imgui_tables.cpp ../extern/imgui/imgui_tables.cpp
../extern/imgui/imgui_widgets.cpp ../extern/imgui/imgui_widgets.cpp
../extern/imgui/misc/cpp/imgui_stdlib.cpp ../extern/imgui/misc/cpp/imgui_stdlib.cpp
../imgui-sys/third-party/cimgui.cpp # ../imgui-sys/third-party/cimgui.cpp
ImGuiEngine.cpp ImGuiEngine.cpp
ImGuiEngine.hpp ImGuiEngine.hpp
NotoMono.cpp NotoMono.cpp
MetaforceIcon.cpp MetaforceIcon.cpp
) )
target_include_directories(imgui PUBLIC ${CMAKE_SOURCE_DIR}/extern/imgui ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(imgui PUBLIC ${CMAKE_SOURCE_DIR}/extern/imgui ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG="imconfig_user.h" IMGUI_USE_WCHAR32) target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG="imconfig_user.h") # IMGUI_USE_WCHAR32
if (CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_COMPILER_IS_GNUCXX)
# currently explicitly ignored for clang in imgui code, but not gcc (yet) # currently explicitly ignored for clang in imgui code, but not gcc (yet)
target_compile_options(imgui PRIVATE -Wno-deprecated-enum-enum-conversion) target_compile_options(imgui PRIVATE -Wno-deprecated-enum-enum-conversion)

View File

@ -53,7 +53,61 @@ void ImGuiEngine_Initialize(float scale) {
#endif #endif
ImGuiEngine::fontLarge = io.Fonts->AddFont(&fontConfig); ImGuiEngine::fontLarge = io.Fonts->AddFont(&fontConfig);
ImGui::GetStyle().ScaleAllSizes(scale); auto& style = ImGui::GetStyle();
style.FrameRounding = 4.0f;
style.GrabRounding = 4.0f;
auto colors = style.Colors;
colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f);
colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.20f, 0.25f, 0.29f, 0.55f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
colors[ImGuiCol_TabHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
style.ScaleAllSizes(scale);
} }
Icon GetIcon() { Icon GetIcon() {

View File

@ -4,9 +4,6 @@
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// To match imgui-sys
#define ImTextureID size_t
#define IM_VEC2_CLASS_EXTRA \ #define IM_VEC2_CLASS_EXTRA \
ImVec2(const zeus::CVector2f& v) { \ ImVec2(const zeus::CVector2f& v) { \
x = v.x(); \ x = v.x(); \