Giter Club home page Giter Club logo

wasm2spirv's Introduction

Crates.io docs.rs GitHub

wasm2spirv - Compile your WebAssembly programs into SPIR-V shaders

Warning

wasm2spirv is still in early development, and not production ready.

This repository contains the code for both, the CLI and library for wasm2spirv. wasm2spirv allows you to compile any WebAssembly program into a SPIR-V shader

Features

  • Compiles your WebAssembly programs into SPIR-V
  • Can transpile into other various shading languages
  • Supports validation and optimization of the resulting SPIR-V
  • Can be compiled to WebAssembly itself
    • You won't be able to use spirv-tools or tree-sitter in WebAssembly
    • spirvcross only works on WASI
    • CLI will have to be compiled to WASI

Caveats

  • Still in early development
    • Unexpected bugs and crashes are to be expected
    • Still working through the WebAssembly MVP
  • WebAssembly programs with memory allocations will not work
    • You can customize whether the memory.grow instruction errors the compilation (hard errors) or always returns -1 (soft errors)
  • You'll have to manually provide quite some extra information
    • This is because SPIR-V has a lot of constructs compared to the simplicity of WebAssembly.
    • wasm2spirv can do some inferrence based on the WebAssembly program itself, but it's usually better to specify most the information on the configuration.
    • The plan for the future is to be able to store the config information inside the WebAssembly program itself.

Compilation Targets

Target Windows Linux macOS WebAssembly
SPIR-V
GLSL ☑️ (spvc-glsl/naga-glsl) ☑️ (spvc-glsl/naga-glsl) ☑️ (spvc-glsl/naga-glsl) ☑️ (spvc-glsl*/naga-glsl)
HLSL ☑️ (spvc-hlsl/naga-hlsl) ☑️ (spvc-hlsl/naga-hlsl) ☑️ (spvc-hlsl/naga-hlsl) ☑️ (spvc-hlsl*/naga-hlsl)
Metal (MSL) ☑️ (spvc-msl/naga-msl) ☑️ (spvc-msl/naga-msl) ☑️ (spvc-msl/naga-msl) ☑️ (spvc-msl*/naga-msl)
WGSL ☑️ (naga-wgsl) ☑️ (naga-wgsl) ☑️ (naga-wgsl) ☑️ (naga-wgsl)
DXIL
OpenCL C
Cuda
Validation ☑️ (spvt-validate/naga-validate) ☑️ (spvt-validate/naga-validate) ☑️ (spvt-validate/naga-validate) ☑️ (naga-validate)
  • ✅ Supported
  • ☑️ Supported, but requires cargo feature(s)
  • ❌ Unsupported

* This feature is only supported on WASI

Note

The CLI programs built by the releases use the Khronos compilers/validators whenever possible, faling back to naga compilers/validators if the Khronos are not available or are not supported on that platform.

Examples

You can find a few examples on the "examples" directory, with their Zig file, translated WebAssembly Text, and compilation configuration file.

Saxpy example

Zig program

export fn main(n: usize, alpha: f32, x: [*]const f32, y: [*]f32) void {
    var i = gl_GlobalInvocationID(0);
    const size = gl_NumWorkGroups(0);

    while (i < n) {
        y[i] += alpha * x[i];
        i += size;
    }
}

extern "spir_global" fn gl_GlobalInvocationID(u32) usize;
extern "spir_global" fn gl_NumWorkGroups(u32) usize;

WebAssembly text

(module
  (type (;0;) (func (param i32) (result i32)))
  (type (;1;) (func (param i32 f32 i32 i32)))
  (import "spir_global" "gl_GlobalInvocationID" (func (;0;) (type 0)))
  (import "spir_global" "gl_NumWorkGroups" (func (;1;) (type 0)))
  (func (;2;) (type 1) (param i32 f32 i32 i32)
    (local i32 i32 i32 i32 i32)
    i32.const 0
    call 0
    local.tee 4
    i32.const 2
    i32.shl
    local.set 5
    i32.const 0
    call 1
    local.tee 6
    i32.const 2
    i32.shl
    local.set 7
    block  ;; label = @1
      loop  ;; label = @2
        local.get 4
        local.get 0
        i32.ge_u
        br_if 1 (;@1;)
        local.get 3
        local.get 5
        i32.add
        local.tee 8
        local.get 8
        f32.load
        local.get 2
        local.get 5
        i32.add
        f32.load
        local.get 1
        f32.mul
        f32.add
        f32.store
        local.get 5
        local.get 7
        i32.add
        local.set 5
        local.get 4
        local.get 6
        i32.add
        local.set 4
        br 0 (;@2;)
      end
    end)
  (memory (;0;) 16)
  (global (;0;) (mut i32) (i32.const 1048576))
  (export "memory" (memory 0))
  (export "main" (func 2)))

