mirror of
https://github.com/ocornut/imgui.git
synced 2025-12-20 13:25:39 +00:00
Examples: GLFW+WebGPU: update to latest specs and to work on Emscripten 4.0.10+ and latest Dawn-Native, WGPU-Native. (#8381, #8567, #8191, #7435)
This commit is contained in:
@@ -91,13 +91,15 @@ Other Changes:
|
|||||||
ImGui_ImplWGPU_GetDeviceLostReasonName(), ImGui_ImplWGPU_GetErrorTypeName(),
|
ImGui_ImplWGPU_GetDeviceLostReasonName(), ImGui_ImplWGPU_GetErrorTypeName(),
|
||||||
ImGui_ImplWGPU_GetLogLevelName().
|
ImGui_ImplWGPU_GetLogLevelName().
|
||||||
- WebGPU: update to compile with Dawn and Emscripten's 4.0.10+
|
- WebGPU: update to compile with Dawn and Emscripten's 4.0.10+
|
||||||
'--use-port=emdawnwebgpu' ports. (#8381, #8898) [@brutpitt, @trbabb]
|
'--use-port=emdawnwebgpu' ports. (#8381, #8898, #7435) [@brutpitt, @trbabb]
|
||||||
When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||||
instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified.
|
instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified.
|
||||||
(note: examples application were not updated yet)
|
(note: examples application were not updated yet)
|
||||||
- Win32: Revert 1.92.4 change of comparing dwPacketNumber, which prevents
|
- Win32: Revert 1.92.4 change of comparing dwPacketNumber, which prevents
|
||||||
refreshing accurate gamepad info after focus-out + io.ClearInputKeys(). (#8556)
|
refreshing accurate gamepad info after focus-out + io.ClearInputKeys(). (#8556)
|
||||||
- Examples:
|
- Examples:
|
||||||
|
- GLFW+WebGPU: update example for latest specs, to work on Emscripten 4.0.10+,
|
||||||
|
latest Dawn-Native and WGPU-Native. (#8381, #8567, #8191, #7435) [@brutpitt]
|
||||||
- GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call
|
- GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call
|
||||||
during surface resize. (#8381)
|
during surface resize. (#8381)
|
||||||
|
|
||||||
|
|||||||
@@ -6,16 +6,28 @@
|
|||||||
# * build/Debug/example_glfw_wgpu[.exe]
|
# * build/Debug/example_glfw_wgpu[.exe]
|
||||||
# * build/example_glfw_wgpu[.exe]
|
# * build/example_glfw_wgpu[.exe]
|
||||||
|
|
||||||
|
# Building for desktop (WGPU-Native) with WGPU-Native:
|
||||||
|
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||||
|
# 2. unzip the downloaded file in your_preferred_folder
|
||||||
|
# 3. cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder ("full path" or "relative" starting from current directory)
|
||||||
|
# 4. cmake --build build
|
||||||
|
# The resulting binary will be found at one of the following locations:
|
||||||
|
# * build/Debug/example_glfw_wgpu[.exe]
|
||||||
|
# * build/example_glfw_wgpu[.exe]
|
||||||
|
|
||||||
# Building for Emscripten:
|
# Building for Emscripten:
|
||||||
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
# 1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||||
# 2. Install Ninja build system
|
# 2. Install Ninja build system
|
||||||
# 3. emcmake cmake -G Ninja -B build
|
# 3. emcmake cmake -G Ninja -B build
|
||||||
|
# (optional) -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py", see ReadMe.md
|
||||||
# 3. cmake --build build
|
# 3. cmake --build build
|
||||||
# 4. emrun build/index.html
|
# 4. emrun build/index.html
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.10.2)
|
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
|
||||||
project(imgui_example_glfw_wgpu C CXX)
|
project(imgui_example_glfw_wgpu C CXX)
|
||||||
|
|
||||||
|
set(IMGUI_EXECUTABLE example_glfw_wgpu)
|
||||||
|
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||||
endif()
|
endif()
|
||||||
@@ -25,51 +37,10 @@ set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
|||||||
# Dear ImGui
|
# Dear ImGui
|
||||||
set(IMGUI_DIR ../../)
|
set(IMGUI_DIR ../../)
|
||||||
|
|
||||||
# Libraries
|
set(IMGUI_EXAMPLE_SOURCE_FILES
|
||||||
if(EMSCRIPTEN)
|
# Example code
|
||||||
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
|
|
||||||
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
|
|
||||||
else()
|
|
||||||
# cannot use contrib.glfw3 prior to 3.1.57
|
|
||||||
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
|
|
||||||
endif()
|
|
||||||
set(LIBRARIES glfw)
|
|
||||||
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1 -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
|
||||||
else()
|
|
||||||
# Dawn wgpu desktop
|
|
||||||
set(DAWN_FETCH_DEPENDENCIES ON)
|
|
||||||
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
|
|
||||||
if (NOT IMGUI_DAWN_DIR)
|
|
||||||
message(FATAL_ERROR "Please specify the Dawn repository by setting IMGUI_DAWN_DIR")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
|
|
||||||
|
|
||||||
# Dawn builds many things by default - disable things we don't need
|
|
||||||
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
|
|
||||||
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
|
|
||||||
option(TINT_BUILD_DOCS "Build documentation" OFF)
|
|
||||||
option(TINT_BUILD_TESTS "Build tests" OFF)
|
|
||||||
if (NOT APPLE)
|
|
||||||
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
|
|
||||||
endif()
|
|
||||||
if(WIN32)
|
|
||||||
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
|
|
||||||
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
|
|
||||||
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
|
|
||||||
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
|
|
||||||
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" OFF)
|
|
||||||
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
set(LIBRARIES webgpu_dawn webgpu_cpp webgpu_glfw glfw)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(example_glfw_wgpu
|
|
||||||
main.cpp
|
main.cpp
|
||||||
# backend files
|
# Dear ImGui Backend files
|
||||||
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
|
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
|
||||||
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
|
${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp
|
||||||
# Dear ImGui files
|
# Dear ImGui files
|
||||||
@@ -79,39 +50,159 @@ add_executable(example_glfw_wgpu
|
|||||||
${IMGUI_DIR}/imgui_tables.cpp
|
${IMGUI_DIR}/imgui_tables.cpp
|
||||||
${IMGUI_DIR}/imgui_widgets.cpp
|
${IMGUI_DIR}/imgui_widgets.cpp
|
||||||
)
|
)
|
||||||
IF(NOT EMSCRIPTEN)
|
|
||||||
target_compile_definitions(example_glfw_wgpu PUBLIC
|
if(EMSCRIPTEN)
|
||||||
"IMGUI_IMPL_WEBGPU_BACKEND_DAWN"
|
if(NOT IMGUI_EMSCRIPTEN_WEBGPU_FLAG) # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG not used, set by current EMSCRIPTEN version
|
||||||
)
|
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "4.0.10")
|
||||||
|
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "--use-port=emdawnwebgpu" CACHE STRING "Choose between --use-port=emdawnwebgpu (Dawn implementation of EMSCRIPTEN) and -sUSE_WEBGPU=1 (WGPU implementation of EMSCRIPTEN, deprecated in 4.0.10): default to --use-port=emdawnwebgpu for EMSCRIPTEN >= 4.0.10")
|
||||||
|
else()
|
||||||
|
set(IMGUI_EMSCRIPTEN_WEBGPU_FLAG "-sUSE_WEBGPU=1" CACHE STRING "Use -sUSE_WEBGPU=1 for EMSCRIPTEN WGPU implementation")
|
||||||
|
endif()
|
||||||
|
else() # if IMGUI_EMSCRIPTEN_WEBGPU_FLAG used, check correct version
|
||||||
|
if(EMSCRIPTEN_VERSION VERSION_LESS "4.0.10" AND "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
|
||||||
|
# it's necessary EMSCRIPTEN >= v4.0.10 (although "--use-port=path/to/emdawnwebgpu.port.py" is supported/tested from v4.0.8)
|
||||||
|
message(FATAL_ERROR "emdawnwebgpu needs EMSCRIPTEN version >= 4.0.10")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(EMSCRIPTEN_VERSION VERSION_GREATER_EQUAL "3.1.57")
|
||||||
|
set(IMGUI_EMSCRIPTEN_GLFW3 "--use-port=contrib.glfw3" CACHE STRING "Choose between --use-port=contrib.glfw3 and -sUSE_GLFW=3 for GLFW implementation (default to --use-port=contrib.glfw3)")
|
||||||
|
else() # cannot use contrib.glfw3 prior to 3.1.57
|
||||||
|
set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(LIBRARIES glfw)
|
||||||
|
add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1)
|
||||||
|
else() # Native/Desktop build
|
||||||
|
# Check DAWN/WGPU directory
|
||||||
|
if(NOT IMGUI_DAWN_DIR AND NOT IMGUI_WGPU_DIR) # if it's Native/Desktop build, IMGUI_DAWN_DIR or IMGUI_WGPU_DIR must be specified
|
||||||
|
message(FATAL_ERROR "Please specify the Dawn or WGPU base directory")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(IMGUI_DAWN_DIR AND IMGUI_WGPU_DIR) # both IMGUI_DAWN_DIR and IMGUI_WGPU_DIR cannot be set
|
||||||
|
message(FATAL_ERROR "Please specify only one between Dawn / WGPU base directory")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE) # Add SDL2 module to get Surface, with libs and file property for MacOS build
|
||||||
|
set_source_files_properties(${IMGUI_DIR}/backends/imgui_impl_wgpu.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
|
||||||
|
# set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(IMGUI_DAWN_DIR) # DAWN-Native build options
|
||||||
|
set(IMGUI_DAWN_DIR CACHE PATH "Path to Dawn repository")
|
||||||
|
if(NOT IMGUI_DAWN_DIR)
|
||||||
|
message(FATAL_ERROR "Please specify the Dawn repository by setting IMGUI_DAWN_DIR")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" ON)
|
||||||
|
set(DAWN_BUILD_MONOLITHIC_LIBRARY "STATIC" CACHE STRING "Build monolithic library: SHARED, STATIC, or OFF.")
|
||||||
|
|
||||||
|
# Dawn builds many things by default - disable things we don't need
|
||||||
|
option(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" OFF)
|
||||||
|
option(TINT_BUILD_CMD_TOOLS "Build the Tint command line tools" OFF)
|
||||||
|
option(TINT_BUILD_DOCS "Build documentation" OFF)
|
||||||
|
option(TINT_BUILD_TESTS "Build tests" OFF)
|
||||||
|
if(NOT APPLE)
|
||||||
|
option(TINT_BUILD_MSL_WRITER "Build the MSL output writer" OFF)
|
||||||
|
endif()
|
||||||
|
if(WIN32)
|
||||||
|
option(DAWN_FORCE_SYSTEM_COMPONENT_LOAD "Allow system component fallback" ON)
|
||||||
|
option(TINT_BUILD_SPV_READER "Build the SPIR-V input reader" OFF)
|
||||||
|
option(TINT_BUILD_WGSL_READER "Build the WGSL input reader" ON)
|
||||||
|
option(TINT_BUILD_GLSL_WRITER "Build the GLSL output writer" OFF)
|
||||||
|
option(TINT_BUILD_GLSL_VALIDATOR "Build the GLSL output validator" OFF)
|
||||||
|
option(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ON)
|
||||||
|
option(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
|
||||||
|
endif()
|
||||||
|
# check if WAYLAND is the current Session Type and enable DAWN_USE_WAYLAND Wayland option @compile time
|
||||||
|
# You can override this using: cmake -DDAWN_USE_WAYLAND=X (X = ON | OFF)
|
||||||
|
if(LINUX)
|
||||||
|
if($ENV{XDG_SESSION_TYPE} MATCHES wayland)
|
||||||
|
option(DAWN_USE_WAYLAND "Enable support for Wayland surface" ON)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory("${IMGUI_DAWN_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/dawn" EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
set(LIBRARIES webgpu_dawn webgpu_glfw glfw)
|
||||||
|
else() # WGPU-Native build options
|
||||||
|
find_package(glfw3 CONFIG)
|
||||||
|
|
||||||
|
set(WGPU_NATIVE_LIB_DIR ${IMGUI_WGPU_DIR}/lib)
|
||||||
|
find_library(WGPU_LIBRARY NAMES libwgpu_native.a wgpu_native.lib wgpu_native HINTS ${WGPU_NATIVE_LIB_DIR} REQUIRED)
|
||||||
|
if(WIN32)
|
||||||
|
set(OS_LIBRARIES d3dcompiler ws2_32 userenv bcrypt ntdll opengl32 Propsys RuntimeObject)
|
||||||
|
elseif(UNIX AND NOT APPLE)
|
||||||
|
set(OS_LIBRARIES "-lm -ldl")
|
||||||
|
elseif(APPLE)
|
||||||
|
set(OS_LIBRARIES "-framework CoreFoundation -framework QuartzCore -framework Metal -framework MetalKit -framework Cocoa")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(LIBRARIES glfw ${WGPU_LIBRARY} ${OS_LIBRARIES})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(example_glfw_wgpu PUBLIC
|
|
||||||
|
add_executable(${IMGUI_EXECUTABLE} ${IMGUI_EXAMPLE_SOURCE_FILES})
|
||||||
|
|
||||||
|
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC
|
||||||
${IMGUI_DIR}
|
${IMGUI_DIR}
|
||||||
${IMGUI_DIR}/backends
|
${IMGUI_DIR}/backends
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(example_glfw_wgpu PUBLIC ${LIBRARIES})
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_EXAMPLE_GLFW_WGPU")
|
||||||
|
|
||||||
|
# compiler option only for IMGUI_EXAMPLE_SOURCE_FILES
|
||||||
|
if (MSVC)
|
||||||
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC /W4) # warning level 4
|
||||||
|
else()
|
||||||
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC -Wall) # -Wextra -Wpedantic
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# In this example IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU internal define is set according to:
|
||||||
|
# EMSCRIPTEN: by used FLAG
|
||||||
|
# --use-port=emdawnwebgpu --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
|
||||||
|
# -sUSE_WEBGPU=1 --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
|
||||||
|
# NATIVE: by used SDK installation directory
|
||||||
|
# if IMGUI_DAWN_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_DAWN defined
|
||||||
|
# if IMGUI_WGPU_DIR is valid --> IMGUI_IMPL_WEBGPU_BACKEND_WGPU defined
|
||||||
|
|
||||||
|
if(NOT EMSCRIPTEN) # WegGPU-Native settings
|
||||||
|
# Set IMGUI_IMPL_WEBGPU_BACKEND_XXXX based on the SDK (directory) used
|
||||||
|
if(IMGUI_DAWN_DIR)
|
||||||
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||||
|
else()
|
||||||
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
||||||
|
target_include_directories(${IMGUI_EXECUTABLE} PUBLIC ${IMGUI_WGPU_DIR}/include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(${IMGUI_EXECUTABLE} INTERFACE webgpu_cpp PUBLIC ${LIBRARIES})
|
||||||
|
else() # Emscripten settings
|
||||||
|
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
||||||
|
|
||||||
# Emscripten settings
|
|
||||||
if(EMSCRIPTEN)
|
|
||||||
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
|
if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
|
||||||
target_compile_options(example_glfw_wgpu PUBLIC
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_GLFW3}")
|
||||||
"${IMGUI_EMSCRIPTEN_GLFW3}"
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
|
message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")
|
||||||
target_link_options(example_glfw_wgpu PRIVATE
|
|
||||||
"-sUSE_WEBGPU=1"
|
if("${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}" MATCHES "emdawnwebgpu")
|
||||||
|
target_compile_options(${IMGUI_EXECUTABLE} PUBLIC "${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}")
|
||||||
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_DAWN")
|
||||||
|
else()
|
||||||
|
target_compile_definitions(${IMGUI_EXECUTABLE} PUBLIC "IMGUI_IMPL_WEBGPU_BACKEND_WGPU")
|
||||||
|
endif()
|
||||||
|
message(STATUS "Using ${IMGUI_EMSCRIPTEN_WEBGPU_FLAG} WebGPU implementation")
|
||||||
|
|
||||||
|
target_link_options(${IMGUI_EXECUTABLE} PRIVATE
|
||||||
|
"${IMGUI_EMSCRIPTEN_WEBGPU_FLAG}"
|
||||||
"${IMGUI_EMSCRIPTEN_GLFW3}"
|
"${IMGUI_EMSCRIPTEN_GLFW3}"
|
||||||
"-sWASM=1"
|
"-sWASM=1"
|
||||||
|
"-sASYNCIFY=1"
|
||||||
"-sALLOW_MEMORY_GROWTH=1"
|
"-sALLOW_MEMORY_GROWTH=1"
|
||||||
"-sNO_EXIT_RUNTIME=0"
|
"-sNO_EXIT_RUNTIME=0"
|
||||||
"-sASSERTIONS=1"
|
"-sASSERTIONS=1"
|
||||||
"-sDISABLE_EXCEPTION_CATCHING=1"
|
"-sDISABLE_EXCEPTION_CATCHING=1"
|
||||||
"-sNO_FILESYSTEM=1"
|
"-sNO_FILESYSTEM=1"
|
||||||
|
"--shell-file=${CMAKE_CURRENT_LIST_DIR}/../libs/emscripten/shell_minimal.html"
|
||||||
)
|
)
|
||||||
set_target_properties(example_glfw_wgpu PROPERTIES OUTPUT_NAME "index")
|
set_target_properties(${IMGUI_EXECUTABLE} PROPERTIES OUTPUT_NAME "index")
|
||||||
# copy our custom index.html to build directory
|
|
||||||
add_custom_command(TARGET example_glfw_wgpu POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_LIST_DIR}/web/index.html" $<TARGET_FILE_DIR:example_glfw_wgpu>
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
# This Makefile assumes you have loaded emscripten's environment.
|
# This Makefile assumes you have loaded emscripten's environment.
|
||||||
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
|
# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
|
||||||
#
|
#
|
||||||
# Running `make` will produce three files:
|
# Running `make -f Makefile.emscripten` will produce three files:
|
||||||
# - web/index.html (current stored in the repository)
|
# - web/index.html
|
||||||
# - web/index.js
|
# - web/index.js
|
||||||
# - web/index.wasm
|
# - web/index.wasm
|
||||||
#
|
#
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
CC = emcc
|
CC = emcc
|
||||||
CXX = em++
|
CXX = em++
|
||||||
WEB_DIR = web
|
WEB_DIR = web
|
||||||
EXE = $(WEB_DIR)/index.js
|
EXE = $(WEB_DIR)/index.html
|
||||||
IMGUI_DIR = ../..
|
IMGUI_DIR = ../..
|
||||||
SOURCES = main.cpp
|
SOURCES = main.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)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||||
@@ -34,15 +34,19 @@ EMS =
|
|||||||
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
|
# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
|
||||||
# Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays.
|
# Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays.
|
||||||
EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
|
EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
|
||||||
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
|
LDFLAGS += -s WASM=1
|
||||||
|
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||||
|
LDFLAGS += -s ASYNCIFY=1
|
||||||
|
LDFLAGS += -s NO_EXIT_RUNTIME=0
|
||||||
|
LDFLAGS += -s ASSERTIONS=1
|
||||||
|
|
||||||
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
|
# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10)
|
||||||
EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
#EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
LDFLAGS += -s USE_WEBGPU=1
|
#LDFLAGS += -s USE_WEBGPU=1
|
||||||
|
|
||||||
# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10) (UNSUPPORTED YET)
|
# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10)
|
||||||
#EMS += --use-port=emdawnwebgpu
|
EMS += --use-port=emdawnwebgpu
|
||||||
#LDFLAGS += --use-port=emdawnwebgpu
|
LDFLAGS += --use-port=emdawnwebgpu
|
||||||
|
|
||||||
# Build as single file (binary text encoded in .html file)
|
# Build as single file (binary text encoded in .html file)
|
||||||
#LDFLAGS += -sSINGLE_FILE
|
#LDFLAGS += -sSINGLE_FILE
|
||||||
@@ -67,7 +71,7 @@ endif
|
|||||||
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||||
#CPPFLAGS += -g
|
#CPPFLAGS += -g
|
||||||
CPPFLAGS += -Wall -Wformat -Os $(EMS)
|
CPPFLAGS += -Wall -Wformat -Os $(EMS)
|
||||||
#LDFLAGS += --shell-file shell_minimal.html
|
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
|
||||||
LDFLAGS += $(EMS)
|
LDFLAGS += $(EMS)
|
||||||
|
|
||||||
##---------------------------------------------------------------------
|
##---------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,5 +1,146 @@
|
|||||||
## How to Build
|
## How to Build
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Using CMake
|
||||||
|
#### Building for desktop (WebGPU-native) with Google Dawn:
|
||||||
|
1. `git clone https://github.com/google/dawn dawn`
|
||||||
|
2. `cmake -B build -DIMGUI_DAWN_DIR=dawn`
|
||||||
|
3. `cmake --build build`
|
||||||
|
The resulting binary will be found at one of the following locations:
|
||||||
|
* build/Debug/example_glfw_wgpu[.exe]
|
||||||
|
* build/example_glfw_wgpu[.exe]
|
||||||
|
|
||||||
|
#### Building for desktop (WebGPU-Native) with WGPU:
|
||||||
|
1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||||
|
2. unzip the downloaded file in `your_preferred_folder`
|
||||||
|
3. `cmake -B build -DIMGUI_WGPU_DIR=your_preferred_folder` ("full path" or "relative" starting from current directory)
|
||||||
|
4. `cmake --build build`
|
||||||
|
The resulting binary will be found at one of the following locations:
|
||||||
|
* build/Debug/example_glfw_wgpu[.exe]
|
||||||
|
* build/example_glfw_wgpu[.exe]
|
||||||
|
|
||||||
|
#### Building for Emscripten:
|
||||||
|
1. Install Emscripten SDK following the instructions: https://emscripten.org/docs/getting_started/downloads.html
|
||||||
|
2. Install Ninja build system
|
||||||
|
3. `emcmake cmake -G Ninja -B build`
|
||||||
|
- (optional) `-DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py"`, see below
|
||||||
|
4. `cmake --build build`
|
||||||
|
|
||||||
|
#### Sync Emscripten with latest Google Dawn:
|
||||||
|
If you want to sync Emscripten with latest DAWN release it's necessary to download the `port-emdawnwgpu-package` (released daily by Google) here:
|
||||||
|
https://github.com/google/dawn/releases
|
||||||
|
Unpack it in your preferred folder and to replace the step 3 with:
|
||||||
|
|
||||||
|
3. `emcmake cmake -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path/to/emdawnwebgpu_package/emdawnwebgpu.port.py" -G Ninja -B build`
|
||||||
|
|
||||||
|
**N.B.**
|
||||||
|
For the WASM code produced by Emscripten to work correctly, it will also be necessary to have the "corresponding" (or newer) version of Google Canary (nightly build for developers) that includes the latest changes
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### CMake by step
|
||||||
|
|
||||||
|
#### Generate Dawn Native:
|
||||||
|
|
||||||
|
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||||
|
- Using `IMGUI_DAWN_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
|
|
||||||
|
#### Generate WGPU Native:
|
||||||
|
|
||||||
|
- `cmake -G Ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||||
|
|
||||||
|
- Using `IMGUI_WGPU_DIR` set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
||||||
|
|
||||||
|
#### Generate Emscripten:
|
||||||
|
|
||||||
|
- `emcmake cmake -G Ninja -B where_to_build_dir`\
|
||||||
|
CMake checks the EMSCRIPEN version then:
|
||||||
|
- if EMS >= 4.0.10 uses `--use-port=emdawnwebgpu` flag to build
|
||||||
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
|
- if EMS < 4.0.10 uses `-sUSE_WEBGPU=1` flag to build
|
||||||
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
||||||
|
|
||||||
|
#### Generate Emscripten forcing `-sUSE_WEBGPU=1` deprecated flag even with EMS >= 4.0.10
|
||||||
|
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="-sUSE_WEBGPU=1" -B where_to_build_dir`
|
||||||
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_WGPU` compiler define
|
||||||
|
|
||||||
|
#### Generate Emscripten using external WebGPU library (emdawnwebgpu_pkg)
|
||||||
|
- `emcmake cmake -G Ninja -DIMGUI_EMSCRIPTEN_WEBGPU_FLAG="--use-port=path_to_emdawnwebgpu_pkg" -B where_to_build_dir`
|
||||||
|
- it set `IMGUI_IMPL_WEBGPU_BACKEND_DAWN` compiler define
|
||||||
|
- *To use external WebGPU library it's necessary to have EMS >= 4.0.10 or the minimum requirements specified by the package:*
|
||||||
|
- https://github.com/google/dawn/releases
|
||||||
|
|
||||||
|
#### Build time
|
||||||
|
|
||||||
|
Once the procedure for the specific builder is generated, the build command is **always the same**:
|
||||||
|
|
||||||
|
- Build using CMake
|
||||||
|
- `cmake --build where_to_build_dir`
|
||||||
|
- It will use selected builder to build the example.
|
||||||
|
|
||||||
|
- Build explicitly:
|
||||||
|
- `cd where_to_build_dir`
|
||||||
|
- `ninja`
|
||||||
|
- This is the builder chosen during the generation phase
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### CMake useful options
|
||||||
|
#### Generator types (alternative to **ninja** bulder):
|
||||||
|
- `-G Ninja` to build with __ninja__ builder
|
||||||
|
- `-G "Unix Makefiles"` to build with __make__ builder
|
||||||
|
- `-G "Visual Studio 17 2022" -A x64` to create a VS 2022 solution (.sln) file, Windows only
|
||||||
|
- **Native build only**
|
||||||
|
- Not **officially** supported to build Google Dawn
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- using **make** instead **ninja**:
|
||||||
|
- `cmake -G "Unix Makefiles" -DIMGUI_DAWN_DIR=path_to_sdk_dir -B where_to_build_dir`
|
||||||
|
|
||||||
|
**Syntax is case sensitive and the "" are necessary in case of spaces between words*
|
||||||
|
|
||||||
|
#### Directories
|
||||||
|
- The directory path can be absolute or relative (starting from the current directory)
|
||||||
|
- It's necessary to use different `where_to_build_dir` for different CMake generations
|
||||||
|
|
||||||
|
|
||||||
|
#### Build type
|
||||||
|
The default build type is **Debug**
|
||||||
|
It is possible to use a different build type using:
|
||||||
|
- `-DCMAKE_BUILD_TYPE=Release`
|
||||||
|
- `-DCMAKE_BUILD_TYPE=MinSizeRel`
|
||||||
|
- `-DCMAKE_BUILD_TYPE=RelWithDebInfo`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- building **Release**:
|
||||||
|
- `cmake -G ninja -DIMGUI_WGPU_DIR=path_to_sdk_dir -DCMAKE_BUILD_TYPE=Release -B where_to_build_dir `
|
||||||
|
|
||||||
|
#### GLFW / SDL2 / SDL3 includes, libraries, search paths and package manager
|
||||||
|
|
||||||
|
Includes and libraries, by default, are searched in system/compiler paths (environment variables): you can add the path to your development tools to the environment variables without having to modify the `CMakeLists.txt` file.
|
||||||
|
- e.g. CLang search in path specified from the following environment variables:
|
||||||
|
- include files: CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH
|
||||||
|
- library files: LIBRARY_PATH
|
||||||
|
|
||||||
|
If you are using a package manager (**vcpkg** / **conan** / ... ) you need/can to specify it, adding to cmake command:
|
||||||
|
- `-DCMAKE_TOOLCHAIN_FILE=path/to/package_manager.cmake`
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- using **vcpkg** package manager it's necessary adding:
|
||||||
|
- `-DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake`
|
||||||
|
|
||||||
|
- full cmake command using **vcpkg** package manager:
|
||||||
|
- `cmake -G Ninja -DIMGUI_DAWN_DIR=path_to_sdk_dir -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root_dir>/scripts/buildsystems/vcpkg.cmake -B where_to_build_dir`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Using makefile
|
||||||
|
|
||||||
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
|
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
|
||||||
|
|
||||||
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
|
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
|
||||||
@@ -10,6 +151,8 @@
|
|||||||
|
|
||||||
- Requires recent Emscripten as WGPU is still a work-in-progress API.
|
- Requires recent Emscripten as WGPU is still a work-in-progress API.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## How to Run
|
## How to Run
|
||||||
|
|
||||||
To run on a local machine:
|
To run on a local machine:
|
||||||
|
|||||||
@@ -12,26 +12,31 @@
|
|||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
#include "imgui_impl_wgpu.h"
|
#include "imgui_impl_wgpu.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
|
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
#include <emscripten/html5_webgpu.h>
|
#include <emscripten/html5_webgpu.h>
|
||||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
|
||||||
#else
|
|
||||||
#include <webgpu/webgpu_glfw.h>
|
|
||||||
#endif
|
#endif
|
||||||
#include <webgpu/webgpu.h>
|
#include <webgpu/webgpu.h>
|
||||||
#include <webgpu/webgpu_cpp.h>
|
#include <webgpu/webgpu_cpp.h>
|
||||||
|
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||||
|
#else
|
||||||
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||||
|
#include <webgpu/webgpu_glfw.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
static WGPUInstance wgpu_instance = nullptr;
|
static WGPUInstance wgpu_instance = nullptr;
|
||||||
static WGPUDevice wgpu_device = nullptr;
|
static WGPUDevice wgpu_device = nullptr;
|
||||||
static WGPUSurface wgpu_surface = nullptr;
|
static WGPUSurface wgpu_surface = nullptr;
|
||||||
static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm;
|
static WGPUQueue wgpu_queue = nullptr;
|
||||||
static WGPUSwapChain wgpu_swap_chain = nullptr;
|
static WGPUSurfaceConfiguration wgpu_surface_configuration = {};
|
||||||
static int wgpu_surface_width = 1280;
|
static int wgpu_surface_width = 1280;
|
||||||
static int wgpu_surface_height = 800;
|
static int wgpu_surface_height = 800;
|
||||||
|
|
||||||
@@ -43,33 +48,11 @@ static void glfw_error_callback(int error, const char* description)
|
|||||||
printf("GLFW Error %d: %s\n", error, description);
|
printf("GLFW Error %d: %s\n", error, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wgpu_error_callback(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";
|
|
||||||
}
|
|
||||||
printf("%s error: %s\n", error_type_lbl, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ResizeSurface(int width, int height)
|
static void ResizeSurface(int width, int height)
|
||||||
{
|
{
|
||||||
if (wgpu_swap_chain)
|
wgpu_surface_configuration.width = wgpu_surface_width = width;
|
||||||
wgpuSwapChainRelease(wgpu_swap_chain);
|
wgpu_surface_configuration.height = wgpu_surface_height = height;
|
||||||
wgpu_surface_width = width;
|
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
|
||||||
wgpu_surface_height = height;
|
|
||||||
WGPUSwapChainDescriptor swap_chain_desc = {};
|
|
||||||
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
|
|
||||||
swap_chain_desc.format = wgpu_preferred_fmt;
|
|
||||||
swap_chain_desc.width = width;
|
|
||||||
swap_chain_desc.height = height;
|
|
||||||
swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
|
|
||||||
wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main code
|
// Main code
|
||||||
@@ -98,7 +81,7 @@ int main(int, char**)
|
|||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ResizeSurface(wgpu_surface_width, wgpu_surface_height);
|
|
||||||
glfwShowWindow(window);
|
glfwShowWindow(window);
|
||||||
|
|
||||||
// Setup Dear ImGui context
|
// Setup Dear ImGui context
|
||||||
@@ -125,7 +108,7 @@ int main(int, char**)
|
|||||||
ImGui_ImplWGPU_InitInfo init_info;
|
ImGui_ImplWGPU_InitInfo init_info;
|
||||||
init_info.Device = wgpu_device;
|
init_info.Device = wgpu_device;
|
||||||
init_info.NumFramesInFlight = 3;
|
init_info.NumFramesInFlight = 3;
|
||||||
init_info.RenderTargetFormat = wgpu_preferred_fmt;
|
init_info.RenderTargetFormat = wgpu_surface_configuration.format;
|
||||||
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
|
init_info.DepthStencilFormat = WGPUTextureFormat_Undefined;
|
||||||
ImGui_ImplWGPU_Init(&init_info);
|
ImGui_ImplWGPU_Init(&init_info);
|
||||||
|
|
||||||
@@ -181,6 +164,23 @@ int main(int, char**)
|
|||||||
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
||||||
ResizeSurface(width, height);
|
ResizeSurface(width, height);
|
||||||
|
|
||||||
|
// Check surface status for error. If texture is not optimal, try to reconfigure the surface.
|
||||||
|
WGPUSurfaceTexture surface_texture;
|
||||||
|
wgpuSurfaceGetCurrentTexture(wgpu_surface, &surface_texture);
|
||||||
|
if (ImGui_ImplWGPU_IsSurfaceStatusError(surface_texture.status))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unrecoverable Surface Texture status=%#.8x\n", surface_texture.status);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(surface_texture.status))
|
||||||
|
{
|
||||||
|
if (surface_texture.texture)
|
||||||
|
wgpuTextureRelease(surface_texture.texture);
|
||||||
|
if (width > 0 && height > 0)
|
||||||
|
ResizeSurface(width, height);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Start the Dear ImGui frame
|
// Start the Dear ImGui frame
|
||||||
ImGui_ImplWGPU_NewFrame();
|
ImGui_ImplWGPU_NewFrame();
|
||||||
ImGui_ImplGlfw_NewFrame();
|
ImGui_ImplGlfw_NewFrame();
|
||||||
@@ -226,17 +226,21 @@ int main(int, char**)
|
|||||||
// Rendering
|
// Rendering
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|
||||||
#ifndef __EMSCRIPTEN__
|
WGPUTextureViewDescriptor view_desc = {};
|
||||||
// Tick needs to be called in Dawn to display validation errors
|
view_desc.format = wgpu_surface_configuration.format;
|
||||||
wgpuDeviceTick(wgpu_device);
|
view_desc.dimension = WGPUTextureViewDimension_2D ;
|
||||||
#endif
|
view_desc.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED;
|
||||||
|
view_desc.arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED;
|
||||||
|
view_desc.aspect = WGPUTextureAspect_All;
|
||||||
|
|
||||||
|
WGPUTextureView texture_view = wgpuTextureCreateView(surface_texture.texture, &view_desc);
|
||||||
|
|
||||||
WGPURenderPassColorAttachment color_attachments = {};
|
WGPURenderPassColorAttachment color_attachments = {};
|
||||||
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
|
color_attachments.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
|
||||||
color_attachments.loadOp = WGPULoadOp_Clear;
|
color_attachments.loadOp = WGPULoadOp_Clear;
|
||||||
color_attachments.storeOp = WGPUStoreOp_Store;
|
color_attachments.storeOp = WGPUStoreOp_Store;
|
||||||
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
|
color_attachments.clearValue = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
|
||||||
color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
|
color_attachments.view = texture_view;
|
||||||
|
|
||||||
WGPURenderPassDescriptor render_pass_desc = {};
|
WGPURenderPassDescriptor render_pass_desc = {};
|
||||||
render_pass_desc.colorAttachmentCount = 1;
|
render_pass_desc.colorAttachmentCount = 1;
|
||||||
@@ -252,14 +256,16 @@ int main(int, char**)
|
|||||||
|
|
||||||
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
|
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
|
||||||
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
|
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
|
||||||
WGPUQueue wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
|
|
||||||
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
|
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
|
||||||
|
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
wgpuSwapChainPresent(wgpu_swap_chain);
|
wgpuSurfacePresent(wgpu_surface);
|
||||||
|
// Tick needs to be called in Dawn to display validation errors
|
||||||
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||||
|
wgpuDeviceTick(wgpu_device);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
wgpuTextureViewRelease(color_attachments.view);
|
wgpuTextureViewRelease(texture_view);
|
||||||
wgpuRenderPassEncoderRelease(pass);
|
wgpuRenderPassEncoderRelease(pass);
|
||||||
wgpuCommandEncoderRelease(encoder);
|
wgpuCommandEncoderRelease(encoder);
|
||||||
wgpuCommandBufferRelease(cmd_buffer);
|
wgpuCommandBufferRelease(cmd_buffer);
|
||||||
@@ -273,75 +279,298 @@ int main(int, char**)
|
|||||||
ImGui_ImplGlfw_Shutdown();
|
ImGui_ImplGlfw_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
wgpuSurfaceUnconfigure(wgpu_surface);
|
||||||
|
wgpuSurfaceRelease(wgpu_surface);
|
||||||
|
wgpuQueueRelease(wgpu_queue);
|
||||||
|
wgpuDeviceRelease(wgpu_device);
|
||||||
|
wgpuInstanceRelease(wgpu_instance);
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __EMSCRIPTEN__
|
// GLFW helper to create a WebGPU surface, used only in WGPU-Native. DAWN-Native already has a built-in function
|
||||||
static WGPUAdapter RequestAdapter(WGPUInstance instance)
|
// As of today (2025/10) there is no "official" support in GLFW to create a surface for WebGPU backend
|
||||||
{
|
// This stub uses "low level" GLFW calls to acquire information from a specific Window Manager.
|
||||||
auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData)
|
// Currently supported platforms: Windows / Linux (X11 and Wayland) / MacOS. Not necessary nor available with EMSCRIPTEN.
|
||||||
{
|
#if !defined(__EMSCRIPTEN__) && (defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) || defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN))
|
||||||
if (status == WGPURequestAdapterStatus_Success)
|
|
||||||
*(WGPUAdapter*)pUserData = adapter;
|
|
||||||
else
|
|
||||||
printf("Could not get WebGPU adapter: %s\n", message);
|
|
||||||
};
|
|
||||||
WGPUAdapter adapter;
|
|
||||||
wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter);
|
|
||||||
return adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
static WGPUDevice RequestDevice(WGPUAdapter adapter)
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||||
|
#define GLFW_HAS_X11_OR_WAYLAND 1
|
||||||
|
#else
|
||||||
|
#define GLFW_HAS_X11_OR_WAYLAND 0
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
#undef APIENTRY
|
||||||
|
#ifndef GLFW_EXPOSE_NATIVE_WIN32 // for glfwGetWin32Window()
|
||||||
|
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||||
|
#endif
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#ifndef GLFW_EXPOSE_NATIVE_COCOA // for glfwGetCocoaWindow()
|
||||||
|
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||||
|
#endif
|
||||||
|
#elif GLFW_HAS_X11_OR_WAYLAND
|
||||||
|
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
|
||||||
|
#define GLFW_EXPOSE_NATIVE_X11
|
||||||
|
#endif
|
||||||
|
#ifndef GLFW_EXPOSE_NATIVE_WAYLAND
|
||||||
|
#if defined(__has_include) && __has_include(<wayland-client.h>)
|
||||||
|
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
|
#undef Status // X11 headers are leaking this.
|
||||||
|
|
||||||
|
WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window)
|
||||||
{
|
{
|
||||||
auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* pUserData)
|
ImGui_ImplWGPU_CreateSurfaceInfo create_info = {};
|
||||||
|
create_info.Instance = instance;
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||||
{
|
{
|
||||||
if (status == WGPURequestDeviceStatus_Success)
|
create_info.System = "cocoa";
|
||||||
*(WGPUDevice*)pUserData = device;
|
create_info.RawWindow = (void*)glfwGetCocoaWindow(window);
|
||||||
else
|
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||||
printf("Could not get WebGPU device: %s\n", message);
|
}
|
||||||
};
|
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||||
WGPUDevice device;
|
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND)
|
||||||
wgpuAdapterRequestDevice(adapter, nullptr, onDeviceRequestEnded, (void*)&device);
|
{
|
||||||
return device;
|
create_info.System = "wayland";
|
||||||
|
create_info.RawDisplay = (void*)glfwGetWaylandDisplay();
|
||||||
|
create_info.RawSurface = (void*)glfwGetWaylandWindow(window);
|
||||||
|
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||||
|
}
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_X11)
|
||||||
|
if (glfwGetPlatform() == GLFW_PLATFORM_X11)
|
||||||
|
{
|
||||||
|
create_info.System = "x11";
|
||||||
|
create_info.RawWindow = (void*)glfwGetX11Window(window);
|
||||||
|
create_info.RawDisplay = (void*)glfwGetX11Display();
|
||||||
|
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||||
|
}
|
||||||
|
#elif defined(GLFW_EXPOSE_NATIVE_WIN32)
|
||||||
|
{
|
||||||
|
create_info.System = "win32";
|
||||||
|
create_info.RawWindow = (void*)glfwGetWin32Window(window);
|
||||||
|
create_info.RawInstance = (void*)::GetModuleHandle(NULL);
|
||||||
|
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "Unsupported WebGPU native platform!"
|
||||||
|
#endif
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||||
|
static WGPUAdapter RequestAdapter(wgpu::Instance& instance)
|
||||||
|
{
|
||||||
|
wgpu::Adapter acquired_adapter;
|
||||||
|
wgpu::RequestAdapterOptions adapter_options;
|
||||||
|
auto onRequestAdapter = [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter, wgpu::StringView message)
|
||||||
|
{
|
||||||
|
if (status != wgpu::RequestAdapterStatus::Success)
|
||||||
|
{
|
||||||
|
printf("Failed to get an adapter: %s\n", message.data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
acquired_adapter = std::move(adapter);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Synchronously (wait until) acquire Adapter
|
||||||
|
wgpu::Future waitAdapterFunc { instance.RequestAdapter(&adapter_options, wgpu::CallbackMode::WaitAnyOnly, onRequestAdapter) };
|
||||||
|
wgpu::WaitStatus waitStatusAdapter = instance.WaitAny(waitAdapterFunc, UINT64_MAX);
|
||||||
|
IM_ASSERT(acquired_adapter != nullptr && waitStatusAdapter == wgpu::WaitStatus::Success && "Error on Adapter request");
|
||||||
|
return acquired_adapter.MoveToCHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter)
|
||||||
|
{
|
||||||
|
// Set device callback functions
|
||||||
|
wgpu::DeviceDescriptor device_desc;
|
||||||
|
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
|
||||||
|
[](const wgpu::Device&, wgpu::DeviceLostReason type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetDeviceLostReasonName((WGPUDeviceLostReason)type), msg.data); }
|
||||||
|
);
|
||||||
|
device_desc.SetUncapturedErrorCallback(
|
||||||
|
[](const wgpu::Device&, wgpu::ErrorType type, wgpu::StringView msg) { fprintf(stderr, "%s error: %s\n", ImGui_ImplWGPU_GetErrorTypeName((WGPUErrorType)type), msg.data); }
|
||||||
|
);
|
||||||
|
|
||||||
|
wgpu::Device acquired_device;
|
||||||
|
auto onRequestDevice = [&](wgpu::RequestDeviceStatus status, wgpu::Device local_device, wgpu::StringView message)
|
||||||
|
{
|
||||||
|
if (status != wgpu::RequestDeviceStatus::Success)
|
||||||
|
{
|
||||||
|
printf("Failed to get an device: %s\n", message.data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
acquired_device = std::move(local_device);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Synchronously (wait until) get Device
|
||||||
|
wgpu::Future waitDeviceFunc { adapter.RequestDevice(&device_desc, wgpu::CallbackMode::WaitAnyOnly, onRequestDevice) };
|
||||||
|
wgpu::WaitStatus waitStatusDevice = instance.WaitAny(waitDeviceFunc, UINT64_MAX);
|
||||||
|
IM_ASSERT(acquired_device != nullptr && waitStatusDevice == wgpu::WaitStatus::Success && "Error on Device request");
|
||||||
|
return acquired_device.MoveToCHandle();
|
||||||
|
}
|
||||||
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
// Adapter and device initialization via JS
|
||||||
|
EM_ASYNC_JS( void, getAdapterAndDeviceViaJS, (),
|
||||||
|
{
|
||||||
|
if (!navigator.gpu)
|
||||||
|
throw Error("WebGPU not supported.");
|
||||||
|
const adapter = await navigator.gpu.requestAdapter();
|
||||||
|
const device = await adapter.requestDevice();
|
||||||
|
Module.preinitializedWebGPUDevice = device;
|
||||||
|
} );
|
||||||
|
#else // __EMSCRIPTEN__
|
||||||
|
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
||||||
|
{
|
||||||
|
if (status == WGPURequestAdapterStatus_Success)
|
||||||
|
{
|
||||||
|
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||||
|
*extAdapter = adapter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
||||||
|
{
|
||||||
|
if (status == WGPURequestDeviceStatus_Success)
|
||||||
|
{
|
||||||
|
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||||
|
*extDevice = device;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Request_device status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
||||||
|
{
|
||||||
|
WGPURequestAdapterOptions adapter_options = {};
|
||||||
|
|
||||||
|
WGPUAdapter local_adapter;
|
||||||
|
WGPURequestAdapterCallbackInfo adapterCallbackInfo = {};
|
||||||
|
adapterCallbackInfo.callback = handle_request_adapter;
|
||||||
|
adapterCallbackInfo.userdata1 = &local_adapter;
|
||||||
|
|
||||||
|
wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
||||||
|
IM_ASSERT(local_adapter && "Error on Adapter request");
|
||||||
|
return local_adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WGPUDevice RequestDevice(WGPUAdapter& adapter)
|
||||||
|
{
|
||||||
|
WGPUDevice local_device;
|
||||||
|
WGPURequestDeviceCallbackInfo deviceCallbackInfo = {};
|
||||||
|
deviceCallbackInfo.callback = handle_request_device;
|
||||||
|
deviceCallbackInfo.userdata1 = &local_device;
|
||||||
|
wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
||||||
|
IM_ASSERT(local_device && "Error on Device request");
|
||||||
|
return local_device;
|
||||||
|
}
|
||||||
|
#endif // __EMSCRIPTEN__
|
||||||
|
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
static bool InitWGPU(GLFWwindow* window)
|
static bool InitWGPU(GLFWwindow* window)
|
||||||
{
|
{
|
||||||
wgpu::Instance instance = wgpuCreateInstance(nullptr);
|
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
|
||||||
|
|
||||||
|
// Google DAWN backend: Adapter and Device acquisition, Surface creation
|
||||||
|
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||||
|
wgpu::InstanceDescriptor instance_desc = {};
|
||||||
|
static constexpr wgpu::InstanceFeatureName timedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
|
||||||
|
instance_desc.requiredFeatureCount = 1;
|
||||||
|
instance_desc.requiredFeatures = &timedWaitAny;
|
||||||
|
wgpu::Instance instance = wgpu::CreateInstance(&instance_desc);
|
||||||
|
|
||||||
|
wgpu::Adapter adapter = RequestAdapter(instance);
|
||||||
|
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter.Get());
|
||||||
|
|
||||||
|
wgpu_device = RequestDevice(instance, adapter);
|
||||||
|
|
||||||
|
// Create the surface.
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
wgpu_device = emscripten_webgpu_get_device();
|
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvas_desc = {};
|
||||||
if (!wgpu_device)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wgpu::SurfaceDescriptorFromCanvasHTMLSelector canvas_desc = {};
|
|
||||||
canvas_desc.selector = "#canvas";
|
canvas_desc.selector = "#canvas";
|
||||||
|
|
||||||
wgpu::SurfaceDescriptor surface_desc = {};
|
wgpu::SurfaceDescriptor surface_desc = {};
|
||||||
surface_desc.nextInChain = &canvas_desc;
|
surface_desc.nextInChain = &canvas_desc;
|
||||||
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
|
wgpu_surface = instance.CreateSurface(&surface_desc).MoveToCHandle();
|
||||||
|
|
||||||
wgpu::Adapter adapter = {};
|
|
||||||
wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter);
|
|
||||||
#else
|
#else
|
||||||
WGPUAdapter adapter = RequestAdapter(instance.Get());
|
wgpu_surface = CreateWGPUSurface(instance.Get(), window);
|
||||||
if (!adapter)
|
|
||||||
return false;
|
|
||||||
wgpu_device = RequestDevice(adapter);
|
|
||||||
|
|
||||||
wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window);
|
|
||||||
if (!surface)
|
|
||||||
return false;
|
|
||||||
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
|
|
||||||
#endif
|
#endif
|
||||||
|
if (!wgpu_surface)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Moving Dawn objects into WGPU handles
|
// Moving Dawn objects into WGPU handles
|
||||||
wgpu_instance = instance.MoveToCHandle();
|
wgpu_instance = instance.MoveToCHandle();
|
||||||
wgpu_surface = surface.MoveToCHandle();
|
|
||||||
|
|
||||||
wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr);
|
WGPUSurfaceCapabilities surface_capabilities = {};
|
||||||
|
wgpuSurfaceGetCapabilities(wgpu_surface, adapter.Get(), &surface_capabilities);
|
||||||
|
|
||||||
|
preferred_fmt = surface_capabilities.formats[0];
|
||||||
|
|
||||||
|
// WGPU backend: Adapter and Device acquisition, Surface creation
|
||||||
|
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||||
|
wgpu_instance = wgpuCreateInstance(nullptr);
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
getAdapterAndDeviceViaJS();
|
||||||
|
|
||||||
|
wgpu_device = emscripten_webgpu_get_device();
|
||||||
|
IM_ASSERT(wgpu_device != nullptr && "Error creating the Device");
|
||||||
|
|
||||||
|
WGPUSurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
|
||||||
|
html_surface_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector;
|
||||||
|
html_surface_desc.selector = "#canvas";
|
||||||
|
|
||||||
|
WGPUSurfaceDescriptor surface_desc = {};
|
||||||
|
surface_desc.nextInChain = &html_surface_desc.chain;
|
||||||
|
|
||||||
|
// Create the surface.
|
||||||
|
wgpu_surface = wgpuInstanceCreateSurface(wgpu_instance, &surface_desc);
|
||||||
|
preferred_fmt = wgpuSurfaceGetPreferredFormat(wgpu_surface, {} /* adapter */);
|
||||||
|
#else // __EMSCRIPTEN__
|
||||||
|
wgpuSetLogCallback(
|
||||||
|
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||||
|
);
|
||||||
|
wgpuSetLogLevel(WGPULogLevel_Warn);
|
||||||
|
|
||||||
|
WGPUAdapter adapter = RequestAdapter(wgpu_instance);
|
||||||
|
ImGui_ImplWGPU_DebugPrintAdapterInfo(adapter);
|
||||||
|
|
||||||
|
wgpu_device = RequestDevice(adapter);
|
||||||
|
|
||||||
|
// Create the surface.
|
||||||
|
wgpu_surface = CreateWGPUSurface(wgpu_instance, window);
|
||||||
|
if (!wgpu_surface)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WGPUSurfaceCapabilities surface_capabilities = {};
|
||||||
|
wgpuSurfaceGetCapabilities(wgpu_surface, adapter, &surface_capabilities);
|
||||||
|
|
||||||
|
preferred_fmt = surface_capabilities.formats[0];
|
||||||
|
#endif // __EMSCRIPTEN__
|
||||||
|
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||||
|
|
||||||
|
wgpu_surface_configuration.presentMode = WGPUPresentMode_Fifo;
|
||||||
|
wgpu_surface_configuration.alphaMode = WGPUCompositeAlphaMode_Auto;
|
||||||
|
wgpu_surface_configuration.usage = WGPUTextureUsage_RenderAttachment;
|
||||||
|
wgpu_surface_configuration.width = wgpu_surface_width;
|
||||||
|
wgpu_surface_configuration.height = wgpu_surface_height;
|
||||||
|
wgpu_surface_configuration.device = wgpu_device;
|
||||||
|
wgpu_surface_configuration.format = preferred_fmt;
|
||||||
|
|
||||||
|
wgpuSurfaceConfigure(wgpu_surface, &wgpu_surface_configuration);
|
||||||
|
wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en-us">
|
|
||||||
<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+GLFW+WebGPU example</title>
|
|
||||||
<style>
|
|
||||||
body { margin: 0; background-color: black }
|
|
||||||
.emscripten {
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
border: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
display: block;
|
|
||||||
image-rendering: optimizeSpeed;
|
|
||||||
image-rendering: -moz-crisp-edges;
|
|
||||||
image-rendering: -o-crisp-edges;
|
|
||||||
image-rendering: -webkit-optimize-contrast;
|
|
||||||
image-rendering: optimize-contrast;
|
|
||||||
image-rendering: crisp-edges;
|
|
||||||
image-rendering: pixelated;
|
|
||||||
-ms-interpolation-mode: nearest-neighbor;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
|
||||||
<script type='text/javascript'>
|
|
||||||
var Module;
|
|
||||||
(async () => {
|
|
||||||
Module = {
|
|
||||||
preRun: [],
|
|
||||||
postRun: [],
|
|
||||||
print: (function() {
|
|
||||||
return function(text) {
|
|
||||||
text = Array.prototype.slice.call(arguments).join(' ');
|
|
||||||
console.log(text);
|
|
||||||
};
|
|
||||||
})(),
|
|
||||||
printErr: function(text) {
|
|
||||||
text = Array.prototype.slice.call(arguments).join(' ');
|
|
||||||
console.error(text);
|
|
||||||
},
|
|
||||||
canvas: (function() {
|
|
||||||
var canvas = document.getElementById('canvas');
|
|
||||||
//canvas.addEventListener("webglcontextlost", function(e) { alert('FIXME: WebGL context lost, please reload the page'); e.preventDefault(); }, false);
|
|
||||||
return canvas;
|
|
||||||
})(),
|
|
||||||
setStatus: function(text) {
|
|
||||||
console.log("status: " + text);
|
|
||||||
},
|
|
||||||
monitorRunDependencies: function(left) {
|
|
||||||
// no run dependencies to log
|
|
||||||
}
|
|
||||||
};
|
|
||||||
window.onerror = function() {
|
|
||||||
console.log("onerror: " + event);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize the graphics adapter
|
|
||||||
{
|
|
||||||
if (!navigator.gpu) {
|
|
||||||
throw Error("WebGPU not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const adapter = await navigator.gpu.requestAdapter();
|
|
||||||
const device = await adapter.requestDevice();
|
|
||||||
Module.preinitializedWebGPUDevice = device;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const js = document.createElement('script');
|
|
||||||
js.async = true;
|
|
||||||
js.src = "index.js";
|
|
||||||
document.body.appendChild(js);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user