mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-30 16:43:00 +00:00
06d87e21a7
Emscripten's generated WebGPU shim implements the dynamic-offset path of
wgpuRenderPassEncoderSetBindGroup as
pass.setBindGroup(index, group, HEAPU32, ptr >>> 2, count);
where HEAPU32 is the view over the entire wasm linear memory. Browsers
validate the byte length of that whole backing buffer, not the slice
actually read, and refuse anything over 2 GB. This build lets the heap
grow to 4 GB because large federations need it, so on a big enough
session (66 models) every dynamic-offset draw — the axis gizmo, section
gizmo and overlay lines, all drawn every frame — throws
TypeError: GPURenderPassEncoder.setBindGroup: Argument 3 can't be an
ArrayBuffer or an ArrayBufferView larger than 2 GB
on every frame for the life of the page.
ifcviewer::setBindGroupDynamic copies the handful of offsets into a
small Uint32Array on web (HEAPU32.slice, not subarray, which would alias
the heap again) and forwards straight through natively. The five
dynamic-offset call sites route through it. A Playwright spec spies on
setBindGroup and asserts the largest buffer it is ever handed is the
offsets themselves (4 bytes), where the shim previously passed the full
268 MB heap 35 times in three seconds of idle rendering.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
66 lines
2.9 KiB
C++
66 lines
2.9 KiB
C++
/********************************************************************************
|
|
* *
|
|
* This file is part of IfcOpenShell. *
|
|
* *
|
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the Lesser GNU General Public License as published by *
|
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* Lesser GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the Lesser GNU General Public License *
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
********************************************************************************/
|
|
|
|
#include "WgpuDynamicOffsets.h"
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
#include <emscripten/em_js.h>
|
|
#endif
|
|
|
|
namespace ifcviewer {
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
|
|
namespace {
|
|
EM_JS(void, ifcv_set_bind_group_dynamic_js,
|
|
(WGPURenderPassEncoder pass, uint32_t group_index, WGPUBindGroup group,
|
|
uint32_t offsets_ptr, uint32_t count), {
|
|
// HEAPU32.slice() copies into a freshly allocated buffer of exactly
|
|
// `count` elements; .subarray() would alias the whole heap again and
|
|
// reintroduce the bug this function exists to avoid.
|
|
var start = offsets_ptr >>> 2;
|
|
var small = HEAPU32.slice(start, start + count);
|
|
WebGPU.getJsObject(pass).setBindGroup(
|
|
group_index, WebGPU.getJsObject(group), small, 0, count);
|
|
});
|
|
} // namespace
|
|
|
|
void setBindGroupDynamic(WGPURenderPassEncoder pass, uint32_t group_index,
|
|
WGPUBindGroup group, uint32_t count,
|
|
const uint32_t* offsets) {
|
|
if (count == 0) {
|
|
wgpuRenderPassEncoderSetBindGroup(pass, group_index, group, 0, nullptr);
|
|
return;
|
|
}
|
|
ifcv_set_bind_group_dynamic_js(pass, group_index, group,
|
|
uint32_t(reinterpret_cast<uintptr_t>(offsets)), count);
|
|
}
|
|
|
|
#else
|
|
|
|
void setBindGroupDynamic(WGPURenderPassEncoder pass, uint32_t group_index,
|
|
WGPUBindGroup group, uint32_t count,
|
|
const uint32_t* offsets) {
|
|
wgpuRenderPassEncoderSetBindGroup(pass, group_index, group, count, offsets);
|
|
}
|
|
|
|
#endif
|
|
|
|
} // namespace ifcviewer
|