Skip to content

[Feature]: Add WebGPU rendering backend#1

Open
bjfssd757 wants to merge 5 commits into
spaceengineworks:mainfrom
bjfssd757:main
Open

[Feature]: Add WebGPU rendering backend#1
bjfssd757 wants to merge 5 commits into
spaceengineworks:mainfrom
bjfssd757:main

Conversation

@bjfssd757

@bjfssd757 bjfssd757 commented Jun 19, 2026

Copy link
Copy Markdown

Description

WebGPU is a next-generation graphics API that acts as a modern, cross-platform abstraction layer over low-level native backends like DirectX 12, Vulkan, Metal, OpenGL, and OpenGL ES.

What's new

  • Added WebGPU backend support using Google's Dawn library as the reference implementation.
  • Implemented the IRenderer and IShader interfaces for the new backend.
  • Added standard UI shaders written in WGSL (WebGPU Shading Language).
  • Added CMake presets for MSVC with the Ninja generator, separating configurations for different rendering backends.

@IlanVinograd

Copy link
Copy Markdown
Collaborator
PS C:\Users\ilanv\DELETE> cmake --build build                          
MSBuild version 18.7.1+024f5b037 for .NET Framework

  Optikos.vcxproj -> C:\Users\ilanv\DELETE\build\optikos-build\Debug\Optikos.lib
  TestApp.vcxproj -> C:\Users\ilanv\DELETE\build\Debug\TestApp.exe
        Copying Optikos resources to TestApp...
PS C:\Users\ilanv\DELETE> C:\Users\ilanv\DELETE\build\Debug\TestApp.exe
Error: DynamicLib.Open: d3dcompiler_47.dll Windows Error: 87
    at EnsureFXC (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d\PlatformFunctions.cpp:117)
    at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d11\PlatformFunctionsD3D11.cpp:41)
    at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d11\BackendD3D11.cpp:89)

Warning: Couldn't load Vulkan: DynamicLib.Open: vulkan-1.dll Windows Error: 87
    at operator () (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\vulkan\BackendVk.cpp:363)
    at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\vulkan\BackendVk.cpp:368)
    at Create (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\vulkan\BackendVk.cpp:346)
    at operator () (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\vulkan\BackendVk.cpp:596)

Warning: No Dawn device lost callback was set. This is probably not intended. If you really want to ignore device lost and suppress this message, set the callback explicitly.

LOGS:


[14:19:57] [TRACE] Window opened
[14:19:58] [ERROR] Can't create WebGPU Device. Status: 3 | Error: DynamicLib.Open: dxil.dll Windows Error: 87
    at EnsureDXCLibraries (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\PlatformFunctionsD3D12.cpp:129)
    at EnsureDXC (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\BackendD3D12.cpp:94)
    at EnsureCompilerLibraries (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\DeviceD3D12.cpp:291)
    at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\DeviceD3D12.cpp:182)
    at Create (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\DeviceD3D12.cpp:88)

Code I use:

#include "optikos.hpp"

