# Blade gfx, luminance, vulkano, wgpu, rafx, sierra ... Yet *another* graphics library? ![](https://i.imgur.com/uXB8rPj.png) --- ## Motivation Case: [Rusty Vangers](https://vange.rs/) ![](https://i.imgur.com/5G1SEDH.png) - 15 pipelines - 7 pipeline layouts, 8 bind group layouts - .. after [removing GPU physics](https://github.com/kvark/vange-rs/commit/c54426c3d6438dd1fd34e2d26147d06fff5065f9) <!-- yes, but different must be FUN (go through a process step by step) other examples: Veloren --> --- ### Motivation: GPU evolves Lots workloads where CPU costs are small: - AZDO (term from late OpenGL) - compute/ML workloads - Ray Tracing <!-- Really, it's hard to come up with a counter-example. Unless it's GTA-5. --> --- ### Why not wgpu/hal? Constraints... <!-- wgpu: safety, layers, design constraints wgpu-hal: attempted, but constrained by D3D12 --> --- ## Lean ![](https://i.imgur.com/DMX4T3z.png) <!-- Who does the heavy lifting? wgpu-hal, rafx-api, sierra: **user** vulkano: user/types/macros/library wgpu, rafx, arcana: **library** blade: **driver** --> --- ## State tracking No per-object state. No image layout transitions. Global barriers between passes. ```rust if let mut pass_encoder = encoder.compute() { let mut pipeline_encoder = pass_encoder.with(pipeline); pipeline_encoder.dispatch(..); } ``` <!-- all images are VK_LAYOUT_GENERAL --> --- ## State tracking: example 1. Create a resource 2. Use in a compute/render/transder pass 3. Submit the command encoder. --- ## Binding model No layouts. No descriptor sets. No uniform buffers, just plain data. <!-- no headache, no caching --> --- ### Binding model: define group ```rust #[derive(bytemuck::Pod)] struct MyUniformStruct { data: u32 } #[derive(blade::ShaderData)] struct Foo { texture: blade::TextureView, uniform: MyUniformStruct, } ``` --- ### Binding model: pipeline creation ```rust let foo_layout = <Foo as blade::ShaderData>::layout(); context.create_pipeline(blade::ComputePipelineDescriptor { data_layouts: &[&foo_layout], }); ``` --- ### Binding model: binding ```rust pass.bind(0, &Foo { texture: my_texture_view, uniform: MyUniformStruct { // plain data data: 1, }, }); ``` --- ### Binding model: thoughts Makes prototyping a breeze! Was BG/BGL/PL a design mistake in WebGPU? <!-- without it, WebGPU basically becomes Metal --> --- ### Lean: code size ![](https://i.imgur.com/pwjFXUX.png) Disclaimer: Blade is much incomplete! --- ## But is it fast? Can do around 20K draw calls per frame on a low-end laptop. --- ## Mean - Totally *unsafe*: use at your own risk. - No tools: ask your local GPU vendor. - Incomplete: customize for your needs. <!-- use your own validation and capturing --> --- ### Mean: shortcuts Who needs vertex buffers, anyway? One context - one window. --- ### Mean: no contract All libraries: we got you! Blade: bring your own maintainer See [What it feels like to be an open-source maintainer](https://nolanlawson.com/2017/03/05/what-it-feels-like-to-be-an-open-source-maintainer/) --- ## Ergonomics Resource objects: light and copyable. ```rust pub struct Buffer { raw: vk::Buffer, memory_handle: usize, mapped_data: *mut u8, } ``` Context: Has everything, internally synchronized. <!--For an unsafe library, ergonomics >> partial safety.--> --- ## API: Shaders Validated(*) WGSL modules. Without resource binding decorations! ```rust var sprite_texture: texture_2d<f32>; var sprite_sampler: sampler; ``` --- ## TL;DR: why use Blade? ![](https://i.imgur.com/Hp9gqlV.png) --- ## Why not use Blade? ![](https://i.imgur.com/ap9l0vj.png) --- # Demo & Questions https://github.com/kvark/blade
{"metaMigratedAt":"2023-06-17T18:37:28.810Z","metaMigratedFrom":"YAML","title":"Blade","breaks":true,"description":"Lean and mean graphics library.","slideOptions":"{\"theme\":\"serif\",\"transition\":\"fade\"}","contributors":"[{\"id\":\"979e994f-8a6f-4ba5-b86c-9af3abd000ad\",\"add\":5060,\"del\":1203}]"}
    1007 views