Configuration file (in JSON)

{
  "platform": {
    "vulkan": "1.1"
  },
  "addressing_model": "logical",
  "memory_model": "GLSL450",
  "capabilities": { "dynamic": ["VariablePointers"] },
  "extensions": ["VH_KHR_variable_pointers"],
  "functions": {
    "2": {
      "execution_model": "GLCompute",
      "execution_modes": [{
        "local_size": [1, 1, 1]
      }],
      "params": {
        "0": {
          "type": "i32",
          "kind": {
            "descriptor_set": {
              "storage_class": "StorageBuffer",
              "set": 0,
              "binding": 0
            }
          }
        },

        "1": {
          "type": "f32",
          "kind": {
            "descriptor_set": {
              "storage_class": "StorageBuffer",
              "set": 0,
              "binding": 1
            }
          }
        },

        "2": {
          "type": {
            "size": "fat",
            "storage_class": "StorageBuffer",
            "pointee": "f32"
          },
          "kind": {
            "descriptor_set": {
              "storage_class": "StorageBuffer",
              "set": 0,
              "binding": 2
            }
          },
          "pointer_size": "fat"
        },

        "3": {
          "type": {
            "size": "fat",
            "storage_class": "StorageBuffer",
            "pointee": "f32"
          },
          "kind": {
            "descriptor_set": {
              "storage_class": "StorageBuffer",
              "set": 0,
              "binding": 3
            }
          }
        }
      }
    }
  }
}

SPIR-V result

; SPIR-V
; Version: 1.3
; Generator: rspirv
; Bound: 73
OpCapability VariablePointers
OpCapability Shader
OpExtension "VH_KHR_variable_pointers"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %3 "main" %6 %7
OpExecutionMode %3 LocalSize 1 1 1
OpDecorate %6 BuiltIn GlobalInvocationId
OpDecorate %7 BuiltIn NumWorkgroups
OpMemberDecorate %10 0 Offset 0
OpDecorate %10 Block
OpDecorate %12 DescriptorSet 0
OpDecorate %12 Binding 0
OpMemberDecorate %14 0 Offset 0
OpDecorate %14 Block
OpDecorate %16 DescriptorSet 0
OpDecorate %16 Binding 1
OpDecorate %17 ArrayStride 4
OpMemberDecorate %18 0 Offset 0
OpDecorate %18 Block
OpDecorate %20 DescriptorSet 0
OpDecorate %20 Binding 2
OpDecorate %21 DescriptorSet 0
OpDecorate %21 Binding 3
%1 = OpTypeInt 32 0
%2 = OpConstant  %1  1048576
%4 = OpTypeVector %1 3
%5 = OpTypePointer Input %4
%6 = OpVariable  %5  Input
%7 = OpVariable  %5  Input
%8 = OpTypeVoid
%9 = OpTypeFunction %8
%10 = OpTypeStruct %1
%11 = OpTypePointer StorageBuffer %10
%12 = OpVariable  %11  StorageBuffer
%13 = OpTypeFloat 32
%14 = OpTypeStruct %13
%15 = OpTypePointer StorageBuffer %14
%16 = OpVariable  %15  StorageBuffer
%17 = OpTypeRuntimeArray %13
%18 = OpTypeStruct %17
%19 = OpTypePointer StorageBuffer %18
%20 = OpVariable  %19  StorageBuffer
%21 = OpVariable  %19  StorageBuffer
%23 = OpTypePointer Function %1
%28 = OpConstant  %1  2
%39 = OpTypeBool
%41 = OpConstant  %1  0
%42 = OpTypePointer StorageBuffer %1
%46 = OpTypePointer Function %19
%50 = OpTypePointer StorageBuffer %13
%51 = OpConstant  %1  4
%3 = OpFunction  %8  None %9
%22 = OpLabel
%48 = OpVariable  %23  Function %41
%47 = OpVariable  %46  Function
%33 = OpVariable  %23  Function
%30 = OpVariable  %23  Function
%27 = OpVariable  %23  Function
%24 = OpVariable  %23  Function
%25 = OpLoad  %4  %6
%26 = OpCompositeExtract  %1  %25 0
OpStore %24 %26
%29 = OpShiftLeftLogical  %1  %26 %28
OpStore %27 %29
%31 = OpLoad  %4  %7
%32 = OpCompositeExtract  %1  %31 0
OpStore %30 %32
%34 = OpShiftLeftLogical  %1  %32 %28
OpStore %33 %34
OpBranch %35
%35 = OpLabel
OpBranch %36
%36 = OpLabel
%40 = OpLoad  %1  %24
%43 = OpAccessChain  %42  %12 %41
%44 = OpLoad  %1  %43
%45 = OpUGreaterThanEqual  %39  %40 %44
OpLoopMerge %37 %38 None
OpBranchConditional %45 %37 %38
%38 = OpLabel
OpStore %47 %21
%49 = OpLoad  %1  %27
OpStore %48 %49
%52 = OpUDiv  %1  %49 %51
%53 = OpAccessChain  %50  %21 %41 %52
%54 = OpLoad  %19  %47
%55 = OpLoad  %1  %48
%56 = OpUDiv  %1  %55 %51
%57 = OpAccessChain  %50  %54 %41 %56
%58 = OpLoad  %13  %57 Aligned 4
%59 = OpLoad  %1  %27
%60 = OpUDiv  %1  %59 %51
%61 = OpAccessChain  %50  %20 %41 %60
%62 = OpLoad  %13  %61 Aligned 4
%63 = OpAccessChain  %50  %16 %41
%64 = OpLoad  %13  %63
%65 = OpFMul  %13  %62 %64
%66 = OpFAdd  %13  %58 %65
OpStore %53 %66 Aligned 4
%67 = OpLoad  %1  %27
%68 = OpLoad  %1  %33
%69 = OpIAdd  %1  %67 %68
OpStore %27 %69
%70 = OpLoad  %1  %24
%71 = OpLoad  %1  %30
%72 = OpIAdd  %1  %70 %71
OpStore %24 %72
OpBranch %36
%37 = OpLabel
OpReturn
OpFunctionEnd

