@cazala/party 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -2366,7 +2366,35 @@ fn grid_cell_index(pos: vec2<f32>) -> u32 { let col = i32(floor((pos.x - GRID_MI
|
|
|
2366
2366
|
fn grid_cell_index_from_rc(r: i32, c: i32) -> u32 { let rr = max(0, min(r, i32(GRID_ROWS()) - 1)); let cc = max(0, min(c, i32(GRID_COLS()) - 1)); return u32(rr) * GRID_COLS() + u32(cc); }
|
|
2367
2367
|
struct NeighborIter { cx: i32, cy: i32, r: i32, c: i32, k: u32, reach: i32, maxK: u32, base: u32, emitted: u32, maxEmit: u32 }
|
|
2368
2368
|
fn neighbor_iter_init(pos: vec2<f32>, radius: f32) -> NeighborIter { let cx = i32(floor((pos.x - GRID_MINX()) / GRID_CELL_SIZE())); let cy = i32(floor((pos.y - GRID_MINY()) / GRID_CELL_SIZE())); let reach = max(1, i32(ceil(radius / GRID_CELL_SIZE()))); var it: NeighborIter; it.cx = cx; it.cy = cy; it.reach = reach; it.r = cy - reach; it.c = cx - reach; let firstCell = grid_cell_index_from_rc(it.r, it.c); let cnt = atomicLoad(&GRID_COUNTS[firstCell]); it.maxK = min(cnt, GRID_MAX_PER_CELL()); it.base = firstCell * GRID_MAX_PER_CELL(); it.k = 0u; it.emitted = 0u; it.maxEmit = max(1u, SIM_MAX_NEIGHBORS()); return it; }
|
|
2369
|
-
fn neighbor_iter_next(it: ptr<function, NeighborIter>, selfIndex: u32) -> u32 {
|
|
2369
|
+
fn neighbor_iter_next(it: ptr<function, NeighborIter>, selfIndex: u32) -> u32 {
|
|
2370
|
+
// Naga (Firefox) sometimes fails to prove that a loop always returns, so
|
|
2371
|
+
// we structure this as break + return result to keep validation happy.
|
|
2372
|
+
var result: u32 = NEIGHBOR_NONE;
|
|
2373
|
+
loop {
|
|
2374
|
+
if ((*it).emitted >= (*it).maxEmit) { break; }
|
|
2375
|
+
if ((*it).r > (*it).cy + (*it).reach) { break; }
|
|
2376
|
+
if ((*it).k < (*it).maxK) {
|
|
2377
|
+
let id = GRID_INDICES[(*it).base + (*it).k];
|
|
2378
|
+
(*it).k = (*it).k + 1u;
|
|
2379
|
+
if (id != selfIndex) {
|
|
2380
|
+
(*it).emitted = (*it).emitted + 1u;
|
|
2381
|
+
result = id;
|
|
2382
|
+
break;
|
|
2383
|
+
} else {
|
|
2384
|
+
continue;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
(*it).c = (*it).c + 1;
|
|
2388
|
+
if ((*it).c > (*it).cx + (*it).reach) { (*it).c = (*it).cx - (*it).reach; (*it).r = (*it).r + 1; }
|
|
2389
|
+
if ((*it).r > (*it).cy + (*it).reach) { break; }
|
|
2390
|
+
let cell = grid_cell_index_from_rc((*it).r, (*it).c);
|
|
2391
|
+
let cnt = atomicLoad(&GRID_COUNTS[cell]);
|
|
2392
|
+
(*it).maxK = min(cnt, GRID_MAX_PER_CELL());
|
|
2393
|
+
(*it).base = cell * GRID_MAX_PER_CELL();
|
|
2394
|
+
(*it).k = 0u;
|
|
2395
|
+
}
|
|
2396
|
+
return result;
|
|
2397
|
+
}`);
|
|
2370
2398
|
// Optional: allow force modules to inject globals
|
|
2371
2399
|
const addGlobal = (module, descriptor) => {
|
|
2372
2400
|
if (module.role !== ModuleRole.Force)
|
|
@@ -3481,6 +3509,12 @@ class WebGPUEngine extends AbstractEngine {
|
|
|
3481
3509
|
writable: true,
|
|
3482
3510
|
value: null
|
|
3483
3511
|
});
|
|
3512
|
+
Object.defineProperty(this, "didSwapchainWarmup", {
|
|
3513
|
+
enumerable: true,
|
|
3514
|
+
configurable: true,
|
|
3515
|
+
writable: true,
|
|
3516
|
+
value: false
|
|
3517
|
+
});
|
|
3484
3518
|
Object.defineProperty(this, "animate", {
|
|
3485
3519
|
enumerable: true,
|
|
3486
3520
|
configurable: true,
|
|
@@ -3569,6 +3603,12 @@ class WebGPUEngine extends AbstractEngine {
|
|
|
3569
3603
|
this.resources.canvas.width = size.width;
|
|
3570
3604
|
this.resources.canvas.height = size.height;
|
|
3571
3605
|
this.render.ensureTargets(this.resources, size.width, size.height);
|
|
3606
|
+
// Safari/WebKit workaround:
|
|
3607
|
+
// On WebKit's WebGPU implementation, the first present can stay blank until the canvas
|
|
3608
|
+
// experiences a "real" resize (even 1px). Apps have been working around this by
|
|
3609
|
+
// jiggling size once after starting. We do it here, once, after the final canvas size
|
|
3610
|
+
// is set and before the first present.
|
|
3611
|
+
await this.warmupSwapchainIfNeeded(size.width, size.height);
|
|
3572
3612
|
// Configure grid storage + uniforms
|
|
3573
3613
|
this.grid.configure(this.view.getSnapshot(), this.resources, program);
|
|
3574
3614
|
// Seed module uniforms on GPU
|
|
@@ -3660,6 +3700,50 @@ class WebGPUEngine extends AbstractEngine {
|
|
|
3660
3700
|
});
|
|
3661
3701
|
});
|
|
3662
3702
|
}
|
|
3703
|
+
isWebKitWebGPU() {
|
|
3704
|
+
// We specifically want WebKit's WebGPU, not Chromium/Blink.
|
|
3705
|
+
// - On iOS, *all* browsers use WebKit, so we treat them as WebKit.
|
|
3706
|
+
// - On macOS, Safari is WebKit; Chrome/Edge/Opera are not (even though their UA includes "AppleWebKit").
|
|
3707
|
+
try {
|
|
3708
|
+
if (typeof navigator === "undefined")
|
|
3709
|
+
return false;
|
|
3710
|
+
const ua = navigator.userAgent || "";
|
|
3711
|
+
const isIOS = /iPad|iPhone|iPod/.test(ua);
|
|
3712
|
+
if (isIOS)
|
|
3713
|
+
return true;
|
|
3714
|
+
const isAppleWebKit = /AppleWebKit\//.test(ua);
|
|
3715
|
+
const isSafari = /Safari\//.test(ua);
|
|
3716
|
+
const isChromiumLike = /(Chrome|Chromium|Edg|OPR)\//.test(ua);
|
|
3717
|
+
return isAppleWebKit && isSafari && !isChromiumLike;
|
|
3718
|
+
}
|
|
3719
|
+
catch {
|
|
3720
|
+
return false;
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
async warmupSwapchainIfNeeded(width, height) {
|
|
3724
|
+
if (this.didSwapchainWarmup)
|
|
3725
|
+
return;
|
|
3726
|
+
if (!this.isWebKitWebGPU())
|
|
3727
|
+
return;
|
|
3728
|
+
if (height <= 1)
|
|
3729
|
+
return;
|
|
3730
|
+
this.didSwapchainWarmup = true;
|
|
3731
|
+
// 1px "resize" to force WebKit to fully bind the swapchain/currentTexture.
|
|
3732
|
+
// We wait a couple of animation frames to match real-world workarounds that proved reliable.
|
|
3733
|
+
try {
|
|
3734
|
+
this.resources.canvas.width = width;
|
|
3735
|
+
this.resources.canvas.height = height - 1;
|
|
3736
|
+
await this.waitForNextTick();
|
|
3737
|
+
this.resources.canvas.width = width;
|
|
3738
|
+
this.resources.canvas.height = height;
|
|
3739
|
+
await this.waitForNextTick();
|
|
3740
|
+
// Re-ensure targets (idempotent) in case any implementation ties resources to canvas size.
|
|
3741
|
+
this.render.ensureTargets(this.resources, width, height);
|
|
3742
|
+
}
|
|
3743
|
+
catch {
|
|
3744
|
+
// If anything goes wrong, fail open: rendering may still work on other browsers.
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3663
3747
|
// Override export to use module registry
|
|
3664
3748
|
export() {
|
|
3665
3749
|
const settings = {};
|