int main()
{
    Logger::add_logger("log");
    Optikos::Optikos app("Hello", 800, 480);

    auto btn = std::make_unique<Optikos::Button>(120, 30, Optikos::Vec2(20, 20), "Click me");
    btn->setEvent([]() { std::cout << "Clicked!\n"; });
    app.addWidget(1, std::move(btn));

    while (!app.should_close())
    {
        app.begin();
        app.end();
    }
}```


```cmake
cmake_minimum_required(VERSION 3.20)
project(TestApp LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# set(OPTIKOS_RENDERER "OPENGL" CACHE STRING "" FORCE)
set(OPTIKOS_RENDERER "WEBGPU" CACHE STRING "" FORCE)
# set(OPTIKOS_RENDERER "VULKAN" CACHE STRING "" FORCE)

set(OPTIKOS_PLATFORM "GLFW"   CACHE STRING "" FORCE)
set(OPTIKOS_INPUT    "GLFW"   CACHE STRING "" FORCE)

find_package(glfw3 CONFIG REQUIRED)

if(OPTIKOS_RENDERER STREQUAL "VULKAN")
    find_package(Vulkan REQUIRED MODULE)
    find_package(unofficial-shaderc CONFIG REQUIRED)
else()
    find_package(glad CONFIG REQUIRED)
endif()

#include(FetchContent)
#FetchContent_Declare(
#    Optikos
#    GIT_REPOSITORY https://github.com/IlanVinograd/Optikos
#    GIT_TAG main
#)
#FetchContent_MakeAvailable(Optikos)

add_subdirectory("C:/Users/ilanv/Optikos" optikos-build)

add_executable(TestApp main.cpp)

target_link_libraries(TestApp PRIVATE 
    Optikos::Optikos
    glfw
)

if(OPTIKOS_RENDERER STREQUAL "VULKAN")
    target_link_libraries(TestApp PRIVATE 
        Vulkan::Vulkan
        unofficial::shaderc::shaderc
    )
else()
    target_link_libraries(TestApp PRIVATE 
        glad::glad
    )
endif()

target_compile_definitions(TestApp PRIVATE
    OPTIKOS_RES_DIR="${optikos_SOURCE_DIR}/res/"
)

target_compile_definitions(TestApp PRIVATE
    OPTIKOS_RES_DIR="C:/Users/ilanv/Optikos/res/"
)

option(ENABLE_GPU_PROFILING "Enable GPU profiling" OFF)
if(ENABLE_GPU_PROFILING)
    target_compile_definitions(TestApp PRIVATE ENABLE_GPU_PROFILING)
    target_compile_definitions(Optikos PRIVATE ENABLE_GPU_PROFILING)
    message(STATUS "GPU Profiling: ON")
endif()

optikos_copy_resources(TestApp)

Comment thread CMakeLists.txt Outdated
Comment thread CMakeLists.txt Outdated
Comment thread CMakeLists.txt Outdated
Comment thread src/render/webgpu/WebGPURenderer.cpp Outdated
Comment thread src/optikos.cpp Outdated
Comment thread src/optikos.cpp Outdated
#endif

#include "optikos.hpp"
#include <memory>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/render/opengl/OpenGLRenderer.hpp Outdated
Comment thread src/platform/IWindow.hpp Outdated
Comment thread src/render/webgpu/WebGPURenderer.cpp Outdated
Comment thread src/render/webgpu/WebGPURenderer.cpp
@bjfssd757

Copy link
Copy Markdown
Author
PS C:\Users\ilanv\DELETE> cmake --build build                          
MSBuild version 18.7.1+024f5b037 for .NET Framework

  Optikos.vcxproj -> C:\Users\ilanv\DELETE\build\optikos-build\Debug\Optikos.lib
  TestApp.vcxproj -> C:\Users\ilanv\DELETE\build\Debug\TestApp.exe
        Copying Optikos resources to TestApp...
PS C:\Users\ilanv\DELETE> C:\Users\ilanv\DELETE\build\Debug\TestApp.exe
Error: DynamicLib.Open: d3dcompiler_47.dll Windows Error: 87
    at EnsureFXC (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d\PlatformFunctions.cpp:117)
    at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d11\PlatformFunctionsD3D11.cpp:41)
    at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d11\BackendD3D11.cpp:89)

Warning: Couldn't load Vulkan: DynamicLib.Open: vulkan-1.dll Windows Error: 87
    at operator () (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\vulkan\BackendVk.cpp:363)
    at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\vulkan\BackendVk.cpp:368)
    at Create (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\vulkan\BackendVk.cpp:346)
    at operator () (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\vulkan\BackendVk.cpp:596)

Warning: No Dawn device lost callback was set. This is probably not intended. If you really want to ignore device lost and suppress this message, set the callback explicitly.

LOGS:


[14:19:57] [TRACE] Window opened
[14:19:58] [ERROR] Can't create WebGPU Device. Status: 3 | Error: DynamicLib.Open: dxil.dll Windows Error: 87
    at EnsureDXCLibraries (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\PlatformFunctionsD3D12.cpp:129)
    at EnsureDXC (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\BackendD3D12.cpp:94)
    at EnsureCompilerLibraries (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\DeviceD3D12.cpp:291)
    at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\DeviceD3D12.cpp:182)
    at Create (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d12\DeviceD3D12.cpp:88)

Code I use:

#include "optikos.hpp"

