{"id":16299031,"url":"https://github.com/teoxoy/encase","last_synced_at":"2025-05-16T13:02:45.877Z","repository":{"id":38392124,"uuid":"466868667","full_name":"teoxoy/encase","owner":"teoxoy","description":"Provides a mechanism to lay out data into GPU buffers according to WGSL's memory layout rules","archived":false,"fork":false,"pushed_at":"2025-04-25T15:59:20.000Z","size":138,"stargazers_count":170,"open_issues_count":13,"forks_count":31,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-11T20:07:03.510Z","etag":null,"topics":["rendering","wgpu","wgsl"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/encase","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit-0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/teoxoy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"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}},"created_at":"2022-03-06T22:08:06.000Z","updated_at":"2025-05-09T12:16:00.000Z","dependencies_parsed_at":"2023-10-14T23:35:24.475Z","dependency_job_id":"600833b7-0968-4398-bdaf-ea2e83a1b0d6","html_url":"https://github.com/teoxoy/encase","commit_stats":{"total_commits":51,"total_committers":7,"mean_commits":7.285714285714286,"dds":"0.11764705882352944","last_synced_commit":"c48b0beeee882f38c263d63d48f793d232ce9119"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoxoy%2Fencase","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoxoy%2Fencase/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoxoy%2Fencase/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teoxoy%2Fencase/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teoxoy","download_url":"https://codeload.github.com/teoxoy/encase/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254535792,"owners_count":22087397,"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":["rendering","wgpu","wgsl"],"created_at":"2024-10-10T20:46:24.178Z","updated_at":"2025-05-16T13:02:45.780Z","avatar_url":"https://github.com/teoxoy.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"./logo.svg\" width=\"320px\" alt/\u003e\u003c/p\u003e\n\nProvides a mechanism to lay out data into GPU buffers ensuring WGSL's memory layout requirements are met.\n\n## Features\n\n- supports all WGSL [host-shareable types] + wrapper types (`\u0026T`, `\u0026mut T`, `Box\u003cT\u003e`, ...)\n- supports data types from a multitude of crates as [features]\n- covers a wide area of use cases (see [examples](#examples))\n\n## Motivation\n\nHaving to manually lay out data into GPU buffers can become very tedious and error prone. How do you make sure the data in the buffer is laid out correctly? Enforce it so that future changes don't break this delicate balance?\n\n`encase` gives you the ability to make sure at compile time that your types will be laid out correctly.\n\n## Design\n\nThe core trait is [`ShaderType`] which mainly contains metadata about the given type.\n\nThe [`WriteInto`], [`ReadFrom`] and [`CreateFrom`] traits represent the ability of a type to be written into the buffer, read from the buffer and created from the buffer respectively.\n\nMost data types can implement the above traits via their respective macros:\n\n  - [`impl_vector!`] for vectors\n  - [`impl_matrix!`] for matrices\n  - [`impl_rts_array!`] for runtime-sized arrays\n  - [`impl_wrapper!`] for wrappers\n  - [`ShaderType`][derive@ShaderType] for structs\n\nThe [`UniformBuffer`], [`StorageBuffer`], [`DynamicUniformBuffer`] and [`DynamicStorageBuffer`] structs are wrappers around an underlying raw buffer (a type implementing [`BufferRef`] and/or [`BufferMut`] depending on required capability). They facilitate the read/write/create operations.\n\n## Examples\n\nWrite affine transform to uniform buffer\n\n```rust\nuse encase::{ShaderType, UniformBuffer};\n\n#[derive(ShaderType)]\nstruct AffineTransform2D {\n    matrix: glam::Mat2,\n    translate: glam::Vec2\n}\n\nlet transform = AffineTransform2D {\n    matrix: glam::Mat2::IDENTITY,\n    translate: glam::Vec2::ZERO,\n};\n\nlet mut buffer = UniformBuffer::new(Vec::\u003cu8\u003e::new());\nbuffer.write(\u0026transform).unwrap();\nlet byte_buffer = buffer.into_inner();\n\n// write byte_buffer to GPU\n\nassert_eq!(\u0026byte_buffer, \u0026[0, 0, 128, 63, 0, 0, 0, 0,\n0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0]);\n```\n\nCreate vector instance by reading from dynamic uniform buffer at specific offset\n\n```rust\nuse encase::DynamicUniformBuffer;\n\n// read byte_buffer from GPU\nlet byte_buffer = [1u8; 256 + 8];\n\nlet mut buffer = DynamicUniformBuffer::new(\u0026byte_buffer);\nbuffer.set_offset(256);\nlet vector: mint::Vector2\u003ci32\u003e = buffer.create().unwrap();\n\nassert_eq!(vector, mint::Vector2 { x: 16843009, y: 16843009 });\n```\n\nWrite and read back data from storage buffer\n\n```rust\nuse encase::{ShaderType, ArrayLength, StorageBuffer};\n\n#[derive(ShaderType)]\nstruct Positions {\n    length: ArrayLength,\n    #[size(runtime)]\n    positions: Vec\u003cmint::Point2\u003cf32\u003e\u003e\n}\n\nlet mut positions = Positions {\n    length: ArrayLength,\n    positions: Vec::from([\n        mint::Point2 { x: 4.5, y: 3.4 },\n        mint::Point2 { x: 1.5, y: 7.4 },\n        mint::Point2 { x: 4.3, y: 1.9 },\n    ])\n};\n\nlet mut byte_buffer: Vec\u003cu8\u003e = Vec::new();\n\nlet mut buffer = StorageBuffer::new(\u0026mut byte_buffer);\nbuffer.write(\u0026positions).unwrap();\n\n// write byte_buffer to GPU\n\n// change length on GPU side\nbyte_buffer[0] = 2;\n\n// read byte_buffer from GPU\n\nlet mut buffer = StorageBuffer::new(\u0026mut byte_buffer);\nbuffer.read(\u0026mut positions).unwrap();\n\nassert_eq!(positions.positions.len(), 2);\n\n```\n\nWrite different data types to dynamic storage buffer\n\n```rust\nuse encase::{ShaderType, DynamicStorageBuffer};\n\nlet mut byte_buffer: Vec\u003cu8\u003e = Vec::new();\n\nlet mut buffer = DynamicStorageBuffer::new_with_alignment(\u0026mut byte_buffer, 64);\nlet offsets = [\n    buffer.write(\u0026[5.; 10]).unwrap(),\n    buffer.write(\u0026vec![3u32; 20]).unwrap(),\n    buffer.write(\u0026glam::Vec3::ONE).unwrap(),\n];\n\n// write byte_buffer to GPU\n\nassert_eq!(offsets, [0, 64, 192]);\n\n```\n\nSupports writing to uninitialized memory as well.\n\n```rust\nuse std::mem::MaybeUninit;\nuse encase::{ShaderType, DynamicStorageBuffer};\n\nlet mut uninit_buffer: Vec\u003cMaybeUninit\u003cu8\u003e\u003e = Vec::new();\n\nlet mut buffer = DynamicStorageBuffer::new_with_alignment(\u0026mut uninit_buffer, 64);\nlet offsets = [\n    buffer.write(\u0026[5.; 10]).unwrap(),\n    buffer.write(\u0026vec![3u32; 20]).unwrap(),\n    buffer.write(\u0026glam::Vec3::ONE).unwrap(),\n];\n\n// SAFETY: Vec\u003cu8\u003e and Vec\u003cMaybeUninit\u003cu8\u003e\u003e share the same layout.\nlet byte_buffer: Vec\u003cu8\u003e = unsafe { \n    Vec::from_raw_parts(\n        uninit_buffer.as_mut_ptr().cast(), \n        uninit_buffer.len(), \n        uninit_buffer.capacity()\n    ) \n};\n\nstd::mem::forget(uninit_buffer);\n\n// write byte_buffer to GPU\n\nassert_eq!(offsets, [0, 64, 192]);\n\n```\n\n[host-shareable types]: https://gpuweb.github.io/gpuweb/wgsl/#host-shareable-types\n[features]: https://docs.rs/crate/encase/latest/features\n[`ShaderType`]: https://docs.rs/encase/latest/encase/trait.ShaderType.html\n\n[`WriteInto`]: https://docs.rs/encase/latest/encase/internal/trait.WriteInto.html\n[`ReadFrom`]: https://docs.rs/encase/latest/encase/internal/trait.ReadFrom.html\n[`CreateFrom`]: https://docs.rs/encase/latest/encase/internal/trait.CreateFrom.html\n\n[`impl_vector!`]: https://docs.rs/encase/latest/encase/macro.impl_vector.html\n[`impl_matrix!`]: https://docs.rs/encase/latest/encase/macro.impl_matrix.html\n[`impl_rts_array!`]: https://docs.rs/encase/latest/encase/macro.impl_rts_array.html\n[`impl_wrapper!`]: https://docs.rs/encase/latest/encase/macro.impl_wrapper.html\n[derive@ShaderType]: https://docs.rs/encase/latest/encase/derive.ShaderType.html\n\n[`UniformBuffer`]: https://docs.rs/encase/latest/encase/struct.UniformBuffer.html\n[`StorageBuffer`]: https://docs.rs/encase/latest/encase/struct.StorageBuffer.html\n[`DynamicUniformBuffer`]: https://docs.rs/encase/latest/encase/struct.DynamicUniformBuffer.html\n[`DynamicStorageBuffer`]: https://docs.rs/encase/latest/encase/struct.DynamicStorageBuffer.html\n\n[`BufferRef`]: https://docs.rs/encase/latest/encase/internal/trait.BufferRef.html\n[`BufferMut`]: https://docs.rs/encase/latest/encase/internal/trait.BufferMut.html","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteoxoy%2Fencase","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteoxoy%2Fencase","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteoxoy%2Fencase/lists"}