Skip to content

Commit

Permalink
Merge pull request #187 from zeux/wasi
Browse files Browse the repository at this point in the history
Switch from Emscripten to WASI SDK
  • Loading branch information
zeux authored Oct 10, 2020
2 parents a507623 + b71b49c commit 58cc432
Show file tree
Hide file tree
Showing 10 changed files with 476 additions and 57 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/build/
/data/
/gltf/bin/
/gltf/bin/gltfpack.wasm
30 changes: 17 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
MAKEFLAGS+=-r -j
COMMA=,

config=debug
files=demo/pirate.obj
Expand All @@ -23,11 +24,15 @@ CFLAGS=-g -Wall -Wextra -Werror -std=c89
CXXFLAGS=-g -Wall -Wextra -Wshadow -Wno-missing-field-initializers -Werror -std=c++98
LDFLAGS=

WASM_SOURCES=src/vertexcodec.cpp src/indexcodec.cpp src/vertexfilter.cpp
WASM_EXPORTS="__initialize","_sbrk"
WASM_EXPORTS+=,"_meshopt_decodeVertexBuffer","_meshopt_decodeIndexBuffer","_meshopt_decodeIndexSequence"
WASM_EXPORTS+=,"_meshopt_decodeFilterOct","_meshopt_decodeFilterQuat","_meshopt_decodeFilterExp"
WASM_FLAGS=-O3 -DNDEBUG -s EXPORTED_FUNCTIONS='[$(WASM_EXPORTS)]' -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=24576 -s TOTAL_MEMORY=65536 --no-entry
WASMCC=clang++
WASI_SDK=

WASM_SOURCES=src/vertexcodec.cpp src/indexcodec.cpp src/vertexfilter.cpp tools/wasmstubs.cpp
WASM_EXPORTS=meshopt_decodeVertexBuffer meshopt_decodeIndexBuffer meshopt_decodeIndexSequence meshopt_decodeFilterOct meshopt_decodeFilterQuat meshopt_decodeFilterExp sbrk __wasm_call_ctors
WASM_FLAGS=--target=wasm32-wasi --sysroot=$(WASI_SDK)
WASM_FLAGS+=$(patsubst %,-Wl$(COMMA)--export=%,$(WASM_EXPORTS))
WASM_FLAGS+=-O3 -DNDEBUG -nostartfiles -nostdlib -Wl,--no-entry -Wl,-s
WASM_FLAGS+=-Wl,-z -Wl,stack-size=24576 -Wl,--initial-memory=65536

ifeq ($(config),iphone)
IPHONESDK=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk
Expand Down Expand Up @@ -79,23 +84,22 @@ format:
gltfpack: $(GLTFPACK_OBJECTS) $(LIBRARY)
$(CXX) $^ $(LDFLAGS) -o $@

gltfpack.js: gltf/bin/gltfpack.js
gltfpack.wasm: gltf/bin/gltfpack.wasm

gltf/bin/gltfpack.js: ${LIBRARY_SOURCES} ${GLTFPACK_SOURCES} tools/meshloader.cpp
@mkdir -p gltf/bin
emcc $^ -o $@ -Os -DNDEBUG -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s NODERAWFS=1
sed -i '1s;^;#!/usr/bin/env node\n;' $@
gltf/bin/gltfpack.wasm: ${LIBRARY_SOURCES} ${GLTFPACK_SOURCES} tools/meshloader.cpp
@mkdir -p gltf/lib
$(WASMCC) $^ -o $@ -Os -DNDEBUG --target=wasm32-wasi --sysroot=$(WASI_SDK)

build/decoder_base.wasm: $(WASM_SOURCES)
@mkdir -p build
emcc $^ $(WASM_FLAGS) -o $@
$(WASMCC) $^ $(WASM_FLAGS) -o $@

build/decoder_simd.wasm: $(WASM_SOURCES)
@mkdir -p build
emcc $^ $(WASM_FLAGS) -o $@ -msimd128 -mbulk-memory
$(WASMCC) $^ $(WASM_FLAGS) -o $@ -msimd128 -mbulk-memory

