{"id":15138002,"url":"https://github.com/kjolnyr/bevy_app_compute","last_synced_at":"2025-04-09T12:05:58.080Z","repository":{"id":153034109,"uuid":"627939266","full_name":"Kjolnyr/bevy_app_compute","owner":"Kjolnyr","description":"App compute plugin for Bevy","archived":false,"fork":false,"pushed_at":"2024-07-25T17:16:16.000Z","size":72,"stargazers_count":82,"open_issues_count":11,"forks_count":26,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-07T23:10:04.763Z","etag":null,"topics":["bevy","bevy-plugin","compute-shader","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kjolnyr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2023-04-14T14:32:05.000Z","updated_at":"2025-02-14T11:32:32.000Z","dependencies_parsed_at":"2024-11-16T18:41:31.083Z","dependency_job_id":"dc6c8b9f-9435-4a86-9e2b-6ea2ecba0106","html_url":"https://github.com/Kjolnyr/bevy_app_compute","commit_stats":{"total_commits":39,"total_committers":3,"mean_commits":13.0,"dds":"0.15384615384615385","last_synced_commit":"5cc5400e0a309cf010a399d2cde65fc8fdd4b5a6"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kjolnyr%2Fbevy_app_compute","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kjolnyr%2Fbevy_app_compute/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kjolnyr%2Fbevy_app_compute/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kjolnyr%2Fbevy_app_compute/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kjolnyr","download_url":"https://codeload.github.com/Kjolnyr/bevy_app_compute/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248036063,"owners_count":21037092,"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":["bevy","bevy-plugin","compute-shader","rust"],"created_at":"2024-09-26T07:04:13.911Z","updated_at":"2025-04-09T12:05:58.058Z","avatar_url":"https://github.com/Kjolnyr.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bevy App Compute\r\n\r\n![MIT/Apache 2.0](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)\r\n[![Doc](https://docs.rs/bevy_app_compute/badge.svg)](https://docs.rs/bevy_app_compute)\r\n[![Crate](https://img.shields.io/crates/v/bevy_app_compute.svg)](https://crates.io/crates/bevy_app_compute)\r\n\r\n\r\nDispatch and run compute shaders on bevy from App World .\r\n\r\n## Getting Started\r\n\r\nAdd the following line to your `Cargo.toml`\r\n\r\n```toml\r\n[dependencies]\r\nbevy_app_compute = \"0.10.3\"\r\n```\r\n\r\n## Usage\r\n\r\n### Setup\r\n\r\nDeclare your shaders in structs implementing `ComputeShader`. The `shader()` fn should point to your shader source code.\r\nYou need to derive `TypeUuid` as well and assign a unique Uuid:\r\n\r\n```rust\r\n#[derive(TypeUuid)]\r\n#[uuid = \"2545ae14-a9bc-4f03-9ea4-4eb43d1075a7\"]\r\nstruct SimpleShader;\r\n\r\nimpl ComputeShader for SimpleShader {\r\n    fn shader() -\u003e ShaderRef {\r\n        \"shaders/simple.wgsl\".into()\r\n    }\r\n}\r\n```\r\n\r\nNext, declare a struct implementing `ComputeWorker` to declare the bindings and the logic of your worker:\r\n\r\n```rust\r\n#[derive(Resource)]\r\nstruct SimpleComputeWorker;\r\n\r\nimpl ComputeWorker for SimpleComputeWorker {\r\n    fn build(world: \u0026mut World) -\u003e AppComputeWorker\u003cSelf\u003e {\r\n        let worker = AppComputeWorkerBuilder::new(world)\r\n            // Add a uniform variable\r\n            .add_uniform(\"uni\", \u00265.)\r\n\r\n            // Add a staging buffer, it will be available from\r\n            // both CPU and GPU land.\r\n            .add_staging(\"values\", \u0026[1., 2., 3., 4.])\r\n\r\n            // Create a compute pass from your compute shader\r\n            // and define used variables\r\n            .add_pass::\u003cSimpleShader\u003e([4, 1, 1], \u0026[\"uni\", \"values\"])\r\n            .build();\r\n\r\n        worker\r\n    }\r\n}\r\n\r\n```\r\n\r\nDon't forget to add a shader file to your `assets/` folder:\r\n\r\n```rust\r\n\r\n@group(0) @binding(0)\r\nvar\u003cuniform\u003e uni: f32;\r\n\r\n@group(0) @binding(1)\r\nvar\u003cstorage, read_write\u003e my_storage: array\u003cf32\u003e;\r\n\r\n@compute @workgroup_size(1)\r\nfn main(@builtin(global_invocation_id) invocation_id: vec3\u003cu32\u003e) {\r\n    my_storage[invocation_id.x] = my_storage[invocation_id.x] + uni;\r\n}\r\n```\r\n\r\nAdd the `AppComputePlugin` plugin to your app, as well as one `AppComputeWorkerPlugin` per struct implementing `ComputeWorker`:\r\n\r\n```rust\r\nuse bevy::prelude::*;\r\nuse bevy_app_compute::AppComputePlugin;\r\n\r\nfn main() {\r\n    App::new()\r\n        .add_plugins(AppComputePlugin)\r\n        .add_plugins(AppComputeWorkerPlugin::\u003cSimpleComputeWorker\u003e::default());\r\n}\r\n```\r\n\r\nYour compute worker will now run every frame, during the `PostUpdate` stage. To read/write from it, use the `AppComputeWorker\u003cT\u003e` resource!\r\n\r\n```rust\r\nfn my_system(\r\n    mut compute_worker: ResMut\u003cAppComputeWorker\u003cSimpleComputeWorker\u003e\u003e\r\n) {\r\n    if !compute_worker.available() {\r\n        return;\r\n    };\r\n\r\n    let result: Vec\u003cf32\u003e = compute_worker.read_vec(\"values\");\r\n\r\n    compute_worker.write_slice(\"values\", [2., 3., 4., 5.]);\r\n\r\n    println!(\"got {:?}\", result)\r\n}\r\n```\r\n\r\n(see [simple.rs](https://github.com/kjolnyr/bevy_app_compute/tree/dev/examples/simple.rs))\r\n\r\n### Multiple passes\r\n\r\nYou can have multiple passes without having to copy data back to the CPU in between:\r\n\r\n```rust\r\nlet worker = AppComputeWorkerBuilder::new(world)\r\n    .add_uniform(\"value\", \u00263.)\r\n    .add_storage(\"input\", \u0026[1., 2., 3., 4.])\r\n    .add_staging(\"output\", \u0026[0f32; 4])\r\n    // add each item + `value` from `input` to `output`\r\n    .add_pass::\u003cFirstPassShader\u003e([4, 1, 1], \u0026[\"value\", \"input\", \"output\"]) \r\n    // multiply each element of `output` by itself\r\n    .add_pass::\u003cSecondPassShader\u003e([4, 1, 1], \u0026[\"output\"]) \r\n    .build();\r\n\r\n    // the `output` buffer will contain [16.0, 25.0, 36.0, 49.0]\r\n\r\n```\r\n\r\n(see [multi_pass.rs](https://github.com/kjolnyr/bevy_app_compute/tree/dev/examples/multi_pass.rs))\r\n\r\n### One shot computes\r\n\r\nYou can configure your worker to execute only when requested:\r\n\r\n```rust\r\nlet worker = AppComputeWorkerBuilder::new(world)\r\n    .add_uniform(\"uni\", \u00265.)\r\n    .add_staging(\"values\", \u0026[1., 2., 3., 4.])\r\n    .add_pass::\u003cSimpleShader\u003e([4, 1, 1], \u0026[\"uni\", \"values\"])\r\n\r\n    // This `one_shot()` function will configure your worker accordingly\r\n    .one_shot()\r\n    .build();\r\n\r\n```\r\n\r\nThen, you can call `execute()` on your worker when you are ready to execute it:\r\n\r\n```rust\r\n// Execute it only when the left mouse button is pressed.\r\nfn on_click_compute(\r\n    buttons: Res\u003cInput\u003cMouseButton\u003e\u003e,\r\n    mut compute_worker: ResMut\u003cAppComputeWorker\u003cSimpleComputeWorker\u003e\u003e\r\n) {\r\n    if !buttons.just_pressed(MouseButton::Left) { return; }\r\n\r\n    compute_worker.execute();\r\n} \r\n```\r\n\r\nIt will run at the end of the current frame, and you'll be able to read the data in the next frame.\r\n\r\n(see [one_shot.rs](https://github.com/kjolnyr/bevy_app_compute/tree/dev/examples/one_shot.rs))\r\n\r\n\r\n## Examples\r\n\r\nSee [examples](https://github.com/kjolnyr/bevy_app_compute/tree/main/examples)\r\n\r\n\r\n## Features being worked upon\r\n\r\n- Ability to read/write between compute passes.\r\n- add more options to the api, like deciding `BufferUsages` or size of buffers.\r\n- Optimization. Right now the code is a complete mess.\r\n- Tests. This badly needs tests.\r\n\r\n## Bevy version mapping\r\n\r\n|Bevy|bevy_app_compute|\r\n|---|---|\r\n|main|main|\r\n|0.10|0.10.3|\r\n|0.12|0.10.5|\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkjolnyr%2Fbevy_app_compute","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkjolnyr%2Fbevy_app_compute","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkjolnyr%2Fbevy_app_compute/lists"}