{"id":25304876,"url":"https://github.com/leops/rasen","last_synced_at":"2025-10-28T09:30:42.261Z","repository":{"id":57658544,"uuid":"68027377","full_name":"leops/rasen","owner":"leops","description":"Generate SPIR-V bytecode from an operation graph","archived":false,"fork":false,"pushed_at":"2020-02-20T14:00:43.000Z","size":231,"stargazers_count":66,"open_issues_count":2,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-05-29T18:35:21.956Z","etag":null,"topics":["compiler","dsl","graph","rust","shaders","spirv","vulkan"],"latest_commit_sha":null,"homepage":"https://docs.rs/rasen/","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/leops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-12T16:35:51.000Z","updated_at":"2023-09-08T16:19:40.000Z","dependencies_parsed_at":"2022-09-16T04:41:32.820Z","dependency_job_id":null,"html_url":"https://github.com/leops/rasen","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leops%2Frasen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leops%2Frasen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leops%2Frasen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leops%2Frasen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leops","download_url":"https://codeload.github.com/leops/rasen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238624054,"owners_count":19503159,"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":["compiler","dsl","graph","rust","shaders","spirv","vulkan"],"created_at":"2025-02-13T08:34:12.366Z","updated_at":"2025-10-28T09:30:41.880Z","avatar_url":"https://github.com/leops.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"Rasen\n================\n\n[![crates.io](https://img.shields.io/crates/v/rasen.svg)](https://crates.io/crates/rasen/)\n[![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/leops/rasen?svg=true)](https://ci.appveyor.com/project/leops/rasen)\n[![Travis Status](https://travis-ci.org/leops/rasen.svg?branch=master)](https://travis-ci.org/leops/rasen/)\n\n# What is Rasen ?\n\nRasen is an umbrella project for a bunch of SPIR-V and Rust related experiments. The core idea of Rasen is to\nprovide a fast and safe compiler for SPIR-V modules, however the core compiler only provide a backend to generate\na shader program from an intermediate representation, specifically a \"dataflow graph\". In traditional, text-based\nlanguages such a graph is a usually a metadata generated by the compiler, but some game engine (eg. Unreal) provide\nan editor to directly edit such a graph, which proved to be a very useful way of quickly prototyping materials.\n\nIn practice, Rasen as a whole is designed with two (seemingly unrelated) use case in mind:\n\n1. To be used as an online shader compiler embedded in a game engine (or any other application doing 3D rendering).\n   Rasen aims to be fast enough to recompile a shader within a frame's budget, and the resulting SPIR-V bytecode can\n   then be retargeted to GLSL, HLSL or MSL using SPIRV-Cross to accomodate the current platform.\n2. To provide a fallback environment for compute shaders in Rust. Rasen uses a special DSL crate to parse Rust code\n   \"from the inside\" and generate a dataflow graph for execution on the GPU, but on constrained platforms where this\n   capability is unavailable the Rust code is still valid and can be run on the CPU instead (and ultimately should be\n   just as fast as raw rust code). As a sidenote, this should also help making shaders more testable and debuggable as\n   they can be now be run on the CPU too.\n\n# Core\n\nThe `rasen` crate contains the core graph compiler itself. It provides graph building utilities (the `Graph` struct),\nvarious types (`rasen::types::*`) and operations (`rasen::node::*`) definitions, and SPIR-V compilation utilities (the\n`ModuleBuilder` struct).\n\nThe API is intentionally low-level, as the use case for the core compiler is to act as a backend for a graph-based\nmaterial editor in a game engine. It's perfectly possible to use this crate as-is by creating a `Graph` struct and\nbuilding the module node-by-node, however this method tends to be quite verbose for \"static\" shaders:\n\n```rust\nextern crate rasen;\n\nuse rasen::prelude::*;\n\nfn main() {\n    let mut graph = Graph::new();\n\n    // A vec3 input at location 0\n    let normal = graph.add_node(Node::Input(0, TypeName::VEC3, VariableName::Named(String::from(\"a_normal\"))));\n\n    // Some ambient light constants\n    let min_light = graph.add_node(Node::Constant(TypedValue::Float(0.1)));\n    let max_light = graph.add_node(Node::Constant(TypedValue::Float(1.0)));\n    let light_dir = graph.add_node(Node::Constant(TypedValue::Vec3(0.3, -0.5, 0.2)));\n\n    // The Material color (also a constant)\n    let mat_color = graph.add_node(Node::Constant(TypedValue::Vec4(0.25, 0.625, 1.0, 1.0)));\n\n    // Some usual function calls\n    let normalize = graph.add_node(Node::Normalize);\n    let dot = graph.add_node(Node::Dot);\n    let clamp = graph.add_node(Node::Clamp);\n    let multiply = graph.add_node(Node::Multiply);\n\n    // And a vec4 output at location 0\n    let color = graph.add_node(Node::Output(0, TypeName::VEC4, VariableName::Named(String::from(\"o_color\"))));\n\n    // Normalize the normal\n    graph.add_edge(normal, normalize, 0);\n\n    // Compute the dot product of the surface normal and the light direction\n    graph.add_edge(normalize, dot, 0);\n    graph.add_edge(light_dir, dot, 1);\n\n    // Restrict the result into the ambient light range\n    graph.add_edge(dot, clamp, 0);\n    graph.add_edge(min_light, clamp, 1);\n    graph.add_edge(max_light, clamp, 2);\n\n    // Multiply the light intensity by the surface color\n    graph.add_edge(clamp, multiply, 0);\n    graph.add_edge(mat_color, multiply, 1);\n\n    // Write the result to the output\n    graph.add_edge(multiply, color, 0);\n\n    let bytecode = build_program(\u0026graph, ShaderType::Fragment).unwrap();\n    // bytecode is now a Vec\u003cu8\u003e you can pass to Vulkan to create the shader module\n}\n```\n\n# DSL\n\nTo reduce the amount of boilerplate, the `rasen_dsl` crate provides a bunch of utility function to write shaders as\nperfectly valid Rust code:\n\n```rust\nextern crate rasen;\nextern crate rasen_dsl;\n\nuse rasen_dsl::prelude::*;\n\nfn main() {\n    let shader = Module::new();\n\n    let normal: Value\u003cVec3\u003e = normalize(shader.input(0, \"a_normal\"));\n    let light = vec3(0.3, -0.5, 0.2);\n    let color = vec4(0.25, 0.625, 1.0, 1.0);\n\n    let res = clamp(dot(normal, light), 0.1f32, 1.0f32) * color;\n    shader.output(0, \"o_color\", res);\n\n    let bytecode = shader.build(ShaderType::Fragment).unwrap();\n    // bytecode is now a Vec\u003cu8\u003e you can pass to Vulkan to create the shader module\n}\n```\n\nThis crate is even more experimental than the Rasen compiler itself, it already provides all the features exposed by\nthe compiler but they might not be completely spec compliant (for instance the typings constraint on the various GLSL\nfunctions may be more, or less strict than required by the OpenGL specification).\n\nUltimately, the goal for the DSL crate (beside being a statically-checked equivalent of the graph builder) is to expose\nan API to test the execution of a shader on the CPU, with all the debugging tools that such an environment provides. The\nlibrary currently provides all the conversion primitives to turn your scalar / vectors / matrices into Value\u003c\\_\u003e types to\ntest your program, however most GLSL operations are left unimplemented.\n\n# Plugin\n\nFinally, the `rasen_plugin` crate is a compiler plugin exposing a few utility macro and attributes to make writing\nshaders in Rust event easier:\n\n```rust\nuse rasen_dsl::prelude::*;\n\n#[rasen(module)]\npub fn basic_vert(a_pos: Value\u003cVec3\u003e, projection: Value\u003cMat4\u003e, view: Value\u003cMat4\u003e, model: Value\u003cMat4\u003e) -\u003e Value\u003cVec4\u003e {\n   let mvp = projection * view * model;\n   mvp * vec4!(a_pos, 1.0f32)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleops%2Frasen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleops%2Frasen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleops%2Frasen/lists"}