Repository: zeux/meshoptimizer (language: cpp)

Issue:
Wasm builds for codecbench
Hi @zeux  .. Should the standalone wasm build for codecbench be expected to work? I build with:

`make codecbench.wasm`
and
`make codecbench-simd.wasm`

and then run with wasmtime but the first returns inf for all scores

```
Algorithm   :   vtx     idx     oct8    oct12   quat12  exp
Score (GB/s):   inf     inf     inf     inf     inf     inf
```

and the simd version has an out-of-bounds memory exception in meshopt_decodeVertexBuffer. Not familiar with where things could be going wrong I've tried doubling TOTAL_MEMORY when building to no avail.  Any suggestions? Right now I am simply putting in print statements and comparing where things first go wrong compared to native.

Thanks.


Discussion / hints:
codecbench works via Emscripten, and isn't designed to be ran within wasmtime. When you say `make codecbench.wasm` you will get a .wasm file that requires Emscripten runtime to work. You should check if `node codecbench.js` / `node codecbench-simd.js` work.
@zeux Hi .. Ok, thanks! But if there are emscripten functions undefined in the module why wouldn't the runtime stop me during verification? It is attempting to run. What about emscripten is needed here and do you think it is something that would be easy to port to another runtime?
I mean, `make codebench.wasm` executes this code:

    emcc [a bunch of source files] -O3 -g -DNDEBUG -s TOTAL_MEMORY=268435456 -o codecbench.js

The .wasm file is just a byproduct. It may depend on arbitrary initialization steps performed by the .js file - I'm not an expert on Emscripten internals but maybe it needs some specific initialization for stack memory for example, if that's not done the decoder is likely to fail. So you're trying to run the .wasm file that is produced as a byproduct of Emscripten compilation using a different runtime without the `.js` file, which I don't think anything guarantees will work.

I don't know what exactly the problem is here, but one thing to note is that the .cpp file relies on `emscripten_get_now` function to compute the time. Maybe wasmtime stubs all unknown functions and this just happens to return 0, or maybe it incorrectly implements this.

So my point is - you're trying to do something that doesn't have to work. If it does, it's an accident, unless wasmtime somehow promises compatibility with emscripten .wasm files without using .js files.

To have this be guaranteed to work under wasmtime I'd expect that you need to build codecbench/codecbench-simd using something like WASI toolchain.
@zeux Ok thanks. The emscripten_get_now is a good suggestion to look into. Yes, I asked about what was your guess about what could be incompatible with emscripten simply because I've run emscripten compiled wasm files in wasmtime before. In some cases though I've also had to implement stubs that did exactly what you point out and that may be what is going on here. If my goal is to run this in wasmtime (which it is) another option would be to try and compile this with clang. I will try that unless you know for sure that's a bad idea? A previous iteration of this .. over a year ago I know you helped @abrown to get this working so that we could run in wasmtime. I ran that myself so I remember that worked fine. Perhaps it still does with a recent version of wasmtime .. but I prefer to get a the current iteration of codebench to work. 
I feel like I tried to use WASI SDK for codecbench and it worked okay but I don't recall exactly... But yeah I feel like that's the more stable route to get this to work. I can look into this, the .js build is useful because browsers don't implement WASI so it allows to run this code on browser engines, but I agree it would be good to get a standalone .wasm option, it's just that the emcc-js output is probably the wrong way to get it.

Fix patch:
diff --git a/Makefile b/Makefile
index 80e733c94..1a05d681b 100644
--- a/Makefile
+++ b/Makefile
@@ -144,11 +144,17 @@ vcachetuner: tools/vcachetuner.cpp $(BUILD)/tools/meshloader.cpp.o $(BUILD)/demo
 codecbench: tools/codecbench.cpp $(LIBRARY)
 	$(CXX) $^ $(CXXFLAGS) $(LDFLAGS) -o $@
 
-codecbench.js codecbench.wasm: tools/codecbench.cpp ${LIBRARY_SOURCES}
-	emcc $^ -O3 -g -DNDEBUG -s TOTAL_MEMORY=268435456 -o $@
+codecbench.js: tools/codecbench.cpp ${LIBRARY_SOURCES}
+	emcc $^ -O3 -g -DNDEBUG -s TOTAL_MEMORY=268435456 -s SINGLE_FILE=1 -o $@
 
-codecbench-simd.js codecbench-simd.wasm: tools/codecbench.cpp ${LIBRARY_SOURCES}
-	emcc $^ -O3 -g -DNDEBUG -s TOTAL_MEMORY=268435456 -msimd128 -o $@
+codecbench-simd.js: tools/codecbench.cpp ${LIBRARY_SOURCES}
+	emcc $^ -O3 -g -DNDEBUG -s TOTAL_MEMORY=268435456 -s SINGLE_FILE=1 -msimd128 -o $@
+
+codecbench.wasm: tools/codecbench.cpp ${LIBRARY_SOURCES}
+	$(WASMCC) $^ -fno-exceptions --target=wasm32-wasi --sysroot=$(WASI_SDK) -lc++ -lc++abi -O3 -g -DNDEBUG -o $@
+
+codecbench-simd.wasm: tools/codecbench.cpp ${LIBRARY_SOURCES}
+	$(WASMCC) $^ -fno-exceptions --target=wasm32-wasi --sysroot=$(WASI_SDK) -lc++ -lc++abi -O3 -g -DNDEBUG -msimd128 -o $@
 
 codecfuzz: tools/codecfuzz.cpp src/vertexcodec.cpp src/indexcodec.cpp
 	$(CXX) $^ -fsanitize=fuzzer,address,undefined -O1 -g -o $@
diff --git a/src/vertexcodec.cpp b/src/vertexcodec.cpp
index 5f3ec204a..4598ae366 100644
--- a/src/vertexcodec.cpp
+++ b/src/vertexcodec.cpp
@@ -77,6 +77,8 @@
 #endif
 
 #ifdef SIMD_WASM
+#undef __DEPRECATED
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 #include <wasm_simd128.h>
 #endif
 
diff --git a/src/vertexfilter.cpp b/src/vertexfilter.cpp
index 023452c2a..606a280aa 100644
--- a/src/vertexfilter.cpp
+++ b/src/vertexfilter.cpp
@@ -52,6 +52,7 @@
 #endif
 
 #ifdef SIMD_WASM
+#undef __DEPRECATED
 #include <wasm_simd128.h>
 #endif
 


Test patch: