From d4d0c934b14d312b47962808a80a3c709d7cd91f Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 2 Jun 2026 13:32:01 +1000 Subject: [PATCH] ifcviewer-wgpu: wire Windows HWND surface creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without a Windows branch in `WgpuViewportWindow::createSurface()` we were falling through to the `qWarning() << "wgpu surface creation not yet wired for this platform"` else clause on Windows runs, causing `init() -> createSurface()` to return false and the viewport to render nothing (the user sees the Qt window's background fill — a white viewport — and the log says "wgpu init failed; viewport will not render in DebugView"). Add a `#elif defined(Q_OS_WIN)` branch that fills a `WGPUSurfaceSourceWindowsHWND` chained-struct from `GetModuleHandleW(nullptr)` (HINSTANCE) and `winId()` (HWND, as a Win32 window handle on the Qt Windows platform plugin), then passes it as `surface_desc.nextInChain` to `wgpuInstanceCreateSurface`. `` is pulled in inside the gated block with NOMINMAX and WIN32_LEAN_AND_MEAN defined first so the preprocessor pollution (`min`, `max`, etc.) doesn't leak into Eigen / `std::min`,`std::max` elsewhere in the TU. Note on the unrelated DXC log line the user also sees: [wgpu err] DxcCreateInstance failed: No such interface supported (0x80004002) That is wgpu-native's DX12 backend probing for a modern `dxcompiler.dll`. `E_NOINTERFACE` means a *too-old* dxcompiler.dll was found on the system DLL search path (typical: a stale copy in System32 / Visual Studio install). wgpu-native then falls back to its Vulkan backend, so this log line is recoverable on its own — the fatal failure was the missing surface branch above. If we hit shader compilation issues after this lands, we can ship a known-good dxcompiler.dll + dxil.dll alongside wgpu_native.dll separately. Co-Authored-By: Claude Opus 4.7 --- src/ifcviewer-wgpu/WgpuViewportWindow.cpp | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/ifcviewer-wgpu/WgpuViewportWindow.cpp b/src/ifcviewer-wgpu/WgpuViewportWindow.cpp index 9ffe0689e4..5ee5ac7c97 100644 --- a/src/ifcviewer-wgpu/WgpuViewportWindow.cpp +++ b/src/ifcviewer-wgpu/WgpuViewportWindow.cpp @@ -1808,6 +1808,16 @@ bool WgpuViewportWindow::probeAndCreatePool() { # if __has_include() # include # endif +#elif defined(Q_OS_WIN) +// HINSTANCE for the surface descriptor. NOMINMAX + LEAN_AND_MEAN keep +// 's preprocessor pollution out of Eigen / std::min,max. +# ifndef NOMINMAX +# define NOMINMAX +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include #endif bool WgpuViewportWindow::createSurface() { @@ -1852,9 +1862,19 @@ bool WgpuViewportWindow::createSurface() { qWarning().noquote() << "Unsupported Qt platform for wgpu surface:" << platform; return false; } +#elif defined(Q_OS_WIN) + // wgpu-native maps WGPUSurfaceSourceWindowsHWND.hwnd to a Win32 HWND + // it never dereferences directly (it only hands the handle to D3D12 / + // Vulkan WSI). winId() is the HWND for top-level Qt windows on the + // Windows platform plugin, returned as WId (== quintptr). + WGPUSurfaceSourceWindowsHWND hwndsrc = {}; + hwndsrc.chain.sType = WGPUSType_SurfaceSourceWindowsHWND; + hwndsrc.hinstance = ::GetModuleHandleW(nullptr); + hwndsrc.hwnd = reinterpret_cast(static_cast(winId())); + surface_desc.nextInChain = &hwndsrc.chain; + surface_ = wgpuInstanceCreateSurface(instance_, &surface_desc); #else - // macOS / Windows native-handle wiring lands when those targets become - // active. Stage-1 development happens on Linux. + // macOS Metal surface wiring lands with task #32. qWarning() << "wgpu surface creation not yet wired for this platform"; return false; #endif