From d1f8247a25d7e71bcad1e64b90bb93f7ea1fbb95 Mon Sep 17 00:00:00 2001 From: Igor Zinken Date: Fri, 7 Jan 2022 09:14:19 +0100 Subject: [PATCH] Fixed issue where certain configurations could not transfer data from WASM memory, updated filter job error handling --- src/services/render-service.js | 24 ++++++++++++++++-------- src/utils/wasm-util.js | 8 ++++---- src/workers/filter.worker.js | 18 +++++++++++++----- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/services/render-service.js b/src/services/render-service.js index 83f4cb2..9dca6d8 100644 --- a/src/services/render-service.js +++ b/src/services/render-service.js @@ -1,7 +1,7 @@ /** * The MIT License (MIT) * - * Igor Zinken 2020-2021 - https://www.igorski.nl + * Igor Zinken 2020-2022 - https://www.igorski.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -106,10 +106,17 @@ export const renderEffectsForLayer = async ( layer, useCaching = true ) => { //console.info( "reading filtered content from cache" ); imageData = cached.filterData; } else { - imageData = await runFilterJob( cvs, { filters: layer.filters }); - //console.info( "writing filtered content to cache" ); - cacheToSet.filters = { ...layer.filters }; - cacheToSet.filterData = imageData; + try { + imageData = await runFilterJob( cvs, { filters: layer.filters }); + //console.info( "writing filtered content to cache" ); + cacheToSet.filters = { ...layer.filters }; + cacheToSet.filterData = imageData; + } catch ( error ) { + // TODO: communicate error ? + console.info( `Caught error "${error}" during runFilterJob()` ); + renderState.pending = Math.max( 0, renderState.pending - 1 ); + return; + } } ctx.clearRect( 0, 0, width, height ); ctx.putImageData( imageData, 0, 0 ); @@ -169,9 +176,10 @@ const runFilterJob = ( source, jobSettings ) => { onComplete?.(); resolve( imageData ); }, - error: () => { + error: optError => { + // TODO: when wasm, disable wasm mode and return to JS worker ? onComplete?.(); - reject(); + reject( optError ); } }); worker.postMessage({ cmd: wasm ? "filterWasm" : "filter", id, imageData, ...jobSettings }); @@ -184,7 +192,7 @@ function handleWorkerMessage({ data }) { jobQueueObj?.success( data ); } if ( data?.cmd === "error" ) { - jobQueueObj?.error( file, data?.error ); + jobQueueObj?.error( data?.error ); } }; diff --git a/src/utils/wasm-util.js b/src/utils/wasm-util.js index 984dd59..43e9ac3 100644 --- a/src/utils/wasm-util.js +++ b/src/utils/wasm-util.js @@ -43,12 +43,12 @@ export const imageDataAsFloat = ( imageData, wasmInstance, fn ) => { // run WASM operations on float32 data fn( memory, length ); - // retrieve operation result to be returned to JS and free WASM memory - const processedImageData = wasmInstance.HEAPF32.subarray( + // retrieve operation result to be returned to JS + const processedImageData = new Uint8ClampedArray( wasmInstance.HEAPF32.subarray( memory / sizeofFloat, memory / sizeofFloat + length - ); - wasmInstance._free( memory ); + )); + wasmInstance._free( memory ); // ...and free WASM memory return processedImageData; }; diff --git a/src/workers/filter.worker.js b/src/workers/filter.worker.js index 4501bad..3a28228 100644 --- a/src/workers/filter.worker.js +++ b/src/workers/filter.worker.js @@ -1,7 +1,7 @@ /** * The MIT License (MIT) * - * Igor Zinken 2021 - https://www.igorski.nl + * Igor Zinken 2021-2022 - https://www.igorski.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -56,13 +56,21 @@ self.addEventListener( "message", async ({ data }) => { // which can be set as onto an ImageData in the main application case "filterWasm": - pixelData = renderFiltersWasm( data.imageData, data.filters ); - self.postMessage({ cmd: "complete", id, pixelData }); + try { + pixelData = renderFiltersWasm( data.imageData, data.filters ); + self.postMessage({ cmd: "complete", id, pixelData }, [ pixelData.buffer ]); + } catch ( error ) { + self.postMessage({ cmd: "error", id, error }); + } break; case "filter": - pixelData = renderFilters( data.imageData, data.filters ); - self.postMessage({ cmd: "complete", id, pixelData }); + try { + pixelData = renderFilters( data.imageData, data.filters ); + self.postMessage({ cmd: "complete", id, pixelData }); + } catch ( error ) { + self.postMessage({ cmd: "error", id, error }); + } break; } }, false );