Advance M8-M11 parity workflows
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-17 04:37:07 -04:00
parent 7c16b279ae
commit 0fe8d2bb56
324 changed files with 31920 additions and 863 deletions

View File

@@ -2,6 +2,10 @@ import type { NanoVDBFloat32TreeLayoutIR, NanoVDBGridIR } from "../../../protoco
export interface NanoVDBSampleIR { value: number; active: boolean }
type NanoVDBNearestLocation =
| { sample: NanoVDBSampleIR }
| { leaf: number; voxel: number };
export class NanoVDBFloat32Sampler {
private readonly view: DataView;
private readonly layout: NanoVDBFloat32TreeLayoutIR;
@@ -24,6 +28,20 @@ export class NanoVDBFloat32Sampler {
}
nearest(coord: readonly [number, number, number]): NanoVDBSampleIR {
const location = this.nearestLocation(coord);
if ("sample" in location) return location.sample;
return {
value: this.f32(location.leaf + this.layout.leafValuesOffset + location.voxel * 4),
active: this.mask(location.leaf + this.layout.leafValueMaskOffset, location.voxel),
};
}
leafByteOffset(coord: readonly [number, number, number]): number | null {
const location = this.nearestLocation(coord);
return "leaf" in location ? location.leaf : null;
}
private nearestLocation(coord: readonly [number, number, number]): NanoVDBNearestLocation {
if (coord.some((value) => !Number.isSafeInteger(value) || value < -0x8000_0000 || value > 0x7fff_ffff)) throw new Error("NANOVDB_MANIFEST_INVALID: sample coordinate is outside int32");
const tableSize = this.u32(this.root + this.layout.rootTableSizeOffset);
const key = this.rootKey(coord);
@@ -39,20 +57,20 @@ export class NanoVDBFloat32Sampler {
if (candidate > key) low = middle + 1;
else high = middle - 1;
}
if (tile < 0) return { value: this.view.getFloat32(this.root + 28, true), active: false };
if (tile < 0) return { sample: { value: this.view.getFloat32(this.root + 28, true), active: false } };
const child = this.i64(tile + this.layout.rootTileChildOffset);
if (child === 0n) return { value: this.f32(tile + this.layout.rootTileValueOffset), active: this.u32(tile + this.layout.rootTileStateOffset) !== 0 };
if (child === 0n) return { sample: { value: this.f32(tile + this.layout.rootTileValueOffset), active: this.u32(tile + this.layout.rootTileStateOffset) !== 0 } };
const upper = this.child(this.root, child, this.layout.upperNodeBytes);
const upperOffset = (((coord[0] >>> 0 & 4095) >>> 7) << 10) | (((coord[1] >>> 0 & 4095) >>> 7) << 5) | ((coord[2] >>> 0 & 4095) >>> 7);
const upperSample = this.internal(upper, upperOffset, this.layout.upperValueMaskOffset, this.layout.upperChildMaskOffset, this.layout.upperTableOffset, this.layout.lowerNodeBytes);
if ("sample" in upperSample) return upperSample.sample;
if ("sample" in upperSample) return upperSample;
const lower = upperSample.child;
const lowerOffset = (((coord[0] >>> 0 & 127) >>> 3) << 8) | (((coord[1] >>> 0 & 127) >>> 3) << 4) | ((coord[2] >>> 0 & 127) >>> 3);
const lowerSample = this.internal(lower, lowerOffset, this.layout.lowerValueMaskOffset, this.layout.lowerChildMaskOffset, this.layout.lowerTableOffset, this.layout.leafNodeBytes);
if ("sample" in lowerSample) return lowerSample.sample;
if ("sample" in lowerSample) return lowerSample;
const leaf = lowerSample.child;
const voxel = ((coord[0] >>> 0 & 7) << 6) | ((coord[1] >>> 0 & 7) << 3) | (coord[2] >>> 0 & 7);
return { value: this.f32(leaf + this.layout.leafValuesOffset + voxel * 4), active: this.mask(leaf + this.layout.leafValueMaskOffset, voxel) };
return { leaf, voxel };
}
linear(coord: readonly [number, number, number]): NanoVDBSampleIR {

View File

@@ -7,6 +7,16 @@ import {
type NanoVDBRangeIR,
} from "../../../protocol/volume-vdb";
import {
dispatchNanoVDBPageFeedbackBatch,
type NanoVDBPageFeedbackBatch,
type NanoVDBPageFeedbackDispatchResult,
} from "../../../protocol/nanovdb-page-feedback";
import {
planNanoVDBDeviceLossReplay,
type NanoVDBDeviceLossReplayPlanIR,
} from "../../../protocol/nanovdb-device-recovery";
import {
createNanoVDBFloat32GridPaged,
NanoVDBWebGPUDeviceSession,
probeNanoVDBWebGPU,
renderNanoVDBFloat32WebGPU,
@@ -267,6 +277,177 @@ export async function loadNanoVDBGridPage(
return output.buffer;
}
export interface NanoVDBFeedbackPageIR {
pageId: number;
renderRevision: number;
data: ArrayBuffer;
}
export interface NanoVDBDeviceLossGridReplayIR {
grid: NanoVDBWebGPUGrid;
plan: NanoVDBDeviceLossReplayPlanIR;
residentBeforeReplay: readonly number[];
}
export async function rebuildNanoVDBGridAfterDeviceLoss(
device: GPUDevice,
manifestValue: NanoVDBBundleManifestIR,
gridName: string,
source: NanoVDBRangeSource,
visiblePageIds: readonly number[],
signal: AbortSignal,
): Promise<NanoVDBDeviceLossGridReplayIR> {
const manifest = validateNanoVDBBundleManifest(manifestValue);
const gridDefinition = manifest.grids.find((candidate) => candidate.name === gridName);
if (!gridDefinition) throw new Error(`NANOVDB_MANIFEST_INVALID: grid ${gridName} is missing`);
const rebuilt = createNanoVDBFloat32GridPaged(
device,
gridDefinition.byteLength,
manifest.gpu.pageByteLength,
manifest.gpu.maxResidentBytes,
);
const residentBeforeReplay = [...rebuilt.residentVirtualPages];
const plan = planNanoVDBDeviceLossReplay(visiblePageIds, rebuilt.pageCount, rebuilt.residentPageCapacity);
try {
for (const pageId of plan.replayedPageIds) {
if (signal.aborted) throw new DOMException("NanoVDB device-loss replay cancelled", "AbortError");
const data = await loadNanoVDBGridPage(manifest, gridName, pageId, source, signal);
rebuilt.uploadPage(pageId, data);
}
return { grid: rebuilt, plan, residentBeforeReplay };
}
catch (error) {
rebuilt.dispose();
throw error;
}
}
interface NanoVDBPageRequestSubscriber {
signal: AbortSignal;
onAbort: () => void;
resolve: (data: ArrayBuffer) => void;
reject: (error: unknown) => void;
}
interface NanoVDBPendingPageRequest {
controller: AbortController;
subscribers: Map<symbol, NanoVDBPageRequestSubscriber>;
}
export interface NanoVDBPageRequestCoordinatorStatsIR {
pendingPages: number;
subscribers: number;
pageIds: number[];
}
function pageRequestCancelled(): DOMException {
return new DOMException("NanoVDB page request cancelled", "AbortError");
}
export class NanoVDBGridPageRequestCoordinator {
private readonly manifest: NanoVDBBundleManifestIR;
private readonly pending = new Map<number, NanoVDBPendingPageRequest>();
private disposed = false;
constructor(
manifestValue: NanoVDBBundleManifestIR,
private readonly gridName: string,
private readonly source: NanoVDBRangeSource,
) {
this.manifest = validateNanoVDBBundleManifest(manifestValue);
if (!this.manifest.grids.some((grid) => grid.name === gridName)) {
throw new Error(`NANOVDB_MANIFEST_INVALID: grid ${gridName} is missing`);
}
}
request(pageId: number, signal: AbortSignal): Promise<ArrayBuffer> {
if (this.disposed || signal.aborted) return Promise.reject(pageRequestCancelled());
let request = this.pending.get(pageId);
if (!request) {
request = { controller: new AbortController(), subscribers: new Map() };
this.pending.set(pageId, request);
const current = request;
void loadNanoVDBGridPage(this.manifest, this.gridName, pageId, this.source, current.controller.signal).then(
(data) => this.resolve(pageId, current, data),
(error) => this.reject(pageId, current, error),
);
}
const current = request;
return new Promise<ArrayBuffer>((resolve, reject) => {
const token = Symbol("NanoVDB page subscriber");
const onAbort = (): void => {
const subscriber = current.subscribers.get(token);
if (!subscriber) return;
current.subscribers.delete(token);
signal.removeEventListener("abort", onAbort);
reject(pageRequestCancelled());
if (current.subscribers.size === 0) {
if (this.pending.get(pageId) === current) this.pending.delete(pageId);
current.controller.abort();
}
};
current.subscribers.set(token, { signal, onAbort, resolve, reject });
signal.addEventListener("abort", onAbort, { once: true });
if (signal.aborted) onAbort();
});
}
stats(): NanoVDBPageRequestCoordinatorStatsIR {
return {
pendingPages: this.pending.size,
subscribers: [...this.pending.values()].reduce((total, request) => total + request.subscribers.size, 0),
pageIds: [...this.pending.keys()].sort((left, right) => left - right),
};
}
dispose(): void {
if (this.disposed) return;
this.disposed = true;
for (const [pageId, request] of this.pending) {
this.pending.delete(pageId);
request.controller.abort();
for (const subscriber of request.subscribers.values()) {
subscriber.signal.removeEventListener("abort", subscriber.onAbort);
subscriber.reject(pageRequestCancelled());
}
request.subscribers.clear();
}
}
private resolve(pageId: number, request: NanoVDBPendingPageRequest, data: ArrayBuffer): void {
if (this.pending.get(pageId) === request) this.pending.delete(pageId);
for (const subscriber of request.subscribers.values()) {
subscriber.signal.removeEventListener("abort", subscriber.onAbort);
subscriber.resolve(data.slice(0));
}
request.subscribers.clear();
}
private reject(pageId: number, request: NanoVDBPendingPageRequest, error: unknown): void {
if (this.pending.get(pageId) === request) this.pending.delete(pageId);
for (const subscriber of request.subscribers.values()) {
subscriber.signal.removeEventListener("abort", subscriber.onAbort);
subscriber.reject(error);
}
request.subscribers.clear();
}
}
export async function loadNanoVDBFeedbackPages(
batch: NanoVDBPageFeedbackBatch,
currentRenderRevision: number,
requests: NanoVDBGridPageRequestCoordinator,
signal: AbortSignal,
consume: (page: NanoVDBFeedbackPageIR) => Promise<void> | void,
): Promise<NanoVDBPageFeedbackDispatchResult> {
return dispatchNanoVDBPageFeedbackBatch(batch, currentRenderRevision, async (pageId, renderRevision) => {
if (signal.aborted) throw new DOMException("NanoVDB feedback page load cancelled", "AbortError");
const data = await requests.request(pageId, signal);
if (signal.aborted) throw new DOMException("NanoVDB feedback page load cancelled", "AbortError");
await consume({ pageId, renderRevision, data });
});
}
export function validateNanoVDBViewportAsset(value: NanoVDBViewportAssetIR): NanoVDBViewportAssetIR {
if (!value.dataId || value.dataId.length > 256) throw new Error("NANOVDB_MANIFEST_INVALID: viewport dataId");
const manifest = validateNanoVDBBundleManifest(value.manifest);