Metal translation

#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct _10
{
    uint _m0;
};

struct _14
{
    float _m0;
};

struct _18
{
    float _m0[1];
};

kernel void main0(device _10& _12 [[buffer(0)]], device _14& _16 [[buffer(1)]], device _18& _20 [[buffer(2)]], device _18& _21 [[buffer(3)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 gl_NumWorkGroups [[threadgroups_per_grid]])
{
    uint _48 = 0u;
    uint _29 = gl_GlobalInvocationID.x << 2u;
    uint _34 = gl_NumWorkGroups.x << 2u;
    device _18* _47;
    for (uint _24 = gl_GlobalInvocationID.x, _27 = _29, _30 = gl_NumWorkGroups.x, _33 = _34; !(_24 >= _12._m0); )
    {
        _47 = &_21;
        _48 = _27;
        _21._m0[_27 / 4u] = _47->_m0[_48 / 4u] + (_20._m0[_27 / 4u] * _16._m0);
        _27 += _33;
        _24 += _30;
        continue;
    }
}

Installation

To add wasm2spirv as a library for your Rust project, run this command on you'r project's root directory.
cargo add wasm2spirv

To install the latest version of the wasm2spirv CLI, run this command.
cargo install wasm2spirv

Cargo features

  • spirv-tools enables optimization and validation.
  • spirvcross enables cross-compilation to GLSL, HLSL and MSL.
  • tree-sitter enables syntax highlighting on the CLI.
  • naga enables cross-compilation for GLSL, HLSL, MSL and WGSL.

Related projects

  • SPIRV-LLVM is an official Khronos tool to compile LLVM IR into SPIR-V.
  • Wasmer is a WebAssembly runtime that runs WebAssembly programs on the host machine.
  • Bytecoder can translate JVM code into JavaScript, WebAssembly and OpenCL.
  • Naga is a translator from, and to, various shading languages and IRs.

wasm2spirv's People

Contributors

aandreba avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

wasm2spirv's Issues

Schrodinger variables v2

WebAssembly compilers have the tendency to use parameter variables to store temporary data, but with the current implementation of Schrodinger variables, this results in casting between pointers and integers, which isn't allowed on most SPIR-V targets.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.