[General] Update to emscripten 4.0.13's emdawnwebgpu

[General] First triangle!
This commit is contained in:
jstefanelli 2025-08-31 17:09:25 +02:00
parent f1e3a25f3a
commit cf374cd368
Signed by: jstefanelli
GPG key ID: 60EDE2437640D2AA
3 changed files with 28 additions and 17 deletions

View file

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 4.0)
project(wgpu-wasm LANGUAGES C CXX)
set(GLM_BUILD_LIBRARY FALSE)
set(GLM_BUILD_LIBRARY FALSE CACHE BOOL "")
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/contrib/glm)
add_custom_target(${CMAKE_PROJECT_NAME}_html COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/assets/index.html ${CMAKE_CURRENT_BINARY_DIR}/index.html
@ -27,6 +27,7 @@ function(compile_and_package_shader SHADER_NAME TARGET)
#TODO: Add deptfile generation via slang for recompilation when embedded files change
add_dependencies(${TARGET} ${TARGET}_shader_${SHADER_NAME})
target_link_options(${TARGET} PRIVATE --embed-file ${CMAKE_CURRENT_BINARY_DIR}/shaders/${SHADER_NAME}.wgsl@/shaders/${SHADER_NAME}.wgsl)
set_target_properties(${TARGET} PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/shaders/${SHADER_NAME}.wgsl)
endfunction()
compile_and_package_shader(shaders ${CMAKE_PROJECT_NAME})

View file

@ -1,4 +1,3 @@
struct STDVertex {
float3 pos;
float4 col;
@ -9,15 +8,17 @@ struct VertexOut {
float4 col;
};
struct STDCamera {
float4x4 mvp;
float3 position;
float3 direction;
};
[vk::binding(0, 0)]
uniform ConstantBuffer<STDCamera> camera;
[shader("vertex")]
VertexOut vsMain(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID, StructuredBuffer<STDVertex> vertices, uniform STDCamera camera) {
VertexOut vsMain(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID, [vk::binding(1, 0)] StructuredBuffer<STDVertex> vertices) {
return VertexOut(mul(camera.mvp, float4(vertices[vertex_id].pos, 1.0)), vertices[vertex_id].col);
}

View file

@ -1,16 +1,20 @@
#include "glm/ext/matrix_clip_space.hpp"
#include "glm/trigonometric.hpp"
#include "glm/ext/matrix_transform.hpp"
#include "webgpu/webgpu_cpp.h"
#include <webgpu/webgpu.h>
#ifdef EMSCRIPTEN
#include "emscripten/emscripten.h"
#endif
#define GLM_FORCE_ALIGNED_GENTYPES
#include <iostream>
#include <stdexcept>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>
#ifdef EMSCRIPTEN
#define SHADERS_ROOT "/shaders/"
@ -85,9 +89,12 @@ wgpu::BindGroup basic_bind_group;
void request_adapter() {
std::cout << "[WGPU] request_adapter()" << std::endl;
wgpu::InstanceFeatureName feature = wgpu::InstanceFeatureName::TimedWaitAny;
wgpu::InstanceDescriptor instance_desc{};
instance_desc.capabilities.timedWaitAnyEnable = true;
instance_desc.capabilities.timedWaitAnyMaxCount = 1;
instance_desc.requiredFeatureCount = 1;
instance_desc.requiredFeatures = &feature;
gpu_instance = wgpu::CreateInstance(&instance_desc);
@ -200,7 +207,7 @@ std::string load_shader_source(const std::string_view& shader_name) {
}
std::ifstream stream(path);
std::istream_iterator<char> start(stream), end{};
std::istreambuf_iterator<char> start(stream), end{};
return std::string(start, end);
}
@ -250,9 +257,11 @@ wgpu::PipelineLayout load_basic_pipeline_layout() {
layout_entries[0].binding = 1;
layout_entries[0].buffer.minBindingSize = sizeof(float) * 8 * 3; //At least 3 STDVertex entries
layout_entries[0].buffer.type = wgpu::BufferBindingType::ReadOnlyStorage;
layout_entries[0].visibility = wgpu::ShaderStage::Vertex;
layout_entries[1].binding = 0;
layout_entries[1].buffer.minBindingSize = sizeof(float) * 24; //1 STDCamera entry
layout_entries[1].buffer.type = wgpu::BufferBindingType::Uniform;
layout_entries[1].visibility = wgpu::ShaderStage::Vertex;
wgpu::BindGroupLayoutDescriptor group_desc{};
group_desc.entryCount = 2;
@ -337,8 +346,7 @@ void fill_buffers() {
staging_buffer.WriteMappedRange(0, sample_triangle.data(), sample_triangle.size() * sizeof(STDVertex));
STDCamera cam{};
//cam.mvp = glm::perspectiveFov(glm::radians(90.0f), 1280.0f, 720.0f, 0.001f, 100.0f);
cam.mvp = glm::mat4(1.0f);
cam.mvp = glm::perspectiveRH(glm::radians(90.0f), 1280.0f / 720.0f, 0.001f, 100.0f) * glm::lookAtRH(glm::vec3(0, 0, 0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0));
staging_buffer.WriteMappedRange(sizeof(STDVertex) * 3, &cam, sizeof(STDCamera));
staging_buffer.Unmap();
@ -357,9 +365,9 @@ void fill_buffers() {
gpu_device.GetQueue().Submit(1, &cmd);
auto f = gpu_device.GetQueue().OnSubmittedWorkDone(wgpu::CallbackMode::WaitAnyOnly, [](wgpu::QueueWorkDoneStatus status) -> void {
auto f = gpu_device.GetQueue().OnSubmittedWorkDone(wgpu::CallbackMode::WaitAnyOnly, [](wgpu::QueueWorkDoneStatus status, std::string_view error) -> void {
if (status != wgpu::QueueWorkDoneStatus::Success) {
std::cout << "WAAAA x2" << std::endl;
std::cout << "[WGPU] Initial copy error: " << error << std::endl;
}
});
@ -424,14 +432,15 @@ EM_JS(void, resize_canvas, (const char* canvas_id, int width, int height), {
});
void update_camera(int width, int height) {
std::cout << "[WGPU] Updating camera " << width << "x" << height << std::endl;
auto map_future = staging_buffer.MapAsync(wgpu::MapMode::Write, 0, sizeof(STDCamera), wgpu::CallbackMode::WaitAnyOnly, [width, height](wgpu::MapAsyncStatus status, std::string_view error) -> void {
if (status != wgpu::MapAsyncStatus::Success) {
std::cerr << "[WGPU] Map failure: " << error << std::endl;
throw std::runtime_error("Staging buffer map failure");
}
STDCamera camera{};
camera.mvp = glm::perspectiveFov(glm::radians(90.0f), static_cast<float>(width), static_cast<float>(height), 0.001f, 100.0f);
camera.mvp = glm::mat4(1.0f);
camera.mvp = glm::perspectiveRH(glm::radians(90.0f), static_cast<float>(width) / height, 0.01f, 10.0f) * glm::lookAtRH(glm::vec3(0, 0, 0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0));
staging_buffer.WriteMappedRange(0, &camera, sizeof(STDCamera));
staging_buffer.Unmap();
@ -445,7 +454,7 @@ void update_camera(int width, int height) {
gpu_device.GetQueue().Submit(1, &cmd);
auto copy_future = gpu_device.GetQueue().OnSubmittedWorkDone(wgpu::CallbackMode::WaitAnyOnly, [](wgpu::QueueWorkDoneStatus) -> void {
auto copy_future = gpu_device.GetQueue().OnSubmittedWorkDone(wgpu::CallbackMode::WaitAnyOnly, [](wgpu::QueueWorkDoneStatus, std::string_view) -> void {
});