diff --git a/src/kiri/mode/sla/work/init-work.js b/src/kiri/mode/sla/work/init-work.js index 86eacd09..8a93e90c 100644 --- a/src/kiri/mode/sla/work/init-work.js +++ b/src/kiri/mode/sla/work/init-work.js @@ -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) { diff --git a/src/kiri/mode/sla/work/raster.js b/src/kiri/mode/sla/work/raster.js index 4b2e43ee..fc85afb5 100644 --- a/src/kiri/mode/sla/work/raster.js +++ b/src/kiri/mode/sla/work/raster.js @@ -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 -- 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 -- 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