{"id":22751965,"url":"https://github.com/aandreba/wasm2spirv","last_synced_at":"2025-10-10T09:12:44.188Z","repository":{"id":182599541,"uuid":"666718789","full_name":"Aandreba/wasm2spirv","owner":"Aandreba","description":"Compile your WebAssembly programs into SPIR-V shaders","archived":false,"fork":false,"pushed_at":"2023-10-26T03:43:19.000Z","size":1102,"stargazers_count":57,"open_issues_count":6,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-05T18:44:51.273Z","etag":null,"topics":["glsl","hlsl","msl","rust","spirv","vulkan","wasm","wgsl"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Aandreba.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["Aandreba"]}},"created_at":"2023-07-15T10:51:48.000Z","updated_at":"2025-07-20T13:20:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"506e96f9-0685-4a28-9a41-a05f21b2e91d","html_url":"https://github.com/Aandreba/wasm2spirv","commit_stats":null,"previous_names":["aandreba/wasm2spirv"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Aandreba/wasm2spirv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aandreba%2Fwasm2spirv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aandreba%2Fwasm2spirv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aandreba%2Fwasm2spirv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aandreba%2Fwasm2spirv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Aandreba","download_url":"https://codeload.github.com/Aandreba/wasm2spirv/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aandreba%2Fwasm2spirv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003389,"owners_count":26083579,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["glsl","hlsl","msl","rust","spirv","vulkan","wasm","wgsl"],"created_at":"2024-12-11T05:09:11.901Z","updated_at":"2025-10-10T09:12:44.172Z","avatar_url":"https://github.com/Aandreba.png","language":"Rust","funding_links":["https://github.com/sponsors/Aandreba"],"categories":[],"sub_categories":[],"readme":"[![Crates.io](https://img.shields.io/crates/v/wasm2spirv)](https://crates.io/crates/wasm2spirv)\n[![docs.rs](https://img.shields.io/docsrs/wasm2spirv)](https://docs.rs/wasm2spirv/latest)\n[![GitHub](https://img.shields.io/github/license/Aandreba/wasm2spirv)](https://github.com/Aandreba/wasm2spirv)\n\n# wasm2spirv - Compile your WebAssembly programs into SPIR-V shaders\n\n\u003e **Warning**\n\u003e\n\u003e `wasm2spirv` is still in early development, and not production ready.\n\nThis repository contains the code for both, the CLI and library for wasm2spirv.\nwasm2spirv allows you to compile any WebAssembly program into a SPIR-V shader\n\n## Features\n\n- Compiles your WebAssembly programs into SPIR-V\n- Can transpile into other various shading languages\n- Supports validation and optimization of the resulting SPIR-V\n- Can be compiled to WebAssembly itself\n  - You won't be able to use `spirv-tools` or `tree-sitter` in WebAssembly\n  - `spirvcross` only works on WASI\n  - CLI will have to be compiled to WASI\n\n## Caveats\n\n- Still in early development\n  - Unexpected bugs and crashes are to be expected\n  - Still working through the WebAssembly MVP\n- WebAssembly programs with memory allocations will not work\n  - You can customize whether the `memory.grow` instruction errors the\n    compilation (hard errors) or always returns -1 (soft errors)\n- You'll have to manually provide quite some extra information\n  - This is because SPIR-V has a lot of constructs compared to the simplicity of\n    WebAssembly.\n  - wasm2spirv can do **some** inferrence based on the WebAssembly program\n    itself, but it's usually better to specify most the information on the\n    configuration.\n  - The plan for the future is to be able to store the config information inside\n    the WebAssembly program itself.\n\n## Compilation Targets\n\n| Target      | Windows                         | Linux                           | macOS                           | WebAssembly              |\n| ----------- | ------------------------------- | ------------------------------- | ------------------------------- | ------------------------ |\n| SPIR-V      | ✅                              | ✅                              | ✅                              | ✅                       |\n| GLSL        | ☑️ (spvc-glsl/naga-glsl)         | ☑️ (spvc-glsl/naga-glsl)         | ☑️ (spvc-glsl/naga-glsl)         | ☑️ (spvc-glsl*/naga-glsl) |\n| HLSL        | ☑️ (spvc-hlsl/naga-hlsl)         | ☑️ (spvc-hlsl/naga-hlsl)         | ☑️ (spvc-hlsl/naga-hlsl)         | ☑️ (spvc-hlsl*/naga-hlsl) |\n| Metal (MSL) | ☑️ (spvc-msl/naga-msl)           | ☑️ (spvc-msl/naga-msl)           | ☑️ (spvc-msl/naga-msl)           | ☑️ (spvc-msl*/naga-msl)   |\n| WGSL        | ☑️ (naga-wgsl)                   | ☑️ (naga-wgsl)                   | ☑️ (naga-wgsl)                   | ☑️ (naga-wgsl)            |\n| DXIL        | ❌                              | ❌                              | ❌                              | ❌                       |\n| OpenCL C    | ❌                              | ❌                              | ❌                              | ❌                       |\n| Cuda        | ❌                              | ❌                              | ❌                              | ❌                       |\n| Validation  | ☑️ (spvt-validate/naga-validate) | ☑️ (spvt-validate/naga-validate) | ☑️ (spvt-validate/naga-validate) | ☑️ (naga-validate)        |\n\n- ✅ Supported\n- ☑️ Supported, but requires cargo feature(s)\n- ❌ Unsupported\n\n\\* This feature is only supported on WASI\n\n\u003e **Note**\n\u003e\n\u003e The CLI programs built by the releases use the Khronos compilers/validators\n\u003e whenever possible, faling back to naga compilers/validators if the Khronos are\n\u003e not available or are not supported on that platform.\n\n## Examples\n\nYou can find a few examples on the \"examples\" directory, with their Zig file,\ntranslated WebAssembly Text, and compilation configuration file.\n\n### Saxpy example\n\nZig program\n\n```zig\nexport fn main(n: usize, alpha: f32, x: [*]const f32, y: [*]f32) void {\n    var i = gl_GlobalInvocationID(0);\n    const size = gl_NumWorkGroups(0);\n\n    while (i \u003c n) {\n        y[i] += alpha * x[i];\n        i += size;\n    }\n}\n\nextern \"spir_global\" fn gl_GlobalInvocationID(u32) usize;\nextern \"spir_global\" fn gl_NumWorkGroups(u32) usize;\n```\n\nWebAssembly text\n\n```wasm\n(module\n  (type (;0;) (func (param i32) (result i32)))\n  (type (;1;) (func (param i32 f32 i32 i32)))\n  (import \"spir_global\" \"gl_GlobalInvocationID\" (func (;0;) (type 0)))\n  (import \"spir_global\" \"gl_NumWorkGroups\" (func (;1;) (type 0)))\n  (func (;2;) (type 1) (param i32 f32 i32 i32)\n    (local i32 i32 i32 i32 i32)\n    i32.const 0\n    call 0\n    local.tee 4\n    i32.const 2\n    i32.shl\n    local.set 5\n    i32.const 0\n    call 1\n    local.tee 6\n    i32.const 2\n    i32.shl\n    local.set 7\n    block  ;; label = @1\n      loop  ;; label = @2\n        local.get 4\n        local.get 0\n        i32.ge_u\n        br_if 1 (;@1;)\n        local.get 3\n        local.get 5\n        i32.add\n        local.tee 8\n        local.get 8\n        f32.load\n        local.get 2\n        local.get 5\n        i32.add\n        f32.load\n        local.get 1\n        f32.mul\n        f32.add\n        f32.store\n        local.get 5\n        local.get 7\n        i32.add\n        local.set 5\n        local.get 4\n        local.get 6\n        i32.add\n        local.set 4\n        br 0 (;@2;)\n      end\n    end)\n  (memory (;0;) 16)\n  (global (;0;) (mut i32) (i32.const 1048576))\n  (export \"memory\" (memory 0))\n  (export \"main\" (func 2)))\n```\n\nConfiguration file (in JSON)\n\n```json\n{\n  \"platform\": {\n    \"vulkan\": \"1.1\"\n  },\n  \"addressing_model\": \"logical\",\n  \"memory_model\": \"GLSL450\",\n  \"capabilities\": { \"dynamic\": [\"VariablePointers\"] },\n  \"extensions\": [\"VH_KHR_variable_pointers\"],\n  \"functions\": {\n    \"2\": {\n      \"execution_model\": \"GLCompute\",\n      \"execution_modes\": [{\n        \"local_size\": [1, 1, 1]\n      }],\n      \"params\": {\n        \"0\": {\n          \"type\": \"i32\",\n          \"kind\": {\n            \"descriptor_set\": {\n              \"storage_class\": \"StorageBuffer\",\n              \"set\": 0,\n              \"binding\": 0\n            }\n          }\n        },\n\n        \"1\": {\n          \"type\": \"f32\",\n          \"kind\": {\n            \"descriptor_set\": {\n              \"storage_class\": \"StorageBuffer\",\n              \"set\": 0,\n              \"binding\": 1\n            }\n          }\n        },\n\n        \"2\": {\n          \"type\": {\n            \"size\": \"fat\",\n            \"storage_class\": \"StorageBuffer\",\n            \"pointee\": \"f32\"\n          },\n          \"kind\": {\n            \"descriptor_set\": {\n              \"storage_class\": \"StorageBuffer\",\n              \"set\": 0,\n              \"binding\": 2\n            }\n          },\n          \"pointer_size\": \"fat\"\n        },\n\n        \"3\": {\n          \"type\": {\n            \"size\": \"fat\",\n            \"storage_class\": \"StorageBuffer\",\n            \"pointee\": \"f32\"\n          },\n          \"kind\": {\n            \"descriptor_set\": {\n              \"storage_class\": \"StorageBuffer\",\n              \"set\": 0,\n              \"binding\": 3\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nSPIR-V result\n\n```asm\n; SPIR-V\n; Version: 1.3\n; Generator: rspirv\n; Bound: 73\nOpCapability VariablePointers\nOpCapability Shader\nOpExtension \"VH_KHR_variable_pointers\"\nOpMemoryModel Logical GLSL450\nOpEntryPoint GLCompute %3 \"main\" %6 %7\nOpExecutionMode %3 LocalSize 1 1 1\nOpDecorate %6 BuiltIn GlobalInvocationId\nOpDecorate %7 BuiltIn NumWorkgroups\nOpMemberDecorate %10 0 Offset 0\nOpDecorate %10 Block\nOpDecorate %12 DescriptorSet 0\nOpDecorate %12 Binding 0\nOpMemberDecorate %14 0 Offset 0\nOpDecorate %14 Block\nOpDecorate %16 DescriptorSet 0\nOpDecorate %16 Binding 1\nOpDecorate %17 ArrayStride 4\nOpMemberDecorate %18 0 Offset 0\nOpDecorate %18 Block\nOpDecorate %20 DescriptorSet 0\nOpDecorate %20 Binding 2\nOpDecorate %21 DescriptorSet 0\nOpDecorate %21 Binding 3\n%1 = OpTypeInt 32 0\n%2 = OpConstant  %1  1048576\n%4 = OpTypeVector %1 3\n%5 = OpTypePointer Input %4\n%6 = OpVariable  %5  Input\n%7 = OpVariable  %5  Input\n%8 = OpTypeVoid\n%9 = OpTypeFunction %8\n%10 = OpTypeStruct %1\n%11 = OpTypePointer StorageBuffer %10\n%12 = OpVariable  %11  StorageBuffer\n%13 = OpTypeFloat 32\n%14 = OpTypeStruct %13\n%15 = OpTypePointer StorageBuffer %14\n%16 = OpVariable  %15  StorageBuffer\n%17 = OpTypeRuntimeArray %13\n%18 = OpTypeStruct %17\n%19 = OpTypePointer StorageBuffer %18\n%20 = OpVariable  %19  StorageBuffer\n%21 = OpVariable  %19  StorageBuffer\n%23 = OpTypePointer Function %1\n%28 = OpConstant  %1  2\n%39 = OpTypeBool\n%41 = OpConstant  %1  0\n%42 = OpTypePointer StorageBuffer %1\n%46 = OpTypePointer Function %19\n%50 = OpTypePointer StorageBuffer %13\n%51 = OpConstant  %1  4\n%3 = OpFunction  %8  None %9\n%22 = OpLabel\n%48 = OpVariable  %23  Function %41\n%47 = OpVariable  %46  Function\n%33 = OpVariable  %23  Function\n%30 = OpVariable  %23  Function\n%27 = OpVariable  %23  Function\n%24 = OpVariable  %23  Function\n%25 = OpLoad  %4  %6\n%26 = OpCompositeExtract  %1  %25 0\nOpStore %24 %26\n%29 = OpShiftLeftLogical  %1  %26 %28\nOpStore %27 %29\n%31 = OpLoad  %4  %7\n%32 = OpCompositeExtract  %1  %31 0\nOpStore %30 %32\n%34 = OpShiftLeftLogical  %1  %32 %28\nOpStore %33 %34\nOpBranch %35\n%35 = OpLabel\nOpBranch %36\n%36 = OpLabel\n%40 = OpLoad  %1  %24\n%43 = OpAccessChain  %42  %12 %41\n%44 = OpLoad  %1  %43\n%45 = OpUGreaterThanEqual  %39  %40 %44\nOpLoopMerge %37 %38 None\nOpBranchConditional %45 %37 %38\n%38 = OpLabel\nOpStore %47 %21\n%49 = OpLoad  %1  %27\nOpStore %48 %49\n%52 = OpUDiv  %1  %49 %51\n%53 = OpAccessChain  %50  %21 %41 %52\n%54 = OpLoad  %19  %47\n%55 = OpLoad  %1  %48\n%56 = OpUDiv  %1  %55 %51\n%57 = OpAccessChain  %50  %54 %41 %56\n%58 = OpLoad  %13  %57 Aligned 4\n%59 = OpLoad  %1  %27\n%60 = OpUDiv  %1  %59 %51\n%61 = OpAccessChain  %50  %20 %41 %60\n%62 = OpLoad  %13  %61 Aligned 4\n%63 = OpAccessChain  %50  %16 %41\n%64 = OpLoad  %13  %63\n%65 = OpFMul  %13  %62 %64\n%66 = OpFAdd  %13  %58 %65\nOpStore %53 %66 Aligned 4\n%67 = OpLoad  %1  %27\n%68 = OpLoad  %1  %33\n%69 = OpIAdd  %1  %67 %68\nOpStore %27 %69\n%70 = OpLoad  %1  %24\n%71 = OpLoad  %1  %30\n%72 = OpIAdd  %1  %70 %71\nOpStore %24 %72\nOpBranch %36\n%37 = OpLabel\nOpReturn\nOpFunctionEnd\n```\n\nMetal translation\n\n```metal\n#include \u003cmetal_stdlib\u003e\n#include \u003csimd/simd.h\u003e\n\nusing namespace metal;\n\nstruct _10\n{\n    uint _m0;\n};\n\nstruct _14\n{\n    float _m0;\n};\n\nstruct _18\n{\n    float _m0[1];\n};\n\nkernel void main0(device _10\u0026 _12 [[buffer(0)]], device _14\u0026 _16 [[buffer(1)]], device _18\u0026 _20 [[buffer(2)]], device _18\u0026 _21 [[buffer(3)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 gl_NumWorkGroups [[threadgroups_per_grid]])\n{\n    uint _48 = 0u;\n    uint _29 = gl_GlobalInvocationID.x \u003c\u003c 2u;\n    uint _34 = gl_NumWorkGroups.x \u003c\u003c 2u;\n    device _18* _47;\n    for (uint _24 = gl_GlobalInvocationID.x, _27 = _29, _30 = gl_NumWorkGroups.x, _33 = _34; !(_24 \u003e= _12._m0); )\n    {\n        _47 = \u0026_21;\n        _48 = _27;\n        _21._m0[_27 / 4u] = _47-\u003e_m0[_48 / 4u] + (_20._m0[_27 / 4u] * _16._m0);\n        _27 += _33;\n        _24 += _30;\n        continue;\n    }\n}\n```\n\n## Installation\n\nTo add `wasm2spirv` as a library for your Rust project, run this command on\nyou'r project's root directory.\\\n`cargo add wasm2spirv`\n\nTo install the latest version of the `wasm2spirv` CLI, run this command.\\\n`cargo install wasm2spirv`\n\n## Cargo features\n\n- [`spirv-tools`](https://github.com/EmbarkStudios/spirv-tools-rs) enables\n  optimization and validation.\n- [`spirvcross`](https://github.com/Aandreba/spirvcross) enables\n  cross-compilation to GLSL, HLSL and MSL.\n- [`tree-sitter`](https://github.com/tree-sitter/tree-sitter) enables syntax\n  highlighting on the CLI.\n- [`naga`](https://github.com/gfx-rs/naga/) enables cross-compilation for GLSL,\n  HLSL, MSL and WGSL.\n\n## Related projects\n\n- [SPIRV-LLVM](https://github.com/KhronosGroup/SPIRV-LLVM-Translator) is an\n  official Khronos tool to compile LLVM IR into SPIR-V.\n- [Wasmer](https://github.com/wasmerio/wasmer) is a WebAssembly runtime that\n  runs WebAssembly programs on the host machine.\n- [Bytecoder](https://github.com/mirkosertic/Bytecoder) can translate JVM code\n  into JavaScript, WebAssembly and OpenCL.\n- [Naga](https://github.com/gfx-rs/naga/) is a translator from, and to, various\n  shading languages and IRs.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faandreba%2Fwasm2spirv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faandreba%2Fwasm2spirv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faandreba%2Fwasm2spirv/lists"}