diff --git a/3rdparty/dawn/include/webgpu/webgpu.h b/3rdparty/dawn/include/webgpu/webgpu.h index 2d860a2ed..61721dec3 100644 --- a/3rdparty/dawn/include/webgpu/webgpu.h +++ b/3rdparty/dawn/include/webgpu/webgpu.h @@ -27,10 +27,6 @@ // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifdef __EMSCRIPTEN__ -#error "Do not include this header. Emscripten already provides headers needed for WebGPU." -#endif - #ifndef WEBGPU_H_ #define WEBGPU_H_ diff --git a/include/bgfx/embedded_shader.h b/include/bgfx/embedded_shader.h index c128b5e2e..077f8dfba 100644 --- a/include/bgfx/embedded_shader.h +++ b/include/bgfx/embedded_shader.h @@ -90,6 +90,7 @@ #ifndef BGFX_PLATFORM_SUPPORTS_WGSL # define BGFX_PLATFORM_SUPPORTS_WGSL (0 \ + || BX_PLATFORM_EMSCRIPTEN \ || BX_PLATFORM_LINUX \ || BX_PLATFORM_WINDOWS \ || BX_PLATFORM_OSX \ diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index 14fd4f32a..bb3974720 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -887,6 +887,12 @@ WGPU_IMPORT renderCtx->m_device = _device; } + WGPUWaitStatus waitForFuture(WGPUFutureWaitInfo& _fwi) + { + wgpuInstanceProcessEvents(m_instance); + return wgpuInstanceWaitAny(m_instance, 1, &_fwi, UINT64_MAX); + } + bool init(const Init& _init) { struct ErrorState @@ -923,6 +929,7 @@ WGPU_IMPORT bool imported = true; +#if !BX_PLATFORM_EMSCRIPTEN m_webgpuDll = bx::dlopen( #if BX_PLATFORM_WINDOWS "webgpu_dawn.dll" @@ -970,12 +977,21 @@ WGPU_IMPORT goto error; } +#else // BX_PLATFORM_EMSCRIPTEN + BX_TRACE("Emscripten: Using statically linked WebGPU."); + m_webgpuDll = NULL; + errorState = ErrorState::LoadedWebGPU; + +#endif // !BX_PLATFORM_EMSCRIPTEN + { { WGPUInstanceFeatureName requiredFeatures[] = { WGPUInstanceFeatureName_TimedWaitAny, +#if !BX_PLATFORM_EMSCRIPTEN WGPUInstanceFeatureName_ShaderSourceSPIRV, +#endif // !BX_PLATFORM_EMSCRIPTEN }; WGPUInstanceDescriptor instanceDesc = @@ -1021,7 +1037,7 @@ WGPU_IMPORT .completed = false, }; - WGPUWaitStatus waitStatus = wgpuInstanceWaitAny(m_instance, 1, &fwi, UINT64_MAX); + WGPUWaitStatus waitStatus = waitForFuture(fwi); if (WGPUWaitStatus_Success != waitStatus || NULL == m_adapter) @@ -1157,15 +1173,18 @@ WGPU_IMPORT if (WGPUStatus_Success == status) { +#if !BX_PLATFORM_EMSCRIPTEN requiredLimits.maxComputeWorkgroupSizeX = 1024; requiredLimits.maxComputeWorkgroupSizeY = 1024; requiredLimits.maxComputeWorkgroupSizeZ = 64; +#endif // !BX_PLATFORM_EMSCRIPTEN } static constexpr uint32_t kMaxEnabledTogles = 10; const char* enabledToggles[kMaxEnabledTogles]; uint32_t enabledTogglesCount = 0; +#if !BX_PLATFORM_EMSCRIPTEN enabledToggles[enabledTogglesCount++] = "allow_unsafe_apis"; // TimestampWrite requires this. if (_init.debug) @@ -1207,10 +1226,15 @@ WGPU_IMPORT .disabledToggleCount = 0, .disabledToggles = NULL, }; +#endif // !BX_PLATFORM_EMSCRIPTEN WGPUDeviceDescriptor deviceDesc = { +#if !BX_PLATFORM_EMSCRIPTEN .nextInChain = &dawnTogglesDescriptor.chain, +#else + .nextInChain = NULL, +#endif .label = WGPU_STRING_VIEW_INIT, .requiredFeatureCount = requiredFeatureCount, .requiredFeatures = requiredFeatures, @@ -1219,7 +1243,7 @@ WGPU_IMPORT .deviceLostCallbackInfo = { .nextInChain = NULL, - .mode = WGPUCallbackMode_WaitAnyOnly, + .mode = WGPUCallbackMode_AllowSpontaneous, .callback = deviceLostCb, .userdata1 = this, .userdata2 = NULL, @@ -1246,7 +1270,7 @@ WGPU_IMPORT .completed = false, }; - WGPUWaitStatus waitStatus = wgpuInstanceWaitAny(m_instance, 1, &fwi, UINT64_MAX); + WGPUWaitStatus waitStatus = waitForFuture(fwi); if (WGPUWaitStatus_Success != waitStatus || NULL == m_device) @@ -4337,7 +4361,7 @@ WGPU_IMPORT { m_resolution = _resolution; - WGPUSurfaceCapabilities surfaceCaps; + WGPUSurfaceCapabilities surfaceCaps = WGPU_SURFACE_CAPABILITIES_INIT; WGPUStatus status = WGPU_CHECK(wgpuSurfaceGetCapabilities(m_surface, s_renderWGPU->m_adapter, &surfaceCaps) ); if (WGPUStatus_Success != status) @@ -4361,6 +4385,24 @@ m_resolution.formatColor = TextureFormat::BGRA8; } } +#if BX_PLATFORM_EMSCRIPTEN + if (WGPUTextureFormat_Undefined != format + && surfaceCaps.formatCount > 0 + && format != surfaceCaps.formats[0]) + { + format = surfaceCaps.formats[0]; + + if (WGPUTextureFormat_BGRA8Unorm == format) + { + m_resolution.formatColor = TextureFormat::BGRA8; + } + else if (WGPUTextureFormat_RGBA8Unorm == format) + { + m_resolution.formatColor = TextureFormat::RGBA8; + } + } +#endif // BX_PLATFORM_EMSCRIPTEN + BX_ASSERT(WGPUTextureFormat_Undefined != format, "SwapChain surface format is not available!"); m_surfaceConfig = @@ -4386,6 +4428,9 @@ m_resolution.formatColor = TextureFormat::BGRA8; const uint32_t msaa = s_msaa[(_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; + wgpuRelease(m_depthStencilView); + wgpuRelease(m_msaaTextureView); + if (bimg::isDepth(bimg::TextureFormat::Enum(m_resolution.formatDepthStencil) ) ) { WGPUTextureDescriptor textureDesc = @@ -4471,6 +4516,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; }; m_msaaTextureView = WGPU_CHECK(wgpuTextureCreateView(texture, &textureViewDesc) ); + wgpuRelease(texture); } return true; @@ -4642,6 +4688,26 @@ m_resolution.formatColor = TextureFormat::BGRA8; .layer = toMetalLayer(m_nwh), }; + surfaceDesc = + { + .nextInChain = &surfaceSource.chain, + .label = toWGPUStringView("SwapChainWGPU"), + }; +#elif BX_PLATFORM_EMSCRIPTEN + WGPUEmscriptenSurfaceSourceCanvasHTMLSelector surfaceSource = + { + .chain = + { + .next = NULL, + .sType = WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector, + }, + .selector = + { + .data = static_cast(m_nwh), + .length = uint32_t(bx::strLen(static_cast(m_nwh))), + }, + }; + surfaceDesc = { .nextInChain = &surfaceSource.chain, @@ -4659,7 +4725,9 @@ m_resolution.formatColor = TextureFormat::BGRA8; void SwapChainWGPU::present() { wgpuRelease(m_textureView); +#if !BX_PLATFORM_EMSCRIPTEN WGPU_CHECK(wgpuSurfacePresent(m_surface) ); +#endif // !BX_PLATFORM_EMSCRIPTEN WGPUSurfaceTexture surfaceTexture = WGPU_SURFACE_TEXTURE_INIT; wgpuSurfaceGetCurrentTexture(m_surface, &surfaceTexture); @@ -4874,30 +4942,42 @@ m_resolution.formatColor = TextureFormat::BGRA8; WGPUCommandBuffer commandBuffer = WGPU_CHECK(wgpuCommandEncoderFinish(m_commandEncoder, NULL) ); WGPU_CHECK(wgpuQueueSubmit(m_queue, 1, &commandBuffer) ); - WGPU_CHECK(wgpuQueueOnSubmittedWorkDone( - m_queue + m_future = wgpuQueueOnSubmittedWorkDone( + m_queue , { .nextInChain = NULL, .mode = WGPUCallbackMode_AllowProcessEvents, .callback = queueWorkDoneCb, .userdata1 = (void*)uintptr_t(m_counter), .userdata2 = NULL, - }) ); + }); wgpuRelease(commandBuffer); wgpuRelease(m_commandEncoder); ++m_counter; + #if !BX_PLATFORM_EMSCRIPTEN WGPU_CHECK(wgpuInstanceProcessEvents(s_renderWGPU->m_instance) ); + #endif // !BX_PLATFORM_EMSCRIPTEN m_commandEncoder = WGPU_CHECK(wgpuDeviceCreateCommandEncoder(s_renderWGPU->m_device, NULL) ); } void CommandQueueWGPU::wait() { + #if BX_PLATFORM_EMSCRIPTEN + wgpuInstanceProcessEvents(s_renderWGPU->m_instance); + #else while (0 < m_counter) { - WGPU_CHECK(wgpuInstanceProcessEvents(s_renderWGPU->m_instance) ); + WGPUFutureWaitInfo fwi = + { + .future = m_future, + .completed = false, + }; + + wgpuInstanceWaitAny(s_renderWGPU->m_instance, 1, &fwi, 1000000); } + #endif // BX_PLATFORM_EMSCRIPTEN } void CommandQueueWGPU::frame() diff --git a/src/renderer_webgpu.h b/src/renderer_webgpu.h index ece1d09bc..947e16cfa 100644 --- a/src/renderer_webgpu.h +++ b/src/renderer_webgpu.h @@ -24,7 +24,9 @@ # define WGPU_CHECK(_call) _call #endif // BGFX_CONFIG_DEBUG -#define WGPU_SKIP_DECLARATIONS +#if !BX_PLATFORM_EMSCRIPTEN +# define WGPU_SKIP_DECLARATIONS +#endif // !BX_PLATFORM_EMSCRIPTEN #include #if USE_WEBGPU_DYNAMIC_LIB @@ -307,11 +309,11 @@ WGPU_IGNORE_____(false, TextureGetDepthOrArrayLayers); \ WGPU_IGNORE_____(false, TextureGetDimension); \ WGPU_IGNORE_____(false, TextureGetFormat); \ - WGPU_IGNORE_____(false, TextureGetHeight); \ + WGPU_IMPORT_FUNC(false, TextureGetHeight); \ WGPU_IGNORE_____(false, TextureGetMipLevelCount); \ WGPU_IGNORE_____(false, TextureGetSampleCount); \ WGPU_IGNORE_____(false, TextureGetUsage); \ - WGPU_IGNORE_____(false, TextureGetWidth); \ + WGPU_IMPORT_FUNC(false, TextureGetWidth); \ WGPU_IGNORE_____(false, TexturePin); \ WGPU_IMPORT_FUNC(false, TextureSetLabel); \ WGPU_IGNORE_____(false, TextureUnpin); \ @@ -744,6 +746,7 @@ namespace wgpu { : m_queue(NULL) , m_commandEncoder(NULL) , m_counter(0) + , m_future(WGPU_FUTURE_INIT) { } @@ -767,6 +770,7 @@ namespace wgpu { WGPUCommandEncoder m_commandEncoder; uint32_t m_currentFrameInFlight; uint32_t m_counter; + WGPUFuture m_future; }; struct TimerQueryWGPU