Skip to content

Commit

Permalink
updated AssemblyScript to latest version
Browse files Browse the repository at this point in the history
  • Loading branch information
ColinEberhardt committed Jul 22, 2018
1 parent 6089569 commit a9e6666
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 67 deletions.
2 changes: 1 addition & 1 deletion app.js
Expand Up @@ -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')(),
];

Expand Down
39 changes: 26 additions & 13 deletions 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.'
}
};
};
24 changes: 15 additions & 9 deletions 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.'
});
});
46 changes: 26 additions & 20 deletions 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;
Expand All @@ -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;
Expand All @@ -51,5 +53,9 @@ define(["require", "exports"], function (require, exports) {
return data;
}
exports.getData = getData;
function getDataBuffer() {
return (data.buffer);
}
exports.getDataBuffer = getDataBuffer;
;
});
45 changes: 27 additions & 18 deletions assemblyscript/mandelbrot.ts
@@ -1,20 +1,23 @@
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;
if (iteration < 256) {
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;
Expand All @@ -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 <ArrayBuffer>(data.buffer);
};
Binary file modified assemblyscript/mandelbrot.wasm
Binary file not shown.
10 changes: 6 additions & 4 deletions assemblyscript/package.json
Expand Up @@ -5,13 +5,15 @@
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build-tsc": "tsc",
"build-asc": "asc -O3 mandelbrot.ts -o mandelbrot.wasm"
"build-tsc": "npx tsc",
"build-asc": "npx asc mandelbrot.ts -b mandelbrot.wasm -t mandelbrot.wat -O3 --validate --noDebug --noAssert --use abort=",
"build": "npm run build-asc && npm run build-tsc"
},
"author": "ceberhardt@scottlogic.com",
"license": "ISC",
"dependencies": {
"assemblyscript": "^0.3.0",
"typescript": "^2.5.3"
"assemblyscript": "github:AssemblyScript/assemblyscript",
"glob": "^7.1.2",
"typescript": "^2.9.2"
}
}
5 changes: 3 additions & 2 deletions assemblyscript/tsconfig.json
@@ -1,9 +1,10 @@
{
"extends": "./node_modules/assemblyscript/tsconfig.assembly.json",
"extends": "./node_modules/assemblyscript/std/assembly.json",
"include": [
"./*.ts"
"./**/*.ts"
],
"compilerOptions": {
"target": "es6",
"module": "amd"
}
}

0 comments on commit a9e6666

Please sign in to comment.