int main()
{
    Logger::add_logger("log");
    Optikos::Optikos app("Hello", 800, 480);

    auto btn = std::make_unique<Optikos::Button>(120, 30, Optikos::Vec2(20, 20), "Click me");
    btn->setEvent([]() { std::cout << "Clicked!\n"; });
    app.addWidget(1, std::move(btn));

    while (!app.should_close())
    {
        app.begin();
        app.end();
    }
}```


```cmake
cmake_minimum_required(VERSION 3.20)
project(TestApp LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# set(OPTIKOS_RENDERER "OPENGL" CACHE STRING "" FORCE)
set(OPTIKOS_RENDERER "WEBGPU" CACHE STRING "" FORCE)
# set(OPTIKOS_RENDERER "VULKAN" CACHE STRING "" FORCE)

set(OPTIKOS_PLATFORM "GLFW"   CACHE STRING "" FORCE)
set(OPTIKOS_INPUT    "GLFW"   CACHE STRING "" FORCE)

find_package(glfw3 CONFIG REQUIRED)

if(OPTIKOS_RENDERER STREQUAL "VULKAN")
    find_package(Vulkan REQUIRED MODULE)
    find_package(unofficial-shaderc CONFIG REQUIRED)
else()
    find_package(glad CONFIG REQUIRED)
endif()

#include(FetchContent)
#FetchContent_Declare(
#    Optikos
#    GIT_REPOSITORY https://github.com/IlanVinograd/Optikos
#    GIT_TAG main
#)
#FetchContent_MakeAvailable(Optikos)

add_subdirectory("C:/Users/ilanv/Optikos" optikos-build)

add_executable(TestApp main.cpp)

target_link_libraries(TestApp PRIVATE 
    Optikos::Optikos
    glfw
)

if(OPTIKOS_RENDERER STREQUAL "VULKAN")
    target_link_libraries(TestApp PRIVATE 
        Vulkan::Vulkan
        unofficial::shaderc::shaderc
    )
else()
    target_link_libraries(TestApp PRIVATE 
        glad::glad
    )
endif()

target_compile_definitions(TestApp PRIVATE
    OPTIKOS_RES_DIR="${optikos_SOURCE_DIR}/res/"
)

target_compile_definitions(TestApp PRIVATE
    OPTIKOS_RES_DIR="C:/Users/ilanv/Optikos/res/"
)

option(ENABLE_GPU_PROFILING "Enable GPU profiling" OFF)
if(ENABLE_GPU_PROFILING)
    target_compile_definitions(TestApp PRIVATE ENABLE_GPU_PROFILING)
    target_compile_definitions(Optikos PRIVATE ENABLE_GPU_PROFILING)
    message(STATUS "GPU Profiling: ON")
endif()

optikos_copy_resources(TestApp)

Add the following to CMake:

if(WIN32)
add_custom_command(TARGET MyApp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_RUNTIME_DLLS:MyApp>
$<TARGET_FILE_DIR:MyApp>
)
endif()

This copies the DLLs that are needed for the build to the directory where the exe file located.

P.S. replace MyApp to your target name

@IlanVinograd

Copy link
Copy Markdown
Collaborator
cmake_minimum_required(VERSION 3.20)
project(TestApp LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# set(OPTIKOS_RENDERER "OPENGL" CACHE STRING "" FORCE)
 set(OPTIKOS_RENDERER "WEBGPU" CACHE STRING "" FORCE)
# set(OPTIKOS_RENDERER "VULKAN" CACHE STRING "" FORCE)

set(OPTIKOS_PLATFORM "GLFW"   CACHE STRING "" FORCE)
set(OPTIKOS_INPUT    "GLFW"   CACHE STRING "" FORCE)

find_package(glfw3 CONFIG REQUIRED)

if(OPTIKOS_RENDERER STREQUAL "VULKAN")
    find_package(Vulkan REQUIRED MODULE)
    find_package(unofficial-shaderc CONFIG REQUIRED)
else()
    find_package(glad CONFIG REQUIRED)
endif()

#include(FetchContent)
#FetchContent_Declare(
#    Optikos
#    GIT_REPOSITORY https://github.com/IlanVinograd/Optikos
#    GIT_TAG main
#)
#FetchContent_MakeAvailable(Optikos)

add_subdirectory("C:/Users/ilanv/Optikos" optikos-build)

add_executable(TestApp main.cpp)

target_link_libraries(TestApp PRIVATE 
    Optikos::Optikos
    glfw
)

if(OPTIKOS_RENDERER STREQUAL "VULKAN")
    target_link_libraries(TestApp PRIVATE 
        Vulkan::Vulkan
        unofficial::shaderc::shaderc
    )
else()
    target_link_libraries(TestApp PRIVATE 
        glad::glad
    )
endif()

target_compile_definitions(TestApp PRIVATE
    OPTIKOS_RES_DIR="${optikos_SOURCE_DIR}/res/"
)

target_compile_definitions(TestApp PRIVATE
    OPTIKOS_RES_DIR="C:/Users/ilanv/Optikos/res/"
)

option(ENABLE_GPU_PROFILING "Enable GPU profiling" OFF)
if(ENABLE_GPU_PROFILING)
    target_compile_definitions(TestApp PRIVATE ENABLE_GPU_PROFILING)
    target_compile_definitions(Optikos PRIVATE ENABLE_GPU_PROFILING)
    message(STATUS "GPU Profiling: ON")
endif()

optikos_copy_resources(TestApp)

if(WIN32)
    add_custom_command(
        TARGET TestApp POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        $<TARGET_RUNTIME_DLLS:TestApp>
        $<TARGET_FILE_DIR:TestApp>
        COMMAND_EXPAND_LISTS
    )
endif()

Same:
PS C:\Users\ilanv\DELETE> C:\Users\ilanv\DELETE\build\Debug\TestApp.exe
Error: DynamicLib.Open: d3dcompiler_47.dll Windows Error: 87
at EnsureFXC (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d\PlatformFunctions.cpp:117)
at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d11\PlatformFunctionsD3D11.cpp:41)
at Initialize (C:\Users\ilanv\vcpkg\buildtrees\dawn\src\423.175430-987edf0925.clean\src\dawn\native\d3d11\BackendD3D11.cpp:89)

Warning: Backend validation enabled but Dawn was not built with DAWN_ENABLE_VULKAN_VALIDATION_LAYERS.
Warning: No Dawn device lost callback was set. This is probably not intended. If you really want to ignore device lost and suppress this message, set the callback explicitly.
PS C:\Users\ilanv\DELETE>

@IlanVinograd

Copy link
Copy Markdown
Collaborator
cmake_minimum_required(VERSION 3.20)
project(TestApp LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# set(OPTIKOS_RENDERER "OPENGL" CACHE STRING "" FORCE)
 set(OPTIKOS_RENDERER "WEBGPU" CACHE STRING "" FORCE)
# set(OPTIKOS_RENDERER "VULKAN" CACHE STRING "" FORCE)

set(OPTIKOS_PLATFORM "GLFW"   CACHE STRING "" FORCE)
set(OPTIKOS_INPUT    "GLFW"   CACHE STRING "" FORCE)

find_package(glfw3 CONFIG REQUIRED)

if(OPTIKOS_RENDERER STREQUAL "VULKAN")
    find_package(Vulkan REQUIRED MODULE)
    find_package(unofficial-shaderc CONFIG REQUIRED)
else()
    find_package(glad CONFIG REQUIRED)
endif()

#include(FetchContent)
#FetchContent_Declare(
#    Optikos
#    GIT_REPOSITORY https://github.com/IlanVinograd/Optikos
#    GIT_TAG main
#)
#FetchContent_MakeAvailable(Optikos)

add_subdirectory("C:/Users/ilanv/Optikos" optikos-build)

add_executable(TestApp main.cpp)

target_link_libraries(TestApp PRIVATE 
    Optikos::Optikos
    glfw
)

if(OPTIKOS_RENDERER STREQUAL "VULKAN")
    target_link_libraries(TestApp PRIVATE 
        Vulkan::Vulkan
        unofficial::shaderc::shaderc
    )
else()
    target_link_libraries(TestApp PRIVATE 
        glad::glad
    )
endif()

target_compile_definitions(TestApp PRIVATE
    OPTIKOS_RES_DIR="${optikos_SOURCE_DIR}/res/"
)

target_compile_definitions(TestApp PRIVATE
    OPTIKOS_RES_DIR="C:/Users/ilanv/Optikos/res/"
)

option(ENABLE_GPU_PROFILING "Enable GPU profiling" OFF)
if(ENABLE_GPU_PROFILING)
    target_compile_definitions(TestApp PRIVATE ENABLE_GPU_PROFILING)
    target_compile_definitions(Optikos PRIVATE ENABLE_GPU_PROFILING)
    message(STATUS "GPU Profiling: ON")
endif()

optikos_copy_resources(TestApp)

if(WIN32 AND VCPKG_TOOLCHAIN)
    set(VCPKG_BIN_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin")
    set(VCPKG_DEBUG_BIN_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug/bin")

    add_custom_command(
        TARGET TestApp POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "$<IF:$<CONFIG:Debug>,${VCPKG_DEBUG_BIN_DIR}/dxcompiler.dll,${VCPKG_BIN_DIR}/dxcompiler.dll>"
        "$<IF:$<CONFIG:Debug>,${VCPKG_DEBUG_BIN_DIR}/dxil.dll,${VCPKG_BIN_DIR}/dxil.dll>"
        $<TARGET_FILE_DIR:TestApp>
        VERBATIM
    )
endif()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants