mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 11:24:19 +00:00
ifcviewer: move configureSurface into ViewportCore (#84-u)
The swapchain configuration path — WGPU_PRESENT_MODE handling, mode-preference order (Mailbox / Immediate / FifoRelaxed / Fifo), caps probe, cfg.alphaMode wiring, and the on-resize depth + MSAA + HiZ texture reallocation + bind-group invalidation — all move to ViewportCore. The only VW-side concern was a QString::fromLatin1 in the advertised-modes log, which becomes a std::string concat with the same output. ViewportWindow's render() / resizeEvent / surface-outdated retry paths call core_.configureSurface() now. createSurface() (which returns the platform-specific WGPUSurface from the host) stays VW because Qt platform discovery has to happen on the Qt side.
This commit is contained in:
@@ -4450,3 +4450,135 @@ bool ViewportCore::raycast(const float origin[3], const float dir[3],
|
||||
out.world_normal[2] = best_normal[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Surface configuration (#84-u): configureSurface
|
||||
// ===========================================================================
|
||||
|
||||
void ViewportCore::configureSurface(int width_px, int height_px) {
|
||||
WGPUSurfaceConfiguration cfg = {};
|
||||
cfg.device = device_;
|
||||
cfg.format = surface_format_;
|
||||
// CopySrc lets the screenshot path copy the surface texture back to
|
||||
// host memory. Trivial cost on all known backends.
|
||||
cfg.usage = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_CopySrc;
|
||||
cfg.width = std::uint32_t(width_px);
|
||||
cfg.height = std::uint32_t(height_px);
|
||||
|
||||
// Present mode preference order: Mailbox → Immediate → FifoRelaxed
|
||||
// → Fifo. Override with WGPU_PRESENT_MODE=...; otherwise pick the
|
||||
// first mode the surface actually advertises (asking for one that
|
||||
// isn't listed panics wgpu-native from Rust).
|
||||
//
|
||||
// Why Immediate sits above FifoRelaxed: Mailbox is the right answer
|
||||
// for an interactive viewer (vsync-aligned, no tearing, 1-frame
|
||||
// queue) but a meaningful subset of Linux Vulkan stacks (some
|
||||
// compositors, some driver/WSI combinations) silently don't expose
|
||||
// it. On those stacks Fifo's 2-3 frame queue doubles input-to-
|
||||
// photon latency; Immediate can tear but keeps latency at one
|
||||
// render-body. FifoRelaxed is the middle option.
|
||||
WGPUPresentMode preferred[4] = {
|
||||
WGPUPresentMode_Mailbox,
|
||||
WGPUPresentMode_Immediate,
|
||||
WGPUPresentMode_FifoRelaxed,
|
||||
WGPUPresentMode_Fifo,
|
||||
};
|
||||
const char* pm_name = "mailbox";
|
||||
if (const char* s = std::getenv("WGPU_PRESENT_MODE")) {
|
||||
WGPUPresentMode override_pm = WGPUPresentMode_Fifo;
|
||||
bool known = true;
|
||||
if (std::strcmp(s, "fifo") == 0) { override_pm = WGPUPresentMode_Fifo; pm_name = "fifo"; }
|
||||
else if (std::strcmp(s, "fifo_relaxed") == 0) { override_pm = WGPUPresentMode_FifoRelaxed; pm_name = "fifo_relaxed"; }
|
||||
else if (std::strcmp(s, "mailbox") == 0) { override_pm = WGPUPresentMode_Mailbox; pm_name = "mailbox"; }
|
||||
else if (std::strcmp(s, "immediate") == 0) { override_pm = WGPUPresentMode_Immediate; pm_name = "immediate"; }
|
||||
else {
|
||||
known = false;
|
||||
Log::warn()
|
||||
<< "[wgpu] unknown WGPU_PRESENT_MODE=" << s
|
||||
<< " (expected fifo|fifo_relaxed|mailbox|immediate);"
|
||||
" falling back to preference order";
|
||||
}
|
||||
if (known) {
|
||||
preferred[0] = override_pm;
|
||||
preferred[1] = WGPUPresentMode_Fifo; // Fifo is the only guaranteed-supported mode
|
||||
preferred[2] = preferred[3] = WGPUPresentMode_Fifo;
|
||||
}
|
||||
}
|
||||
|
||||
WGPUSurfaceCapabilities caps = {};
|
||||
wgpuSurfaceGetCapabilities(surface_, adapter_, &caps);
|
||||
auto supports = [&](WGPUPresentMode mode) {
|
||||
for (std::size_t i = 0; i < caps.presentModeCount; ++i) {
|
||||
if (caps.presentModes[i] == mode) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Diagnostic: dump the full advertised set on first configure. If
|
||||
// Mailbox is missing here the driver doesn't expose it (drives the
|
||||
// input-latency story); if Mailbox is listed but we still pick
|
||||
// Fifo, the preference order has a bug.
|
||||
if (!surface_configured_) {
|
||||
std::string advertised;
|
||||
for (std::size_t i = 0; i < caps.presentModeCount; ++i) {
|
||||
const char* name = "?";
|
||||
switch (caps.presentModes[i]) {
|
||||
case WGPUPresentMode_Fifo: name = "fifo"; break;
|
||||
case WGPUPresentMode_FifoRelaxed: name = "fifo_relaxed"; break;
|
||||
case WGPUPresentMode_Mailbox: name = "mailbox"; break;
|
||||
case WGPUPresentMode_Immediate: name = "immediate"; break;
|
||||
default: break;
|
||||
}
|
||||
if (i > 0) advertised += ", ";
|
||||
advertised += name;
|
||||
}
|
||||
Log::info() << "[wgpu] surface advertises present modes: " << advertised;
|
||||
}
|
||||
WGPUPresentMode pm = WGPUPresentMode_Fifo; // spec-guaranteed fallback
|
||||
for (WGPUPresentMode candidate : preferred) {
|
||||
if (supports(candidate)) { pm = candidate; break; }
|
||||
}
|
||||
switch (pm) {
|
||||
case WGPUPresentMode_Mailbox: pm_name = "mailbox"; break;
|
||||
case WGPUPresentMode_FifoRelaxed: pm_name = "fifo_relaxed"; break;
|
||||
case WGPUPresentMode_Immediate: pm_name = "immediate"; break;
|
||||
case WGPUPresentMode_Fifo: pm_name = "fifo"; break;
|
||||
default: break;
|
||||
}
|
||||
wgpuSurfaceCapabilitiesFreeMembers(caps);
|
||||
cfg.presentMode = pm;
|
||||
if (!surface_configured_) {
|
||||
const char* note = "";
|
||||
switch (pm) {
|
||||
case WGPUPresentMode_Mailbox:
|
||||
note = " (vsync-aligned, no queue lag -- default)"; break;
|
||||
case WGPUPresentMode_Fifo:
|
||||
note = " (strict vsync, may queue 2-3 frames)"; break;
|
||||
case WGPUPresentMode_FifoRelaxed:
|
||||
note = " (adaptive vsync -- sync if in budget, tear if not)"; break;
|
||||
case WGPUPresentMode_Immediate:
|
||||
note = " (vsync OFF -- framerate uncapped, may tear)"; break;
|
||||
default: break;
|
||||
}
|
||||
Log::info() << "[wgpu] present mode = " << pm_name << note;
|
||||
}
|
||||
cfg.alphaMode = WGPUCompositeAlphaMode_Auto;
|
||||
|
||||
wgpuSurfaceConfigure(surface_, &cfg);
|
||||
configured_w_ = width_px;
|
||||
configured_h_ = height_px;
|
||||
surface_configured_ = true;
|
||||
ensureDepthTexture(width_px, height_px);
|
||||
ensureMsaaColorTexture(width_px, height_px);
|
||||
ensureHizTextures(width_px, height_px);
|
||||
// depth_view_ was just replaced; force the HiZ + edge bind groups
|
||||
// to rebuild against the new view on next encode.
|
||||
if (hiz_bind_group_) {
|
||||
wgpuBindGroupRelease(hiz_bind_group_);
|
||||
hiz_bind_group_ = nullptr;
|
||||
}
|
||||
if (edge_bind_group_) {
|
||||
wgpuBindGroupRelease(edge_bind_group_);
|
||||
edge_bind_group_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user