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 c8c2da5fb..c7e355673 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 = NULL, +#else .nextInChain = &dawnTogglesDescriptor.chain, +#endif // BX_PLATFORM_EMSCRIPTEN .label = WGPU_STRING_VIEW_INIT, .requiredFeatureCount = requiredFeatureCount, .requiredFeatures = requiredFeatures, @@ -1219,7 +1243,10 @@ WGPU_IMPORT .deviceLostCallbackInfo = { .nextInChain = NULL, - .mode = WGPUCallbackMode_WaitAnyOnly, + .mode = BX_ENABLED(BX_PLATFORM_EMSCRIPTEN) + ? WGPUCallbackMode_AllowSpontaneous + : WGPUCallbackMode_WaitAnyOnly + , .callback = deviceLostCb, .userdata1 = this, .userdata2 = NULL, @@ -1246,7 +1273,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) @@ -4340,7 +4367,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) @@ -4364,6 +4391,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 = @@ -4389,6 +4434,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 = @@ -4474,6 +4522,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; }; m_msaaTextureView = WGPU_CHECK(wgpuTextureCreateView(texture, &textureViewDesc) ); + wgpuRelease(texture); } return true; @@ -4645,6 +4694,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, @@ -4662,7 +4731,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); @@ -4890,17 +4961,23 @@ m_resolution.formatColor = TextureFormat::BGRA8; 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) ); } + #endif // BX_PLATFORM_EMSCRIPTEN } void CommandQueueWGPU::frame() diff --git a/src/renderer_webgpu.h b/src/renderer_webgpu.h index ece1d09bc..dabb0eff9 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); \