wasm grow and fallback for sla

This commit is contained in:
Stewart Allen 2026-05-16 12:32:06 -04:00
commit 806c4fb70b
5 changed files with 71 additions and 7 deletions

View file

@ -20,6 +20,27 @@ function init(worker) {
// console.log({ INIT_SLA: worker });
}
export function ensureSLAMemory(required) {
let wasm = SLA.wasm;
let available = wasm.memory.buffer.byteLength;
if (available >= required) {
return;
}
let page = 65536;
let pages = Math.ceil((required - available) / page);
try {
wasm.memory.grow(pages);
} catch (error) {
let growError = new Error(`SLA WASM memory grow failed: need ${required} bytes, have ${available} bytes`);
growError.code = "SLA_WASM_MEMORY";
growError.cause = error;
throw growError;
}
wasm.heap = new Uint8Array(wasm.memory.buffer);
}
// runs in worker. would usually be in src/mode/sla/prepare.js
// but the SLA driver skips the prepare step because there is no path routing
async function sla_prepare(widgets, settings, update) {

View file

@ -30,9 +30,10 @@ export function renderRasterLayers(print, renderer, onlayer, progress) {
let { process, widgets, width, height, scaleX, scaleY, layermax } = ctx;
let volume = 0;
let count = 0;
let useWasm = renderer.renderLayerWasm !== undefined;
for (let index=0; index<layermax; index++) {
let rendered = renderer.renderLayerWasm({
let params = {
index,
width,
height,
@ -40,7 +41,22 @@ export function renderRasterLayers(print, renderer, onlayer, progress) {
scaleX,
scaleY,
masks: []
});
};
let rendered;
if (useWasm) {
try {
rendered = renderer.renderLayerWasm(params);
} catch (error) {
if (error.code !== "SLA_WASM_MEMORY" || !renderer.renderLayer) {
throw error;
}
useWasm = false;
}
}
if (!useWasm) {
rendered = renderer.renderLayer(params);
}
if (rendered.end) break;
volume += rendered.area * process.slaSlice;

View file

@ -1,6 +1,6 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { SLA } from './init-work.js';
import { SLA, ensureSLAMemory } from './init-work.js';
const default_values = {
magic1: 'CXSW3DV2',
@ -394,8 +394,11 @@ CXDLP.render = function(params) {
}
});
let wasm = SLA.wasm;
let imagelen = width * height;
let metadata = 6 + array.reduce((total, poly) => total + polyRecordBytes(poly), 0);
ensureSLAMemory(imagelen + metadata + 1024);
let wasm = SLA.wasm;
let writer = new self.DataWriter(new DataView(wasm.memory.buffer), imagelen);
writer.writeU16(width, true);
writer.writeU16(height, true);
@ -431,3 +434,13 @@ CXDLP.render = function(params) {
}
return { lines, area };
}
function polyRecordBytes(poly) {
let bytes = 14 + poly.points.length * 8;
if (poly.inner) {
for (let i=0, il=poly.inner.length; i<il; i++) {
bytes += polyRecordBytes(poly.inner[i]);
}
}
return bytes;
}

View file

@ -1,6 +1,6 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { SLA } from './init-work.js';
import { SLA, ensureSLAMemory } from './init-work.js';
function generatePhoton(print, conf, progress) {
let printset = print.settings,
@ -445,8 +445,12 @@ function renderLayerWasm(params) {
}
});
let wasm = SLA.wasm;
let imagelen = width * height;
let metadata = 6 + array.reduce((total, poly) => total + polyRecordBytes(poly), 0);
let rleSpace = masks.length ? imagelen : 0;
ensureSLAMemory(imagelen + Math.max(metadata, rleSpace) + 1024);
let wasm = SLA.wasm;
let writer = new self.DataWriter(new DataView(wasm.memory.buffer), imagelen);
writer.writeU16(width, true);
writer.writeU16(height, true);
@ -471,6 +475,16 @@ function renderLayerWasm(params) {
return { image, layers, end: count === 0, area };
}
function polyRecordBytes(poly) {
let bytes = 14 + poly.points.length * 8;
if (poly.inner) {
for (let i=0, il=poly.inner.length; i<il; i++) {
bytes += polyRecordBytes(poly.inner[i]);
}
}
return bytes;
}
// legacy JS-only rasterizer uses OffscreenCanvas
function renderLayer(params) {
let {width, height, index, widgets, scaleX, scaleY} = params;

View file

@ -1,7 +1,7 @@
all: kiri-sla.wasm kiri-geo.wasm kiri-ani.wasm
kiri-sla.wasm: kiri-sla.c
emcc --no-entry -o kiri-sla.wasm kiri-sla.c -O3 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s TOTAL_MEMORY=40mb
emcc --no-entry -o kiri-sla.wasm kiri-sla.c -O3 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s INITIAL_MEMORY=64mb -s ALLOW_MEMORY_GROWTH=1
kiri-geo.wasm: kiri-geo.cpp
emcc --no-entry -o kiri-geo.wasm clipper.cpp kiri-geo.cpp -Oz -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s TOTAL_MEMORY=40mb