From a9e6666da60be88fdff14422f1def46f1badd769 Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Sun, 22 Jul 2018 08:42:22 +0100 Subject: [PATCH] updated AssemblyScript to latest version --- app.js | 2 +- assemblyscript/mandelbrot-asc.js | 39 +++++++++++++++++--------- assemblyscript/mandelbrot-tsc.js | 24 ++++++++++------ assemblyscript/mandelbrot.js | 46 +++++++++++++++++-------------- assemblyscript/mandelbrot.ts | 45 ++++++++++++++++++------------ assemblyscript/mandelbrot.wasm | Bin 9556 -> 1408 bytes assemblyscript/package.json | 10 ++++--- assemblyscript/tsconfig.json | 5 ++-- 8 files changed, 104 insertions(+), 67 deletions(-) diff --git a/app.js b/app.js index 8cacfee..f53cece 100644 --- a/app.js +++ b/app.js @@ -38,7 +38,7 @@ const bootstrap = async() => { await require('js/mandelbrot.js')(), await require('emscripten/mandelbrot.js')(), await require('assemblyscript/mandelbrot-asc.js')(), - await require('assemblyscript/mandelbrot-tsc.js')(), + // await require('assemblyscript/mandelbrot-tsc.js')(), await require('asmjs/mandelbrot.js')(), ]; diff --git a/assemblyscript/mandelbrot-asc.js b/assemblyscript/mandelbrot-asc.js index 75d4b14..4834c02 100644 --- a/assemblyscript/mandelbrot-asc.js +++ b/assemblyscript/mandelbrot-asc.js @@ -1,27 +1,40 @@ -module.exports = async() => { +module.exports = async () => { - const WIDTH = 1200, HEIGHT = 800; + const WIDTH = 1200; + const HEIGHT = 800; + const PAGE_SIZE = 65536; + + function allocateMemory() { + const initial = Math.floor(WIDTH * HEIGHT * 4 / PAGE_SIZE) + 1; + return new WebAssembly.Memory({ initial }); + } + + const imports = { + env: { + memoryBase: 0, + memory: allocateMemory() + } + }; const res = await fetch('assemblyscript/mandelbrot.wasm'); const buffer = await res.arrayBuffer(); - const instance = await WebAssembly.instantiate(buffer, {}); - - + const module = await WebAssembly.instantiate(buffer, imports); + const { mandelbrot, getDataBuffer, memory } = module.instance.exports; + let imgData = null; return { - render: (ctx, config) => { - console.log(instance.instance.exports.structured()); - instance.instance.exports.mandelbrot(config.iterations, config.x, config.y, config.d); + render: (ctx, { iterations, x, y, d }) => { + mandelbrot(iterations, x, y, d); - const imgData = ctx.createImageData(WIDTH, HEIGHT); - const offset = instance.instance.exports.getData(); - const linearMemory = new Uint8Array(instance.instance.exports.memory.buffer, offset, WIDTH * HEIGHT * 4); - for (let i = 0; i < linearMemory.length; i++) { + if (!imgData) imgData = ctx.createImageData(WIDTH, HEIGHT); + const offset = getDataBuffer(); + const linearMemory = new Uint8Array(memory.buffer, offset, WIDTH * HEIGHT * 4); + for (let i = 0, len = linearMemory.length; i < len; i++) { imgData.data[i] = linearMemory[i]; } ctx.putImageData(imgData, 0, 0); }, name: 'AssemblyScript', description: 'This implementation uses the AssemblyScript compiler to compile a TypeScript mandelbrot to WebAssembly.' - } + }; }; diff --git a/assemblyscript/mandelbrot-tsc.js b/assemblyscript/mandelbrot-tsc.js index 7f49f55..8d55ac7 100644 --- a/assemblyscript/mandelbrot-tsc.js +++ b/assemblyscript/mandelbrot-tsc.js @@ -1,18 +1,24 @@ const typeScriptMandelbrot = require('./mandelbrot.js'); +const WIDTH = 1200; +const HEIGHT = 800; + +var imgData = null; + +const { getData, mandelbrot } = typeScriptMandelbrot; + module.exports = () => Promise.resolve({ - render: (ctx, config) => { - const WIDTH = 1200, HEIGHT = 800; - - typeScriptMandelbrot.mandelbrot(config.iterations, config.x, config.y, config.d); - - const imgData = ctx.createImageData(WIDTH, HEIGHT); - const linearMemory = typeScriptMandelbrot.getData(); - for (let i = 0; i < linearMemory.length; i++) { + render: (ctx, { iterations, x, y, d }) => { + mandelbrot(iterations, x, y, d); + + if (!imgData) imgData = ctx.createImageData(WIDTH, HEIGHT); + const linearMemory = getData(); + + for (let i = 0, len = linearMemory.length; i < len; i++) { imgData.data[i] = linearMemory[i]; } ctx.putImageData(imgData, 0, 0); }, name: 'TypeScript', description: 'This implementation takes the TypeScript that is used by AssemblyScript to generate WebAssembly, but instead passes it through the TypeScript compiler to create JavaScript.' -}); \ No newline at end of file +}); diff --git a/assemblyscript/mandelbrot.js b/assemblyscript/mandelbrot.js index 66dd218..c9aabeb 100644 --- a/assemblyscript/mandelbrot.js +++ b/assemblyscript/mandelbrot.js @@ -1,23 +1,22 @@ define(["require", "exports"], function (require, exports) { "use strict"; - exports.__esModule = true; - var WIDTH = 1200, HEIGHT = 800; - var data = new Uint8Array(1200 * 800 * 4); + Object.defineProperty(exports, "__esModule", { value: true }); + const WIDTH = 1200; + const HEIGHT = 800; + var data = new Uint8Array(WIDTH * HEIGHT * 4); function colour(iteration, offset, scale) { - iteration = ((iteration * scale) + offset) % 1024; + iteration = (iteration * scale + offset) & 1023; if (iteration < 256) { return iteration; } else if (iteration < 512) { - return 255 - (iteration - 255); - } - else { - return 0; + return (255 - (iteration - 255)); } + return 0; } function iterateEquation(x0, y0, maxiterations) { - var a = 0, b = 0, rx = 0, ry = 0; - var iterations = 0; + let a = 0.0, b = 0.0, rx = 0.0, ry = 0.0; + let iterations = 0; while (iterations < maxiterations && (rx * rx + ry * ry <= 4)) { rx = a * a - b * b + x0; ry = 2 * a * b + y0; @@ -27,19 +26,22 @@ define(["require", "exports"], function (require, exports) { } return iterations; } - function scale(domainStart, domainLength, screenLength, step) { - return domainStart + domainLength * ((step - screenLength) / screenLength); + // @inline + function scale(domainStart, domainLength, invScreenLength, step) { + return domainStart + domainLength * (step * invScreenLength - 1.0); } function mandelbrot(maxIterations, cx, cy, diameter) { - var verticalDiameter = diameter * HEIGHT / WIDTH; - for (var x = 0; x < WIDTH; x++) { - for (var y = 0; y < HEIGHT; y++) { + const invWidth = 1.0 / WIDTH; + const invHeight = 1.0 / HEIGHT; + var verticalDiameter = diameter * HEIGHT * invWidth; + for (let x = 0; x < WIDTH; ++x) { + for (let y = 0; y < HEIGHT; ++y) { // convert from screen coordinates to mandelbrot coordinates - var rx = scale(cx, diameter, WIDTH, x); - var ry = scale(cy, verticalDiameter, HEIGHT, y); - var iterations = iterateEquation(rx, ry, maxIterations); - var idx = ((x + y * WIDTH) * 4); - data[idx] = iterations == maxIterations ? 0 : colour(iterations, 0, 4); + let rx = scale(cx, diameter, invWidth, x); + let ry = scale(cy, verticalDiameter, invHeight, y); + let iterations = iterateEquation(rx, ry, maxIterations); + let idx = (x + y * WIDTH) << 2; + data[idx + 0] = iterations == maxIterations ? 0 : colour(iterations, 0, 4); data[idx + 1] = iterations == maxIterations ? 0 : colour(iterations, 128, 4); data[idx + 2] = iterations == maxIterations ? 0 : colour(iterations, 356, 4); data[idx + 3] = 255; @@ -51,5 +53,9 @@ define(["require", "exports"], function (require, exports) { return data; } exports.getData = getData; + function getDataBuffer() { + return (data.buffer); + } + exports.getDataBuffer = getDataBuffer; ; }); diff --git a/assemblyscript/mandelbrot.ts b/assemblyscript/mandelbrot.ts index b86f24b..92cd230 100644 --- a/assemblyscript/mandelbrot.ts +++ b/assemblyscript/mandelbrot.ts @@ -1,5 +1,9 @@ -const WIDTH: f64 = 1200, HEIGHT: f64 = 800; -const data: Uint8Array = new Uint8Array(1200 * 800 * 4); +import "allocator/arena"; + +const WIDTH: i32 = 1200; +const HEIGHT: i32 = 800; + +var data: Uint8Array = new Uint8Array(WIDTH * HEIGHT * 4); function colour(iteration: i32, offset: i32, scale: i32): u8 { iteration = ((iteration * scale) + offset) % 1024; @@ -7,14 +11,13 @@ function colour(iteration: i32, offset: i32, scale: i32): u8 { return iteration as u8; } else if (iteration < 512) { return 255 - ((iteration as u8) - 255); - } else { - return 0; - } + } + return 0; } function iterateEquation(x0: f64, y0: f64, maxiterations: i32): i32 { - let a: f64 = 0, b: f64 = 0, rx: f64 = 0, ry: f64 = 0; - let iterations: i32 = 0; + let a = 0.0, b = 0.0, rx = 0.0, ry = 0.0; + let iterations = 0; while (iterations < maxiterations && (rx * rx + ry * ry <= 4)) { rx = a * a - b * b + x0; ry = 2 * a * b + y0; @@ -25,27 +28,33 @@ function iterateEquation(x0: f64, y0: f64, maxiterations: i32): i32 { return iterations; } +@inline function scale(domainStart: f64, domainLength: f64, screenLength: f64, step: f64): f64 { return domainStart + domainLength * ((step - screenLength) / screenLength); } export function mandelbrot(maxIterations: i32, cx: f64, cy: f64, diameter: f64): void { - const verticalDiameter: f64 = diameter * HEIGHT / WIDTH; - for (var x: f64 = 0; x < WIDTH; x++) { - for (var y: f64 = 0; y < HEIGHT; y++) { + let verticalDiameter: f64 = diameter * HEIGHT / WIDTH; + for (let x = 0; x < WIDTH; ++x) { + for (let y = 0; y < HEIGHT; ++y) { // convert from screen coordinates to mandelbrot coordinates - const rx: f64 = scale(cx, diameter, WIDTH, x); - const ry: f64 = scale(cy, verticalDiameter, HEIGHT, y); - const iterations: i32 = iterateEquation(rx, ry, maxIterations); - const idx: i32 = ((x + y * (WIDTH as f64)) * 4) as i32; - data[idx] = iterations == maxIterations ? 0 : colour(iterations, 0, 4); - data[idx + 1] = iterations == maxIterations ? 0 : colour(iterations, 128, 4); - data[idx + 2] = iterations == maxIterations ? 0 : colour(iterations, 356, 4); - data[idx+3] = 255; + let rx = scale(cx, diameter, WIDTH, x); + let ry = scale(cy, verticalDiameter, HEIGHT, y); + let iterations = iterateEquation(rx, ry, maxIterations); + let idx = (x + y * WIDTH) << 2; + + unchecked(data[idx + 0] = iterations == maxIterations ? 0 : colour(iterations, 0, 4)); + unchecked(data[idx + 1] = iterations == maxIterations ? 0 : colour(iterations, 128, 4)); + unchecked(data[idx + 2] = iterations == maxIterations ? 0 : colour(iterations, 356, 4)); + unchecked(data[idx + 3] = 255); } } } export function getData(): Uint8Array { return data; +} + +export function getDataBuffer(): ArrayBuffer { + return (data.buffer); }; diff --git a/assemblyscript/mandelbrot.wasm b/assemblyscript/mandelbrot.wasm index fd83cb56c2eca6cd7a8dbcebb8a53574a63bfcde..a154a5df5b10675a9166e962752e4c406eacf8c0 100644 GIT binary patch literal 1408 zcmbVM&5GPc5U&1_)S8}Ub+BRa`cTsBAr}X7iNTks%qEx^+pjQdcDzBen`JhWV1uwG z#sqxL6U>hB(J(h(^Du@$o*<`;KmCj{kmM49T3=UHSAF%Prjs8o6cMS<-B?$Zs>Z5b zOjT7hwpCe{G&W_ql|e=IOJ)!&O*SxL7zG9%!ke~ILVjllt$0zd>3imp6|Ho&~CRY@N7n6(2s~4J_a)aOF_&a4PCYv+K0*`%YbMhmVDW*cA zLY~hu`ie3w$s8)yOsuA|*_ZDB zYn$&w!Rj6nKDrP!Z8uuV0O}-sfLlr`Dib!cXefvb}5S z1K`{t@aPbtHwd;(RfOShsL;GKr7D!?&kefWjD;v+2%_R_I!`bYeRT>{RwWo2^j3yY zVHDab;bRdPA6NHW?@H_Aj>(^DUD*A; zu2?P8h=XQ>?KRUfb7{a)8nVF@rKV1Wjla`0_M8>w)?I?&Lf6Ae`vK@JEU^4#FdqB9 z9@ck8$CWDCbm89Qs}}wCYyLLf(>d4-fA7J2n$^KLmHX(#yX-A?j00qvHn9P`bhgvy7Sku literal 9556 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 rrhAj!>E8DE;qLU_(f#%O&e6fq!%4OB