diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c5f395..e8290e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}) diff --git a/assets/shaders/shaders.slang b/assets/shaders/shaders.slang index 55b5ffc..ec9447f 100644 --- a/assets/shaders/shaders.slang +++ b/assets/shaders/shaders.slang @@ -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 camera; + [shader("vertex")] -VertexOut vsMain(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID, StructuredBuffer vertices, uniform STDCamera camera) { +VertexOut vsMain(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID, [vk::binding(1, 0)] StructuredBuffer vertices) { return VertexOut(mul(camera.mvp, float4(vertices[vertex_id].pos, 1.0)), vertices[vertex_id].col); } diff --git a/src/main.cpp b/src/main.cpp index 00e956b..d893c4d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 #ifdef EMSCRIPTEN #include "emscripten/emscripten.h" #endif -#define GLM_FORCE_ALIGNED_GENTYPES #include #include #include #include #include #include +#include +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include #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 start(stream), end{}; + std::istreambuf_iterator 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(width), static_cast(height), 0.001f, 100.0f); - camera.mvp = glm::mat4(1.0f); + camera.mvp = glm::perspectiveRH(glm::radians(90.0f), static_cast(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 { });