diff --git a/.gitignore b/.gitignore index d1fdd53e..8d720199 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ examples/*.o.tmp examples/*.out.js examples/*.out.wasm examples/example_emscripten_opengl3/web/* +examples/example_emscripten_wgpu/web/* ## JetBrains IDE artifacts .idea diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 74a266e1..0b9ac216 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -1,5 +1,5 @@ // dear imgui: Platform Backend for GLFW -// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..) +// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..) // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (Requires: GLFW 3.1+) @@ -63,7 +63,8 @@ enum GlfwClientApi { GlfwClientApi_Unknown, GlfwClientApi_OpenGL, - GlfwClientApi_Vulkan + GlfwClientApi_Vulkan, + GlfwClientApi_WebGPU }; static GLFWwindow* g_Window = NULL; // Main window static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown; @@ -231,6 +232,11 @@ bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks) return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan); } +bool ImGui_ImplGlfw_InitForWebGPU(GLFWwindow* window, bool install_callbacks) +{ + return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_WebGPU); +} + void ImGui_ImplGlfw_Shutdown() { if (g_InstalledCallbacks) diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index 6abb4056..f04ba728 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -1,5 +1,5 @@ // dear imgui: Platform Backend for GLFW -// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..) +// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..) // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // Implemented features: @@ -23,6 +23,7 @@ struct GLFWwindow; IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); +IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForWebGPU(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 23605dd6..b18a5345 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -1,5 +1,6 @@ // dear imgui: Renderer for WebGPU // This needs to be used along with a Platform Binding (e.g. GLFW) +// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.) // Implemented features: // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID! @@ -11,51 +12,33 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2021-01-28: Initial version. #include "imgui.h" #include "imgui_impl_wgpu.h" - -// CRT #include - -// WebGPU #include -// ImGui prototypes -ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0); +// Dear ImGui prototypes from imgui_internal.h +extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0); // WebGPU data -static WGPUDevice g_wgpuDevice = NULL; -static WGPUTextureFormat g_renderTargetFormat = WGPUTextureFormat_Undefined; -static WGPURenderPipeline g_pipelineState = NULL; +static WGPUDevice g_wgpuDevice = NULL; +static WGPUTextureFormat g_renderTargetFormat = WGPUTextureFormat_Undefined; +static WGPURenderPipeline g_pipelineState = NULL; struct RenderResources { - // Font texture - WGPUTexture FontTexture; - - // Texture view for font texture - WGPUTextureView FontTextureView; - - // Sampler for the font texture - WGPUSampler Sampler; - - // Shader uniforms - WGPUBuffer Uniforms; - - // Resources bind-group to bind the common resources to pipeline - WGPUBindGroup CommonBindGroup; - - // Bind group layout for image textures - WGPUBindGroupLayout ImageBindGroupLayout; - - // Resources bind-group to bind the font/image resources to pipeline - ImGuiStorage ImageBindGroups; - - // Default font-resource of ImGui - WGPUBindGroup ImageBindGroup; + WGPUTexture FontTexture; // Font texture + WGPUTextureView FontTextureView; // Texture view for font texture + WGPUSampler Sampler; // Sampler for the font texture + WGPUBuffer Uniforms; // Shader uniforms + WGPUBindGroup CommonBindGroup; // Resources bind-group to bind the common resources to pipeline + WGPUBindGroupLayout ImageBindGroupLayout; // Bind group layout for image textures + ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map) + WGPUBindGroup ImageBindGroup; // Default font-resource of Dear ImGui }; -static RenderResources g_resources; +static RenderResources g_resources; struct FrameResources { @@ -285,9 +268,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(uint32_ static WGPUBindGroup ImGui_ImplWGPU_CreateImageBindGroup(WGPUBindGroupLayout layout, WGPUTextureView texture) { - WGPUBindGroupEntry image_bg_entries[] = { - { 0, 0, 0, 0, 0, texture }, - }; + WGPUBindGroupEntry image_bg_entries[] = { { 0, 0, 0, 0, 0, texture } }; WGPUBindGroupDescriptor image_bg_descriptor = {}; image_bg_descriptor.layout = layout; @@ -339,7 +320,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) return; - // FIXME: I'm assuming that this only gets called once per frame! + // FIXME: 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. g_frameIndex = g_frameIndex + 1; FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight]; @@ -351,9 +332,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder SafeRelease(fr->VertexBufferHost); fr->VertexBufferSize = draw_data->TotalVtxCount + 5000; - WGPUBufferDescriptor vb_desc = { - nullptr, - "IMGUI Vertex buffer", + WGPUBufferDescriptor vb_desc = + { + NULL, + "Dear ImGui Vertex buffer", WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex, fr->VertexBufferSize * sizeof(ImDrawVert), false @@ -370,9 +352,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder SafeRelease(fr->IndexBufferHost); fr->IndexBufferSize = draw_data->TotalIdxCount + 10000; - WGPUBufferDescriptor ib_desc = { - nullptr, - "IMGUI Index buffer", + WGPUBufferDescriptor ib_desc = + { + NULL, + "Dear ImGui Index buffer", WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index, fr->IndexBufferSize * sizeof(ImDrawIdx), false @@ -427,13 +410,14 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder { // Bind custom texture auto bind_group = g_resources.ImageBindGroups.GetVoidPtr(ImHashData(&pcmd->TextureId, sizeof(ImTextureID))); - if (bind_group) { + if (bind_group) + { wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, NULL); } - else { - WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(g_resources.ImageBindGroupLayout, (WGPUTextureView) pcmd->TextureId); + else + { + WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(g_resources.ImageBindGroupLayout, (WGPUTextureView)pcmd->TextureId); g_resources.ImageBindGroups.SetVoidPtr(ImHashData(&pcmd->TextureId, sizeof(ImTextureID)), image_bind_group); - wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, image_bind_group, 0, NULL); } @@ -464,7 +448,6 @@ static WGPUBuffer ImGui_ImplWGPU_CreateBufferFromData(const WGPUDevice& device, return buffer; } - static void ImGui_ImplWGPU_CreateFontsTexture() { // Build texture atlas @@ -476,7 +459,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture to graphics system { WGPUTextureDescriptor tex_desc = {}; - tex_desc.label = "IMGUI Font Texture"; + tex_desc.label = "Dear ImGui Font Texture"; tex_desc.dimension = WGPUTextureDimension_2D; tex_desc.size.width = width; tex_desc.size.height = height; @@ -500,7 +483,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture data { - WGPUBuffer staging_buffer = ImGui_ImplWGPU_CreateBufferFromData(g_wgpuDevice, pixels, static_cast(width * size_pp * height), WGPUBufferUsage_CopySrc); + WGPUBuffer staging_buffer = ImGui_ImplWGPU_CreateBufferFromData(g_wgpuDevice, pixels, (uint32_t)(width * size_pp * height), WGPUBufferUsage_CopySrc); WGPUBufferCopyView bufferCopyView = {}; bufferCopyView.buffer = staging_buffer; @@ -516,7 +499,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture() textureCopyView.aspect = WGPUTextureAspect_All; #endif - WGPUExtent3D copySize = { static_cast(width), static_cast(height), 1 }; + WGPUExtent3D copySize = { (uint32_t)width, (uint32_t)height, 1 }; WGPUCommandEncoderDescriptor enc_desc = {}; WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(g_wgpuDevice, &enc_desc); @@ -549,9 +532,10 @@ static void ImGui_ImplWGPU_CreateFontsTexture() static void ImGui_ImplWGPU_CreateUniformBuffer() { - WGPUBufferDescriptor ub_desc = { - nullptr, - "IMGUI Uniform buffer", + WGPUBufferDescriptor ub_desc = + { + NULL, + "Dear ImGui Uniform buffer", WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform, sizeof(Uniforms), false @@ -568,12 +552,10 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() // Create render pipeline WGPURenderPipelineDescriptor graphics_pipeline_desc = {}; - graphics_pipeline_desc.primitiveTopology = WGPUPrimitiveTopology_TriangleList; graphics_pipeline_desc.sampleCount = 1; graphics_pipeline_desc.sampleMask = UINT_MAX; - WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {}; common_bg_layout_entries[0].binding = 0; common_bg_layout_entries[0].visibility = WGPUShaderStage_Vertex; @@ -609,7 +591,8 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() graphics_pipeline_desc.vertexStage = vertex_shader_desc; // Vertex input configuration - WGPUVertexAttributeDescriptor attribute_binding_desc[] = { + WGPUVertexAttributeDescriptor attribute_binding_desc[] = + { { WGPUVertexFormat_Float2, (uint64_t)IM_OFFSETOF(ImDrawVert, pos), 0 }, { WGPUVertexFormat_Float2, (uint64_t)IM_OFFSETOF(ImDrawVert, uv), 1 }, { WGPUVertexFormat_UChar4Norm, (uint64_t)IM_OFFSETOF(ImDrawVert, col), 2 }, @@ -665,7 +648,6 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() { // Configure disabled state depth_desc.format = WGPUTextureFormat_Undefined; - depth_desc.depthWriteEnabled = true; depth_desc.depthCompare = WGPUCompareFunction_Always; depth_desc.stencilReadMask = 0; @@ -680,7 +662,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() depth_desc.stencilFront.passOp = WGPUStencilOperation_Keep; // No depth buffer corresponds to no configuration - graphics_pipeline_desc.depthStencilState = nullptr; + graphics_pipeline_desc.depthStencilState = NULL; } g_pipelineState = wgpuDeviceCreateRenderPipeline(g_wgpuDevice, &graphics_pipeline_desc); @@ -689,7 +671,8 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() ImGui_ImplWGPU_CreateUniformBuffer(); // Create resource bind group - WGPUBindGroupEntry common_bg_entries[] = { + WGPUBindGroupEntry common_bg_entries[] = + { { 0, g_resources.Uniforms, 0, sizeof(Uniforms), 0, 0 }, { 1, 0, 0, 0, g_resources.Sampler, 0 }, }; @@ -724,9 +707,7 @@ void ImGui_ImplWGPU_InvalidateDeviceObjects() io.Fonts->TexID = NULL; // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. for (unsigned int i = 0; i < g_numFramesInFlight; i++) - { SafeRelease(g_pFrameResources[i]); - } } bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format) diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 92365b5f..f6c61528 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -1,5 +1,6 @@ // dear imgui: Renderer for WebGPU // This needs to be used along with a Platform Binding (e.g. GLFW) +// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.) // Implemented features: // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID! @@ -10,12 +11,9 @@ // Read online: https://github.com/ocornut/imgui/tree/master/docs #pragma once -#include "imgui.h" // IMGUI_IMPL_API - -// WebGPU +#include "imgui.h" // IMGUI_IMPL_API #include -// cmd_list is the command list that the implementation will use to render imgui draw lists. IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format); IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown(); IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame(); diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index 099d71b8..7a723cc7 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -80,35 +80,7 @@ The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/ex ### Backends for third-party frameworks, graphics API or other languages -See https://github.com/ocornut/imgui/wiki/Bindings -- AGS/Adventure Game Studio -- Amethyst -- bsf -- Cinder -- Cocos2d-x -- Diligent Engine -- Flexium, -- GML/Game Maker Studio2 -- GTK3+OpenGL3 -- Irrlicht Engine -- LÖVE+LUA -- Magnum -- NanoRT -- Nim Game Lib, -- Ogre -- openFrameworks -- OSG/OpenSceneGraph -- Orx -- px_render -- Qt/QtDirect3D -- SFML -- Sokol -- Unity -- Unreal Engine 4 -- vtk -- Win32 GDI -etc. - +See https://github.com/ocornut/imgui/wiki/Bindings for the full list. ### Recommended Backends diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f2a38393..3e51e2dd 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,6 +59,12 @@ Other Changes: User needs to call ImGui_ImplVulkan_LoadFunctions() with their custom loader prior to other functions. - Backends: Metal: Fixed texture storage mode when building on Mac Catalyst. (#3748) [@Belinsky-L-V] - Backends: OSX: Fixed mouse position not being reported when mouse buttons other than left one are down. (#3762) [@rokups] +- Backends: WebGPU: Added enderer backend for WebGPU support (imgui_impl_wgpu.cpp) (#3632) [@bfierz] + Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break. +- Examples: WebGPU: Added Emscripten+WebGPU example. (#3632) [@bfierz] +- Backends: GLFW: Added ImGui_ImplGlfw_InitForWebGPU() init point. It currently has strictly no effect on anything, + but because some multi-viewport renderers require knowledge of the render stack in the Platform back-end, we're + adding it for consistency. (#3632) ----------------------------------------------------------------------- @@ -94,7 +100,6 @@ Breaking Changes: confusion with Tables API. Keep redirection enums (will obsolete). (#125, #513, #913, #1204, #1444, #2142, #2707) - Renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature now applies to other data structures. (#2636) -- Backends: WebGPU: Added backend for WebGPU support in imgui_impl_wgpu [@bfierz] Other Changes: diff --git a/docs/README.md b/docs/README.md index 7c088556..7c8ea360 100644 --- a/docs/README.md +++ b/docs/README.md @@ -115,13 +115,13 @@ On most platforms and when using C++, **you should be able to use a combination Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://www.dearimgui.org/faq), comments, and some of the examples/ application!** Officially maintained backends/bindings (in repository): -- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, Metal. +- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL (legacy), OpenGL3/ES/ES2 (modern), Vulkan, WebGPU. - Platforms: GLFW, SDL2, Win32, Glut, OSX. - Frameworks: Emscripten, Allegro5, Marmalade. [Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page: - Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... -- Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, nCine, Nim Game Lib, Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SFML, Sokol, Unity, Unreal Engine 4, vtk, Win32 GDI, WxWidgets. +- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, GLEQ, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS & Switch (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SDL_Renderer, SFML, Sokol, Unity, Unreal Engine 4, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets. - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. [Useful widgets and extensions](https://github.com/ocornut/imgui/wiki/Useful-Widgets) wiki page: diff --git a/examples/example_emscripten_opengl3/main.cpp b/examples/example_emscripten_opengl3/main.cpp index 13f90ede..0c926660 100644 --- a/examples/example_emscripten_opengl3/main.cpp +++ b/examples/example_emscripten_opengl3/main.cpp @@ -21,7 +21,7 @@ SDL_Window* g_Window = NULL; SDL_GLContext g_GLContext = NULL; // For clarity, our main loop code is declared at the end. -void main_loop(void*); +static void main_loop(void*); int main(int, char**) { @@ -99,7 +99,7 @@ int main(int, char**) emscripten_set_main_loop_arg(main_loop, NULL, 0, true); } -void main_loop(void* arg) +static void main_loop(void* arg) { ImGuiIO& io = ImGui::GetIO(); IM_UNUSED(arg); // We can pass this argument as the second parameter of emscripten_set_main_loop_arg(), but we don't use that. diff --git a/examples/example_emscripten_wgpu/Makefile b/examples/example_emscripten_wgpu/Makefile index 44e2b8be..de1792fe 100644 --- a/examples/example_emscripten_wgpu/Makefile +++ b/examples/example_emscripten_wgpu/Makefile @@ -6,18 +6,20 @@ # This Makefile assumes you have loaded emscripten's environment. # (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead) # -# Running `make` will produce two files: -# - example_emscripten_wgpu.js -# - example_emscripten_wgpu.wasm +# Running `make` will produce three files: +# - web/index.html (current stored in the repository) +# - web/index.js +# - web/index.wasm # # All three are needed to run the demo. CC = emcc CXX = em++ -EXE = example_emscripten_wgpu.js +WEB_DIR = web +EXE = $(WEB_DIR)/index.js IMGUI_DIR = ../.. SOURCES = main.cpp -SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_widgets.cpp +SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) @@ -47,7 +49,7 @@ endif ## FINAL BUILD FLAGS ##--------------------------------------------------------------------- -CPPFLAGS += -I$(IMGUI_DIR)/ -I$(IMGUI_DIR)/backends +CPPFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends #CPPFLAGS += -g CPPFLAGS += -Wall -Wformat -Os CPPFLAGS += $(EMS) @@ -61,9 +63,6 @@ LIBS += $(EMS) %.o:%.cpp $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< -%.o:../%.cpp - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< - %.o:$(IMGUI_DIR)/%.cpp $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< @@ -73,8 +72,14 @@ LIBS += $(EMS) all: $(EXE) @echo Build complete for $(EXE) -$(EXE): $(OBJS) - $(CXX) -o $@ $^ $(LIBS) $(LDFLAGS) +$(WEB_DIR): + mkdir $@ + +serve: all + python3 -m http.server -d $(WEB_DIR) + +$(EXE): $(OBJS) $(WEB_DIR) + $(CXX) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) clean: - rm -f $(EXE) $(OBJS) *.js *.wasm *.wasm.pre + rm -f $(EXE) $(OBJS) $(WEB_DIR)/*.js $(WEB_DIR)/*.wasm $(WEB_DIR)/*.wasm.pre diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index 4ff634cd..94f20142 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -3,10 +3,6 @@ // 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 -// This is mostly the same code as the SDL2 + OpenGL3 example, simply with the modifications needed to run on Emscripten. -// It is possible to combine both code into a single source file that will compile properly on Desktop and using Emscripten. -// See https://github.com/ocornut/imgui/pull/2492 as an example on how to do just that. - #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_wgpu.h" @@ -22,7 +18,6 @@ static WGPUDevice wgpu_device = NULL; static WGPUSurface wgpu_surface = NULL; static WGPUSwapChain wgpu_swap_chain = NULL; - static int wgpu_swap_chain_width = 0; static int wgpu_swap_chain_height = 0; @@ -31,11 +26,11 @@ static bool show_demo_window = true; static bool show_another_window = false; static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); -// Forward declartions -bool init_wgpu(); -void main_loop(void* window); -void print_glfw_error(int error, const char* description); -void print_wgpu_error(WGPUErrorType error_type, const char* message, void*); +// Forward declarations +static bool init_wgpu(); +static void main_loop(void* window); +static void print_glfw_error(int error, const char* description); +static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*); int main(int, char**) { @@ -48,13 +43,15 @@ int main(int, char**) glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", NULL, NULL); - if (!window) { + if (!window) + { glfwTerminate(); return 1; } // Initialize the WebGPU environment - if (!init_wgpu()) { + if (!init_wgpu()) + { if (window) glfwDestroyWindow(window); glfwTerminate(); @@ -99,7 +96,7 @@ int main(int, char**) //IM_ASSERT(font != NULL); #endif - // This function will directly return and extit he main function. + // This function will directly return and exit the main function. // Make sure that no required objects get cleaned up. // This way we can use the browsers 'requestAnimationFrame' to control the rendering. emscripten_set_main_loop_arg(main_loop, window, 0, false); @@ -107,31 +104,31 @@ int main(int, char**) return 0; } -bool init_wgpu() +static bool init_wgpu() { wgpu_device = emscripten_webgpu_get_device(); if (!wgpu_device) return false; - wgpuDeviceSetUncapturedErrorCallback(wgpu_device, print_wgpu_error, nullptr); + wgpuDeviceSetUncapturedErrorCallback(wgpu_device, print_wgpu_error, NULL); - // Use C++ wrapper due to malbehaviour in Emscripten. + // Use C++ wrapper due to misbehavior in Emscripten. // Some offset computation for wgpuInstanceCreateSurface in JavaScript // seem to be inline with struct alignments in the C++ structure - wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc{}; + wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {}; html_surface_desc.selector = "#canvas"; - wgpu::SurfaceDescriptor surface_desc{}; + wgpu::SurfaceDescriptor surface_desc = {}; surface_desc.nextInChain = &html_surface_desc; // Use 'null' instance - wgpu::Instance instance{}; + wgpu::Instance instance = {}; wgpu_surface = instance.CreateSurface(&surface_desc).Release(); return true; } -void main_loop(void* window) +static void main_loop(void* window) { glfwPollEvents(); @@ -202,7 +199,7 @@ void main_loop(void* window) ImGui::End(); } - // Render the generated ImGui frame + // Rendering ImGui::Render(); WGPURenderPassColorAttachmentDescriptor color_attachments = {}; @@ -213,7 +210,7 @@ void main_loop(void* window) WGPURenderPassDescriptor render_pass_desc = {}; render_pass_desc.colorAttachmentCount = 1; render_pass_desc.colorAttachments = &color_attachments; - render_pass_desc.depthStencilAttachment = nullptr; + render_pass_desc.depthStencilAttachment = NULL; WGPUCommandEncoderDescriptor enc_desc = {}; WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc); @@ -228,30 +225,21 @@ void main_loop(void* window) wgpuQueueSubmit(queue, 1, &cmd_buffer); } -void print_glfw_error(int error, const char* description) +static void print_glfw_error(int error, const char* description) { printf("Glfw Error %d: %s\n", error, description); } -void print_wgpu_error(WGPUErrorType error_type, const char* message, void*) +static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*) { const char* error_type_lbl = ""; - switch (error_type) { - case WGPUErrorType_Validation: - error_type_lbl = "Validation"; - break; - case WGPUErrorType_OutOfMemory: - error_type_lbl = "Out of memory"; - break; - case WGPUErrorType_Unknown: - error_type_lbl = "Unknown"; - break; - case WGPUErrorType_DeviceLost: - error_type_lbl = "Device lost"; - break; - default: - error_type_lbl = "Unknown"; + switch (error_type) + { + case WGPUErrorType_Validation: error_type_lbl = "Validation"; break; + case WGPUErrorType_OutOfMemory: error_type_lbl = "Out of memory"; break; + case WGPUErrorType_Unknown: error_type_lbl = "Unknown"; break; + case WGPUErrorType_DeviceLost: error_type_lbl = "Device lost"; break; + default: error_type_lbl = "Unknown"; } - printf("%s error: %s\n", error_type_lbl, message); } diff --git a/examples/example_emscripten_wgpu/example_emscripten_wgpu.html b/examples/example_emscripten_wgpu/web/index.html similarity index 96% rename from examples/example_emscripten_wgpu/example_emscripten_wgpu.html rename to examples/example_emscripten_wgpu/web/index.html index 796844b6..82b1c422 100644 --- a/examples/example_emscripten_wgpu/example_emscripten_wgpu.html +++ b/examples/example_emscripten_wgpu/web/index.html @@ -3,7 +3,7 @@ - Dear ImGui Emscripten example + Dear ImGui Emscripten+WebGPU example