js/meshopt_decoder.js: build/decoder_base.wasm build/decoder_simd.wasm
sed -i "s#Built with emcc.*#Built with $$(emcc --version | head -n 1)#" $@
sed -i "s#Built with clang.*#Built with $$($(WASMCC) --version | head -n 1)#" $@
sed -i "s#\(var wasm_base = \)\".*\";#\\1\"$$(cat build/decoder_base.wasm | python3 tools/wasmpack.py)\";#" $@
sed -i "s#\(var wasm_simd = \)\".*\";#\\1\"$$(cat build/decoder_simd.wasm | python3 tools/wasmpack.py)\";#" $@

Expand Down
291 changes: 291 additions & 0 deletions gltf/bin/gltfpack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
var fs = require('fs');
var cp = require('child_process');

var WASI_EBADF = 8;
var WASI_EINVAL = 28;
var WASI_EIO = 29;
var WASI_ENOSYS = 52;

var instance;

function getHeap() {
return new DataView(instance.exports.memory.buffer);
}

var fds = {
0: { fd: 0 },
1: { fd: 1 },
2: { fd: 2 },
3: null // fake fd for directory
};

var args = process.argv.slice(1);
var env = Object.keys(process.env).map(function (key) { return key + '=' + process.env[key] });

function nextFd() {
for (var i = 0; ; ++i) {
if (fds[i] === undefined) {
return i;
}
}
}

