Backends, Examples: Added support for WebGPU and corresponding example. Amend 5853fbd (#3632)
diff --git a/.gitignore b/.gitignore
index d1fdd53..8d72019 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@
 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 74a266e..0b9ac21 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 @@
 {
     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 @@
     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 6abb405..f04ba72 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 @@
 
 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 23605dd..b18a534 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 <limits.h>
-
-// WebGPU
 #include <webgpu/webgpu.h>
 
-// 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 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 @@
     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 @@
         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 @@
         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 @@
             {
                 // 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 @@
     return buffer;
 }
 
-
 static void ImGui_ImplWGPU_CreateFontsTexture()
 {
     // Build texture atlas
@@ -476,7 +459,7 @@
     // 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 @@
 
     // Upload texture data
     {
-        WGPUBuffer staging_buffer = ImGui_ImplWGPU_CreateBufferFromData(g_wgpuDevice, pixels, static_cast<uint32_t>(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 @@
         textureCopyView.aspect = WGPUTextureAspect_All;
 #endif
 
-        WGPUExtent3D copySize = { static_cast<uint32_t>(width), static_cast<uint32_t>(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_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 @@
 
     // 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 @@
     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 @@
     {
         // 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 @@
         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 @@
     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 @@
     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 92365b5..f6c6152 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 <webgpu/webgpu.h>
 
-// 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 099d71b..7a723cc 100644
--- a/docs/BACKENDS.md
+++ b/docs/BACKENDS.md
@@ -80,35 +80,7 @@
 
 ### 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 f2a3839..3e51e2d 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -59,6 +59,12 @@
   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 @@
   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 7c08855..7c8ea36 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -115,13 +115,13 @@
 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 13f90ed..0c92666 100644
--- a/examples/example_emscripten_opengl3/main.cpp
+++ b/examples/example_emscripten_opengl3/main.cpp
@@ -21,7 +21,7 @@
 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 @@
     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 44e2b8b..de1792f 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 @@
 ## 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 @@
 %.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 @@
 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 4ff634c..94f2014 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_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 @@
     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 @@
     //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 @@
     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 @@
         ImGui::End();
     }
     
-    // Render the generated ImGui frame
+    // Rendering
     ImGui::Render();
 
     WGPURenderPassColorAttachmentDescriptor color_attachments = {};
@@ -213,7 +210,7 @@
     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 @@
     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 95%
rename from examples/example_emscripten_wgpu/example_emscripten_wgpu.html
rename to examples/example_emscripten_wgpu/web/index.html
index 796844b..82b1c42 100644
--- a/examples/example_emscripten_wgpu/example_emscripten_wgpu.html
+++ b/examples/example_emscripten_wgpu/web/index.html
@@ -3,7 +3,7 @@
   <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
-    <title>Dear ImGui Emscripten example</title>
+    <title>Dear ImGui Emscripten+WebGPU example</title>
     <style>
         body { margin: 0; background-color: black }
         .emscripten {
@@ -71,7 +71,7 @@
       {
           const js = document.createElement('script');
           js.async = true;
-          js.src = "example_emscripten_wgpu.js";
+          js.src = "index.js";
           document.body.appendChild(js);
       }
       })();