Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compilation of spirv-opt to WASM #5029

Open
wdanilo opened this issue Dec 19, 2022 · 7 comments · May be fixed by #5047
Open

Compilation of spirv-opt to WASM #5029

wdanilo opened this issue Dec 19, 2022 · 7 comments · May be fixed by #5047
Assignees

Comments

@wdanilo
Copy link

wdanilo commented Dec 19, 2022

Hi! Is it possible to compile spirv-opt to WASM? I was able to run ./source/wasm/build.sh, but according to docs, "The resulting SpirvTools WebAssembly module only exports methods to assemble and disassemble SPIR-V modules". My use case is that we are generating shaders at runtime and we want to be sure they are properly optimized before feeding them to WebGL, so we want to replicate this workflow in WASM:

glslc --target-env=opengl -fshader-stage=... -o ${FILE}.spv ${FILE}
spirv-opt -Os -o ${FILE}.spv.opt ${FILE}.spv
spirv-cross --output ${FILE}.opt ${FILE}.spv.opt
@dneto0
Copy link
Collaborator

dneto0 commented Dec 19, 2022

The only reason it was limited to assembly and disassembly is that nobody put the work in to do it.
That said the optimizer is quite large, so you may want to make a separate WASM module for the optimizer.

@mwu-tow
Copy link

mwu-tow commented Dec 20, 2022

Hi @dneto0, thank you for the answer! Could you provide us some pointers as to how to proceed with separating the optimizer module and how to compile it? We don't have much experience with CMake, so any hints would be very valuable.

@farmaazon
Copy link

I can answer this question, as I'm doing a similar thing.

The diff I have:

diff --git a/source/wasm/build.sh b/source/wasm/build.sh
index f02ae525..d9f5fda1 100755
--- a/source/wasm/build.sh
+++ b/source/wasm/build.sh
@@ -34,7 +34,7 @@ build() {
         -DCMAKE_BUILD_TYPE=Release \
         $args \
         ../..
-    emmake make -j $(( $NUM_CORES )) SPIRV-Tools-static
+    emmake make -j $(( $NUM_CORES )) SPIRV-Tools-opt
 
     echo Building js interface
     emcc \
@@ -43,6 +43,7 @@ build() {
         -std=c++11 \
         ../../source/wasm/spirv-tools.cpp \
         source/libSPIRV-Tools.a \
+        source/opt/libSPIRV-Tools-opt.a \
         -o spirv-tools.js \
         -s MODULARIZE \
         -Oz
diff --git a/source/wasm/spirv-tools.cpp b/source/wasm/spirv-tools.cpp
index 33f2f05f..f9dffc9c 100644
--- a/source/wasm/spirv-tools.cpp
+++ b/source/wasm/spirv-tools.cpp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "spirv-tools/libspirv.hpp"
+#include "spirv-tools/optimizer.hpp"
 
 #include <iostream>
 #include <string>
@@ -50,9 +51,22 @@ emscripten::val as(std::string const& source, uint32_t env, uint32_t options) {
     ptr));
 }
 
+emscripten::val opt(std::string const& input, uint32_t env, uint32_t options) {
+  spvtools::Optimizer optimizer(static_cast<spv_target_env>(env));
+  optimizer.SetMessageConsumer(print_msg_to_stderr);
+
+  std::vector<uint32_t> optimized;
+  const uint32_t* input_ptr = reinterpret_cast<const uint32_t*>(input.data());
+  if (!optimizer.Run(input_ptr, input.size(), &optimized)) optimized.clear();
+  const uint8_t* output_ptr = reinterpret_cast<const uint8_t*>(optimized.data());
+  return emscripten::val(emscripten::typed_memory_view(optimized.size() * 4,
+    output_ptr));
+}
+
 EMSCRIPTEN_BINDINGS(my_module) {
   function("dis", &dis);
   function("as", &as);
+  function("opt", &opt);
   
   constant("SPV_ENV_UNIVERSAL_1_0", static_cast<uint32_t>(SPV_ENV_UNIVERSAL_1_0));
   constant("SPV_ENV_VULKAN_1_0", static_cast<uint32_t>(SPV_ENV_VULKAN_1_0));

No cmake needed to be built, we must just build a different target (the emmake command) and link the built static library to the interface.

Additionally, in source/wasm/spirv-tools.cpp you need to bind the functions you want to use in js using embind. For example, I've created a simple function opt for optimizing existing binary. Be careful, though: it duplicates the problem the as method has with returning a pointer to freed memory (see #5036)

@dneto0
Copy link
Collaborator

dneto0 commented Dec 22, 2022

Thanks. Yesterday I was looking at making a separate node package for the optimizer because it is so large.
I'm most of the way there, and will take care of the use-after-free.

@dneto0
Copy link
Collaborator

dneto0 commented Dec 22, 2022

Also, the optimizer has a more complicated interface, where you can schedule specific passes, or entire recipes at a time. So I was working my way through providing that API.

dneto0 added a commit to dneto0/SPIRV-Tools that referenced this issue Dec 22, 2022
dneto0 added a commit to dneto0/SPIRV-Tools that referenced this issue Dec 22, 2022
@dneto0 dneto0 linked a pull request Dec 22, 2022 that will close this issue
@dneto0
Copy link
Collaborator

dneto0 commented Dec 22, 2022

I have a WIP PR that adds a separate WASM package for the spir-v optimizer.
The compressed wasm is 562kb. Which is a lot.

And the PR doesn't work. Something is being messed up earlier in the flow I think.
The simple SPIR-V module assembled in the test-opt.js file doesn't disassemble.

I'd welcome feedback if I've messed up WASM-bindings or other emscripten things. I'm a total newbie in it.

@wdanilo
Copy link
Author

wdanilo commented Dec 23, 2022

Also, the optimizer has a more complicated interface, where you can schedule specific passes, or entire recipes at a time. So I was working my way through providing that API.

Oh wow, thank you so much @dneto0 ❤️ I was able to compile the WASM module with what @farmaazon provided above and the final WASM opt file is relatively small - 2Mb? I'm wondering if it contains all the passes though. Just out of curiosity, do you have any approximate timeline for your module? I'm asking only to plan how / when I could integrate it to what we are building 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
@mwu-tow @wdanilo @farmaazon @dneto0 @s-perron and others