{"id":19941054,"url":"https://github.com/rust-gpu/spirt","last_synced_at":"2025-06-13T20:06:26.267Z","repository":{"id":257813395,"uuid":"827375993","full_name":"Rust-GPU/spirt","owner":"Rust-GPU","description":"SPIR-🇹: shader-focused IR to target, transform and translate from 🦀","archived":false,"fork":false,"pushed_at":"2024-11-05T22:26:20.000Z","size":1247,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-05T23:27:39.498Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rust-GPU.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-11T14:31:37.000Z","updated_at":"2024-11-05T22:26:23.000Z","dependencies_parsed_at":"2024-10-07T15:39:53.834Z","dependency_job_id":null,"html_url":"https://github.com/Rust-GPU/spirt","commit_stats":null,"previous_names":["rust-gpu/spirt"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rust-GPU%2Fspirt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rust-GPU%2Fspirt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rust-GPU%2Fspirt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rust-GPU%2Fspirt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rust-GPU","download_url":"https://codeload.github.com/Rust-GPU/spirt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224365429,"owners_count":17299156,"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","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":[],"created_at":"2024-11-13T00:07:57.995Z","updated_at":"2024-11-13T00:07:58.755Z","avatar_url":"https://github.com/Rust-GPU.png","language":"Rust","readme":"\u003c!-- Allow this file to not have a first line heading --\u003e\n\u003c!-- markdownlint-disable-file MD041 no-emphasis-as-heading --\u003e\n\n\u003c!-- inline html --\u003e\n\u003c!-- markdownlint-disable-file MD033 --\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n# `SPIR-🇹`\n\n**⋯🢒 🇹arget 🠆 🇹ransform 🠆 🇹ranslate ⋯🢒**\n\n[![Crates.io](https://img.shields.io/crates/v/spirt.svg)](https://crates.io/crates/spirt)\n[![Docs](https://docs.rs/spirt/badge.svg)](https://docs.rs/spirt)\n[![Git Docs](https://img.shields.io/badge/git%20main%20docs-published-blue)](https://rust-gpu.github.io/spirt/spirt/index.html)\n[![Build status](https://github.com/rust-gpu/spirt/workflows/CI/badge.svg)](https://github.com/rust-gpu/spirt/actions)\n\u003c/div\u003e\n\n**SPIR-🇹** is a research project aimed at exploring shader-oriented IR designs derived from SPIR-V, and producing a framework around such an IR to facilitate advanced compilation pipelines, beyond what existing SPIR-V tooling allows for.\n\nSuch a need arose in the [Rust-GPU] project, which requires a variety of legalization passes to turn general-purpose (Rust\u003csup\u003e1\u003c/sup\u003e) code operating on *untyped* memory, into GPU-friendly direct data-flow.  \nOur goal is to replace the existing [Rust-GPU] SPIR-V legalizations passes with **SPIR-🇹** equivalents - but even more imporantly, **SPIR-🇹** should allow writing much more powerful legalization/optimization passes, that would've been unfathomable\u003csup\u003e2\u003c/sup\u003e for direct SPIR-V manipulation.\n\n---\n\n\u003csub\u003e\u003csup\u003e1\u003c/sup\u003e Rust is not unique in its needs here, and more languages (or IRs) could eventually make use of such a framework, but the initial design and implementation work has focused on [Rust-GPU]\u003c/sub\u003e\n\n\u003csub\u003e\u003csup\u003e2\u003c/sup\u003e not outright impossible, but requiring excessive development/maintenance cost, having to constantly balance correctness and power (more conservative passes are easier to trust), etc.\u003c/sub\u003e\n\n## Disclaimer\n\nThis project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with Khronos Group Inc., or any of its subsidiaries or its affiliates. The official Khronos Group Inc. website can be found at https://www.khronos.org.  \nThe names SPIR, SPIR-V, as well as related names, marks, emblems and images are trademarks of their respective owners.\n\n\u003csub\u003e\u003ci\u003eAdditional context: the name of this project is a pun on SPIR-V, and entirely unrelated to SPIR (the older IR standard).\u003c/i\u003e\u003c/sub\u003e\n\n## Status\n\n🚧 *This project is in active design and development, many details can and will change* 🚧\n\nIf you're interested in using **SPIR-🇹** yourself, you may want to first take a look at [the issue tracker](https://github.com/rust-gpu/spirt/issues) for relevant issues, and even open new ones describing your usecase.  \nWith the initial focus being on [Rust-GPU]'s usecase, various (otherwise desirable) functionality/APIs/docs may be lacking, or rapidly changing - at the same time, discussions around widening the scope and usability of **SPIR-🇹** _in the long term_ are still welcome.\n\n### Non-goals (at least in the short term)\n\n* supporting the (\"OpenCL\") `Kernel` dialect of SPIR-V\n  * `Kernel` SPIR-V is much closer to LLVM IR, than `Shader` SPIR-V, and\n    as such tooling oriented around LLVM is more likely to be a better fit\n* textual syntax that can be parsed back\n  * i.e. the pretty-printer output is purely a visualization\n\n### Designed and implemented so far\n\n\u003ctable\u003e\n\u003ctr\u003e\u003ctd width=\"50%\"\u003e\n\n**IR data types**:\n* allowing near-arbitrary SPIR-V instructions for any unrecognized opcodes\n  * IDs are replaced with interned/\"entity\" handles (see below)\n* interning for attributes (decorations \u0026 similar), types and constants\n  * i.e. automatic deduplication, efficient indexing, and no concept of \"definition\"\n    (only uses of interned handles can lead to a module being considered to contain a specific type/constant)\n* \"entity\" system for e.g. definitions in a module, instructions in a function, etc.\n  * disallows iteration in favor of/forcing the use of efficient indexing\n* structured control-flow \"regions\" inspired by RVSDG, stricter than SPIR-V\n  (see `RegionDef`'s docs for more details)\n\n\u003c/td\u003e\u003ctd\u003e\n\n**Framework utilities**:\n* `visit`/`transform`: immutable/mutable IR traversal\n* `print`: pretty-printer with (styled and hyperlinked) HTML output\n\n**Passes (to/from/on SPIR-🇹)**:\n* `spv::lower`: \"lowering\" from SPIR-V, normalizing away many irrelevant details\n  * lossy for some relevant details (these are bugs, though many are non-semantic so lower priority)\n* `spv::lift`: \"lifting\" back up to SPIR-V, making arbitrary choices where necessary\n  * comparable to e.g. generating GLSL syntax from SPIR-V, just one level down\n* `cfg::Structurizer`: (re)structurization, from arbitrary control-flow to the stricter structured \"regions\"\n* `passes::link`: mapping (linkage) imports to relevant exports\n\n\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n## Simple example (with non-trivial control-flow)\n\n\u003ctable\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n**GLSL** ([`for-loop.vert.glsl`](tests/data/for-loop.vert.glsl))\u003c/div\u003e\n\u003csup\u003e\n\n```glsl\n#version 450\nout int output0;\nvoid main() {\n    int o = 1;\n    for(int i = 1; i \u003c 10; i++)\n    \t  o *= i;\n    output0 = o;\n}\n```\n\u003c/sup\u003e\n\u003cdiv align=\"center\"\u003e\n\n**WGSL** ([`for-loop.wgsl`](tests/data/for-loop.wgsl))\u003c/div\u003e\n\u003c!--FIXME(eddyb) this is WGSL but GitHub can't syntax-highlight it yet --\u003e\n\u003csup\u003e\n\n```glsl\n@vertex\nfn main() -\u003e @location(0) i32 {\n    var o: i32 = 1;\n    for(var i: i32 = 1; i \u003c 10; i++) {\n    \to *= i;\n    }\n    return o;\n}\n```\n\u003c/sup\u003e\n\u003c/td\u003e\u003ctd\u003e\n\n\u003c!--FIXME(eddyb) link to GH pages having a `.spirt.html` render of this --\u003e\n\u003cdiv align=\"center\"\u003e\n\n**SPIR-🇹**\u003c/div\u003e\n\u003c!--FIXME(eddyb) this is SPIR-T but GitHub can't syntax-highlight it (ever?) --\u003e\n\u003csup\u003e\n\n\u003c!-- NOTE(eddyb) BEGIN/END below processed by .github/workflows/check-examples.sh --\u003e\n\u003c!-- BEGIN tests/data/for-loop.wgsl.spvasm.structured.spirt --\u003e\n```cxx\n#[spv.Decoration.Flat]\n#[spv.Decoration.Location(Location: 0)]\nglobal_var GV0 in spv.StorageClass.Output: s32\n\nfunc F0() -\u003e spv.OpTypeVoid {\n  loop(v0: s32 \u003c- 1s32, v1: s32 \u003c- 1s32) {\n    v2 = spv.OpSLessThan(v1, 10s32): bool\n    (v3: s32, v4: s32) = if v2 {\n      v5 = spv.OpIMul(v0, v1): s32\n      v6 = spv.OpIAdd(v1, 1s32): s32\n      (v5, v6)\n    } else {\n      (spv.OpUndef: s32, spv.OpUndef: s32)\n    }\n    (v3, v4) -\u003e (v0, v1)\n  } while v2\n  spv.OpStore(Pointer: \u0026GV0, Object: v0)\n}\n```\n\u003c!-- END tests/data/for-loop.wgsl.spvasm.structured.spirt --\u003e\n\u003c/sup\u003e\n\u003c/td\u003e\u003ctd\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n**SPIR-V** ([`for-loop.wgsl.spvasm`](tests/data/for-loop.wgsl.spvasm))\u003c/div\u003e\n\u003c!--FIXME(eddyb) this is SPIR-V assembly but GitHub can't syntax-highlight it yet --\u003e\n\u003csup\u003e\n\n```llvm\n%typeof_output0 = OpTypePointer Output %i32\n%output0 = OpVariable %typeof_output0 Output\n\n%typeof_main = OpTypeFunction %void\n%main = OpFunction %void None %typeof_main\n  %entry = OpLabel\n    OpBranch %bb0\n  %bb0 = OpLabel\n    OpBranch %bb1\n  %bb1 = OpLabel\n    %o = OpPhi %i32 %1_i32 %bb0 %o_next %bb5\n    %i = OpPhi %i32 %0_i32 %bb0 %i_next %bb5\n    OpLoopMerge %bb6 %bb5 None\n    OpBranch %bb2\n  %bb2 = OpLabel\n    %cond = OpSLessThan %bool %i %10_i32\n    OpSelectionMerge %bb4 None\n  OpBranchConditional %cond %bb4 %bb3\n  %bb3 = OpLabel\n    OpBranch %bb6\n  %bb4 = OpLabel\n    %o_next = OpIMul %i32 %o %i\n    OpBranch %bb5\n  %bb5 = OpLabel\n    %i_next = OpIAdd %i32 %i %1_i32\n    OpBranch %bb1\n  %bb6 = OpLabel\n    OpStore %output0 %o\n    OpReturn\nOpFunctionEnd\n```\n\u003c/sup\u003e\n\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n## GPU (shader) IR landscape overview\n*(and the vision of how **SPIR-🇹** fits into it)*\n\n![](docs/landscape.svg)\n\nThe distinction being made here is between:\n* **Interchange IRs** (standards that many tools can use to interoperate)\n  * SPIR-V was very much intended as such a standard\n    (outside of the GPU space, wasm is also a great example)\n  * they only need to encode the right concepts, not straying too far away from what tools understand, but the design effort is often oriented around being a \"serialization\" format\n* **Compiler IRs** (non-standard implementation details of compilers)\n  * LLVM is quite well-known, but Mesa's NIR is even closer to **SPIR-🇹**\n    (both being shader-oriented, and having similar specialized choices of e.g. handling control-flow)\n  * these _have to_ handle legalization/optimization passes quite well, and in general a lot of on-the-fly transformations - as their main purpose is to _expedite_ such operations\n  * this is where **SPIR-🇹** sits, as a kind of \"relative\"/dialect of SPIR-V, but making trade-offs in favor of the \"intra-compiler\" usage\n\n## Contribution\n\n[![Contributor Covenant](https://img.shields.io/badge/contributor%20covenant-v1.4-ff69b4.svg)](CODE_OF_CONDUCT.md)\n\nWe welcome community contributions to this project.\n\nPlease read our [Contributor Guide](CONTRIBUTING.md) for more information on how to get started.\nPlease also read our [Contributor Terms](CONTRIBUTING.md#contributor-terms) before you make any contributions.\n\nAny contribution intentionally submitted for inclusion shall comply with the Rust standard licensing model (MIT OR Apache 2.0) and therefore be dual licensed as described below, without any additional terms or conditions:\n\n### License\n\nThis contribution is dual licensed under EITHER OF\n\n- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or \u003chttp://opensource.org/licenses/MIT\u003e)\n\nat your option.\n\nFor clarity, \"your\" refers to any licensee/user of the contribution.\n\n[Rust-GPU]: https://github.com/rust-gpu/rust-gpu\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-gpu%2Fspirt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frust-gpu%2Fspirt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-gpu%2Fspirt/lists"}