wgpu backend: --camera flag + request adapter's max buffer limits

Two pieces that block proper side-by-side parity with the GL minimal:

1. --camera tx,ty,tz,dist,yaw,pitch. Same format string as the GL
   minimal so a pasted camera arg lands the same view on both backends.
   setCamera() also flips initial_view_applied_ = true so the auto-
   viewAll-on-first-load doesn't snap away from the script-set position
   when the model finishes uploading.

2. Real BIM models exceed the conservative WebGPU defaults at device
   create time. A 114k-instance / 19M-index sidecar's vertex storage is
   139 MB, which trips wgpu's default 128 MB max_storage_buffer_binding_
   size and bind-group creation fails. Now wgpuAdapterGetLimits is
   called first and the device is requested at the adapter's full
   ceiling — every desktop driver supports multi-GB.

   Trade-off worth flagging: web parity will fail here because browsers
   cap at the defaults. The eventual fix is to split a model's vertex/
   instance storage into ≤128 MB chunks with a small per-frame routing
   table, which is a real chunk of work. For now this unblocks all the
   native benchmarking the user is actually doing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-05-27 14:58:18 +10:00
parent f9a9273ecc
commit 7893135790
3 changed files with 55 additions and 2 deletions
+20
View File
@@ -45,6 +45,9 @@ int main(int argc, char* argv[]) {
"Render one frame, save to PATH as PNG, exit.", "path"});
parser.addOption({{"b", "benchmark"},
"Render N frames (yaw-sweeping the camera), print stats, exit.", "frames"});
parser.addOption({{"c", "camera"},
"Set camera as tx,ty,tz,dist,yaw,pitch (same format as IfcViewerMinimal).",
"params"});
parser.process(app);
auto* viewport = new WgpuViewportWindow;
@@ -65,6 +68,23 @@ int main(int argc, char* argv[]) {
viewport->queueLoadSidecar(path);
}
if (parser.isSet("camera")) {
const QStringList parts = parser.value("camera").split(',');
if (parts.size() == 6) {
bool ok = true;
float v[6];
for (int i = 0; i < 6 && ok; ++i) v[i] = parts[i].toFloat(&ok);
if (ok) {
viewport->setCamera(v[0], v[1], v[2], v[3], v[4], v[5]);
} else {
qWarning() << "--camera: failed to parse" << parser.value("camera");
}
} else {
qWarning() << "--camera: expected 6 comma-separated floats, got"
<< parts.size();
}
}
if (parser.isSet("screenshot")) {
viewport->captureNextFrameToPng(parser.value("screenshot"),
/*quit_after=*/true);