Backends, Examples: Added support for WebGPU and corresponding example. Amend 5853fbd (#3632)

This commit is contained in:
ocornut
2021-01-28 12:11:26 +01:00
parent 5853fbd68b
commit dff0044d4e
12 changed files with 114 additions and 157 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
})();