var wasi = {
proc_exit: function(rval) {
process.exit(rval);
},

fd_close: function(fd) {
if (!fds[fd]) {
return WASI_EBADF;
}

try {
fs.closeSync(fds[fd].fd);
fds[fd] = undefined;
return 0;
} catch (err) {
fds[fd] = undefined;
return WASI_EIO;
}
},

fd_fdstat_get: function(fd, stat) {
if (fds[fd] === undefined) {
return WASI_EBADF;
}

var heap = getHeap();
heap.setUint8(stat + 0, fds[fd] === null ? 3 : 4); // directory
heap.setUint16(stat + 2, 0, true);
heap.setUint32(stat + 8, 0, true);
heap.setUint32(stat + 12, 0, true);
heap.setUint32(stat + 16, 0, true);
heap.setUint32(stat + 20, 0, true);
return 0;
},

path_open32: function(parent_fd, dirflags, path, path_len, oflags, fs_rights_base, fs_rights_inheriting, fdflags, opened_fd) {
if (fds[parent_fd] !== null) {
return WASI_EBADF;
}

var heap = getHeap();

var path_name = Buffer.from(heap.buffer, path, path_len).toString('utf-8');
var flags = (oflags & 1) ? 'w' : 'r';

try {
var real_fd = fs.openSync(path_name, flags);
var stat = fs.fstatSync(real_fd);

var fd = nextFd();
fds[fd] = { fd: real_fd, position: 0, size: stat.size };

heap.setUint32(opened_fd, fd, true);
return 0;
} catch (err) {
return WASI_EIO;
}
},

path_unlink_file: function(parent_fd, path, path_len) {
if (fds[parent_fd] !== null) {
return WASI_EBADF;
}

var heap = getHeap();
var path_name = Buffer.from(heap.buffer, path, path_len).toString('utf-8');

try {
fs.unlinkSync(path_name);
return 0;
} catch (err) {
return WASI_EIO;
}
},

args_sizes_get: function(argc, argv_buf_size) {
var heap = getHeap();

var buf_size = 0;
for (var i = 0; i < args.length; ++i) {
buf_size += Buffer.from(args[i], 'utf-8').length + 1;
}

heap.setUint32(argc, args.length, true);
heap.setUint32(argv_buf_size, buf_size, true);
return 0;
},

args_get: function(argv, argv_buf) {
var heap = getHeap();
var memory = new Uint8Array(heap.buffer);

var argp = argv_buf;

for (var i = 0; i < args.length; ++i) {
var item = Buffer.from(args[i], 'utf-8');

heap.setUint32(argv + i * 4, argp, true);
item.copy(memory, argp);
heap.setUint8(argp + item.length, 0);

argp += item.length + 1;
}

return 0;
},

fd_prestat_get: function(fd, buf) {
var heap = getHeap();

if (fd == 3) {
heap.setUint8(buf, 0);
heap.setUint32(buf + 4, 0, true);
return 0;
} else {
return WASI_EBADF;
}
},

fd_prestat_dir_name: function(fd, path, path_len) {
return 0;
},

path_remove_directory: function(parent_fd, path, path_len) {
return WASI_EINVAL;
},

environ_sizes_get: function(environc, environ_buf_size) {
var heap = getHeap();

var buf_size = 0;
for (var i = 0; i < env.length; ++i) {
buf_size += Buffer.from(env[i], 'utf-8').length + 1;
}

heap.setUint32(environc, env.length, true);
heap.setUint32(environ_buf_size, buf_size, true);
return 0;
},

environ_get: function(environ, environ_buf) {
var heap = getHeap();
var memory = new Uint8Array(heap.buffer);

var envp = environ_buf;

for (var i = 0; i < env.length; ++i) {
var item = Buffer.from(env[i], 'utf-8');

heap.setUint32(environ + i * 4, envp, true);
item.copy(memory, envp);
heap.setUint8(envp + item.length, 0);

envp += item.length + 1;
}

return 0;
},

fd_fdstat_set_flags: function(fd, flags) {
return WASI_ENOSYS;
},

fd_seek32: function(fd, offset, whence, newoffset) {
if (!fds[fd]) {
return WASI_EBADF;
}

var heap = getHeap();

switch (whence) {
case 0:
fds[fd].position = offset;
break;

case 1:
fds[fd].position += offset;
break;

case 2:
fds[fd].position = fds[fd].size;
break;

default:
return WASI_EINVAL;
}

heap.setUint32(newoffset, fds[fd].position, true);
return 0;
},

fd_read: function(fd, iovs, iovs_len, nread) {
if (!fds[fd]) {
return WASI_EBADF;
}

var heap = getHeap();
var read = 0;

for (var i = 0; i < iovs_len; ++i) {
var buf = heap.getUint32(iovs + 8 * i + 0, true);
var buf_len = heap.getUint32(iovs + 8 * i + 4, true);

try {
var readi = fs.readSync(fds[fd].fd, heap, buf, buf_len, fds[fd].position);

fds[fd].position += readi;
read += readi;
} catch (err) {
return WASI_EIO;
}
}

heap.setUint32(nread, read, true);
return 0;
},

fd_write: function(fd, iovs, iovs_len, nwritten) {
var heap = getHeap();
var written = 0;

for (var i = 0; i < iovs_len; ++i) {
var buf = heap.getUint32(iovs + 8 * i + 0, true);
var buf_len = heap.getUint32(iovs + 8 * i + 4, true);

try {
var writei = fs.writeSync(fds[fd].fd, heap, buf, buf_len, fds[fd].position);

fds[fd].position += writei;
written += writei;
} catch (err) {
return WASI_EIO;
}
}

heap.setUint32(nwritten, written, true);
return 0;
},

path_readlink: function(fd, path, path_len, buf, buf_len, bufused) {
if (fd !== -1) {
return WASI_ENOSYS;
}

var heap = getHeap();
var command = Buffer.from(heap.buffer, path, path_len).toString('utf-8');

var ret = cp.spawnSync(command, [], {shell:true});
return ret.status == null ? 256 : ret.status;
},
};

var wasm = fs.readFileSync(__dirname + '/gltfpack.wasm');

WebAssembly.instantiate(wasm, { wasi_snapshot_preview1: wasi })
.then(function (result) {
instance = result.instance;
instance.exports._start();
});
10 changes: 7 additions & 3 deletions gltf/fileio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ TempFile::TempFile(const char* suffix)
path += "\\gltfpack-XXXXXX";
(void)_mktemp(&path[0]);
path += suffix;
#elif defined(__EMSCRIPTEN__)
path = "gltfpack-XXXXXX";
(void)mktemp(&path[0]);
#elif defined(__wasi__)
static int id = 0;
char ids[16];
sprintf(ids, "%d", id++);

path = "gltfpack-temp-";
path += ids;
path += suffix;
#else
path = "/tmp/gltfpack-XXXXXX";
Expand Down
4 changes: 0 additions & 4 deletions gltf/gltfpack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@

#include "../src/meshoptimizer.h"

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif

std::string getVersion()
{
char result[32];
Expand Down
Loading

0 comments on commit 58cc432

Please sign in to comment.