From cf338190cf9683a2fe20d1bbcc99a8636fccf028 Mon Sep 17 00:00:00 2001 From: Swoorup Joshi Date: Sat, 10 Aug 2024 17:09:37 +1000 Subject: [PATCH] Support push constants output in naga_oil composition strategy --- example/build.rs | 5 +- example/shaders/triangle.wgsl | 8 +- example/src/main.rs | 21 +- example/src/shader_bindings.rs | 2833 +++++++++-------- wgsl_bindgen/src/bindgen/bindgen.rs | 4 +- wgsl_bindgen/src/bindgen/options/mod.rs | 7 +- wgsl_bindgen/src/generate/bind_group/mod.rs | 22 +- wgsl_bindgen/src/generate/mod.rs | 26 + wgsl_bindgen/src/generate/pipeline.rs | 36 +- wgsl_bindgen/src/generate/shader_module.rs | 32 +- wgsl_bindgen/src/lib.rs | 29 +- wgsl_bindgen/tests/bindgen_tests.rs | 4 +- .../tests/output/bindgen_main.expected.rs | 10 +- 13 files changed, 1627 insertions(+), 1410 deletions(-) diff --git a/example/build.rs b/example/build.rs index 09899b4..1802c3e 100644 --- a/example/build.rs +++ b/example/build.rs @@ -1,8 +1,8 @@ use miette::{IntoDiagnostic, Result}; use wgsl_bindgen::qs::quote; use wgsl_bindgen::{ - GlamWgslTypeMap, Regex, WgslBindgenOptionBuilder, WgslShaderSourceType, - WgslTypeSerializeStrategy, + GlamWgslTypeMap, Regex, WgslBindgenOptionBuilder, WgslShaderIrCapabilities, + WgslShaderSourceType, WgslTypeSerializeStrategy, }; fn main() -> Result<()> { @@ -13,6 +13,7 @@ fn main() -> Result<()> { .skip_hash_check(true) .serialization_strategy(WgslTypeSerializeStrategy::Bytemuck) .type_map(GlamWgslTypeMap) + .ir_capabilities(WgslShaderIrCapabilities::PUSH_CONSTANT) .override_struct_field_type( [("utils::types::VectorsU32", "a", quote!(crate::MyTwoU32))].map(Into::into), ) diff --git a/example/shaders/triangle.wgsl b/example/shaders/triangle.wgsl index f1d5f2a..5a6fc9d 100644 --- a/example/shaders/triangle.wgsl +++ b/example/shaders/triangle.wgsl @@ -31,6 +31,12 @@ fn vs_main(in: VertexInput) -> VertexOutput { return out; } +struct PushConstants { + color_matrix: mat4x4 +} + +var constants: PushConstants; + // wgsl outputs with pipeline constants are not supported. // https://github.com/gfx-rs/wgpu/blob/abba12ae4e5488b08d9e189fc37dab5e1755b443/naga/src/back/wgsl/writer.rs#L108-L113 // override force_black: bool; @@ -44,5 +50,5 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { // } else { // return vec4(color * uniforms.color_rgb.rgb * scale, 1.0); // } - return vec4(color * uniforms.color_rgb.rgb, 1.0); + return constants.color_matrix * vec4(color * uniforms.color_rgb.rgb, 1.0); } diff --git a/example/src/main.rs b/example/src/main.rs index 59d4717..ccf57b7 100644 --- a/example/src/main.rs +++ b/example/src/main.rs @@ -57,8 +57,13 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - required_features: wgpu::Features::TEXTURE_COMPRESSION_BC, - required_limits: wgpu::Limits::default(), + required_features: wgpu::Features::TEXTURE_COMPRESSION_BC + | wgpu::Features::PUSH_CONSTANTS, + required_limits: wgpu::Limits { + max_push_constant_size: 128, + ..Default::default() + }, + memory_hints: Default::default(), }, None, ) @@ -99,6 +104,7 @@ impl State { depth_stencil: None, multisample: wgpu::MultisampleState::default(), multiview: None, + cache: Default::default(), }); // Create a gradient texture. @@ -242,6 +248,17 @@ impl State { render_pass.set_pipeline(&self.pipeline); + // Push constant data also needs to follow alignment rules. + let push_constant = shader_bindings::triangle::PushConstants { + color_matrix: glam::Mat4::IDENTITY, + }; + + render_pass.set_push_constants( + wgpu::ShaderStages::VERTEX_FRAGMENT, + 0, + &bytemuck::cast_slice(&[push_constant]), + ); + // Use this function to ensure all bind groups are set. self.bind_group0.set(&mut render_pass); self.bind_group1.set(&mut render_pass); diff --git a/example/src/shader_bindings.rs b/example/src/shader_bindings.rs index 4b4ecaa..0bc9906 100644 --- a/example/src/shader_bindings.rs +++ b/example/src/shader_bindings.rs @@ -2,918 +2,962 @@ // // ^ wgsl_bindgen version 0.14.1 // Changes made to this file will not be saved. -// SourceHash: 6017586cd84fa513a8e92bda218ca1f7b6cf9de5fa8c4fd92c2206e287dc1dfa +// SourceHash: 2e4d8dfdf37cba7f605dc2ce5725070d16973fab7816cffda62741732eed0dff #![allow(unused, non_snake_case, non_camel_case_types, non_upper_case_globals)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum ShaderEntry { - Testbed, - Triangle, + Testbed, + Triangle, } impl ShaderEntry { - pub fn create_pipeline_layout(&self, device: &wgpu::Device) -> wgpu::PipelineLayout { - match self { - Self::Testbed => testbed::create_pipeline_layout(device), - Self::Triangle => triangle::create_pipeline_layout(device), - } - } - pub fn create_shader_module_embed_source( - &self, - device: &wgpu::Device, - ) -> wgpu::ShaderModule { - match self { - Self::Testbed => testbed::create_shader_module_embed_source(device), - Self::Triangle => triangle::create_shader_module_embed_source(device), - } - } - pub fn create_shader_module_embedded( - &self, - device: &wgpu::Device, - shader_defs: std::collections::HashMap, - ) -> wgpu::ShaderModule { - match self { - Self::Testbed => testbed::create_shader_module_embedded(device, shader_defs), - Self::Triangle => triangle::create_shader_module_embedded(device, shader_defs), - } - } - pub fn create_shader_module_from_path( - &self, - device: &wgpu::Device, - shader_defs: std::collections::HashMap, - ) -> Result { - match self { - Self::Testbed => testbed::create_shader_module_from_path(device, shader_defs), - Self::Triangle => triangle::create_shader_module_from_path(device, shader_defs), - } - } - pub fn shader_entry_filename(&self) -> &'static str { - match self { - Self::Testbed => "testbed.wgsl", - Self::Triangle => "triangle.wgsl", - } - } - pub fn shader_paths(&self) -> &[&str] { - match self { - Self::Testbed => testbed::SHADER_PATHS, - Self::Triangle => triangle::SHADER_PATHS, - } - } + pub fn create_pipeline_layout(&self, device: &wgpu::Device) -> wgpu::PipelineLayout { + match self { + Self::Testbed => testbed::create_pipeline_layout(device), + Self::Triangle => triangle::create_pipeline_layout(device), + } + } + pub fn create_shader_module_embed_source( + &self, + device: &wgpu::Device, + ) -> wgpu::ShaderModule { + match self { + Self::Testbed => testbed::create_shader_module_embed_source(device), + Self::Triangle => triangle::create_shader_module_embed_source(device), + } + } + pub fn create_shader_module_embedded( + &self, + device: &wgpu::Device, + shader_defs: std::collections::HashMap, + ) -> wgpu::ShaderModule { + match self { + Self::Testbed => testbed::create_shader_module_embedded(device, shader_defs), + Self::Triangle => { + triangle::create_shader_module_embedded(device, shader_defs) + } + } + } + pub fn create_shader_module_from_path( + &self, + device: &wgpu::Device, + shader_defs: std::collections::HashMap, + ) -> Result { + match self { + Self::Testbed => testbed::create_shader_module_from_path(device, shader_defs), + Self::Triangle => { + triangle::create_shader_module_from_path(device, shader_defs) + } + } + } + pub fn shader_entry_filename(&self) -> &'static str { + match self { + Self::Testbed => "testbed.wgsl", + Self::Triangle => "triangle.wgsl", + } + } + pub fn shader_paths(&self) -> &[&str] { + match self { + Self::Testbed => testbed::SHADER_PATHS, + Self::Triangle => triangle::SHADER_PATHS, + } + } } mod _root { - pub use super::*; + pub use super::*; } pub mod layout_asserts { - use super::_root; - use super::_root::*; - const WGSL_BASE_TYPE_ASSERTS: () = { - assert!(std::mem::size_of::() == 16); - assert!(std::mem::align_of::() == 16); - assert!(std::mem::size_of::() == 16); - assert!(std::mem::align_of::() == 16); - assert!(std::mem::size_of::() == 48); - assert!(std::mem::align_of::() == 16); - assert!(std::mem::size_of::() == 64); - assert!(std::mem::align_of::() == 16); - }; - const UTILSTYPES_VECTORS_U32_ASSERTS: () = { - assert!(std::mem::offset_of!(utils::types::VectorsU32, a) == 0); - assert!(std::mem::offset_of!(utils::types::VectorsU32, b) == 16); - assert!(std::mem::offset_of!(utils::types::VectorsU32, c) == 32); - assert!(std::mem::size_of::() == 64); - }; - const UTILSTYPES_VECTORS_I32_ASSERTS: () = { - assert!(std::mem::offset_of!(utils::types::VectorsI32, a) == 0); - assert!(std::mem::offset_of!(utils::types::VectorsI32, b) == 16); - assert!(std::mem::offset_of!(utils::types::VectorsI32, c) == 32); - assert!(std::mem::size_of::() == 48); - }; - const UTILSTYPES_VECTORS_F32_ASSERTS: () = { - assert!(std::mem::offset_of!(utils::types::VectorsF32, a) == 0); - assert!(std::mem::offset_of!(utils::types::VectorsF32, b) == 16); - assert!(std::mem::offset_of!(utils::types::VectorsF32, c) == 32); - assert!(std::mem::size_of::() == 48); - }; - const UTILSTYPES_MATRICES_F32_ASSERTS: () = { - assert!(std::mem::offset_of!(utils::types::MatricesF32, a) == 0); - assert!(std::mem::offset_of!(utils::types::MatricesF32, b) == 64); - assert!(std::mem::offset_of!(utils::types::MatricesF32, c) == 128); - assert!(std::mem::offset_of!(utils::types::MatricesF32, d) == 160); - assert!(std::mem::offset_of!(utils::types::MatricesF32, e) == 208); - assert!(std::mem::offset_of!(utils::types::MatricesF32, f) == 256); - assert!(std::mem::offset_of!(utils::types::MatricesF32, g) == 288); - assert!(std::mem::offset_of!(utils::types::MatricesF32, h) == 320); - assert!(std::mem::offset_of!(utils::types::MatricesF32, i) == 352); - assert!(std::mem::size_of::() == 368); - }; - const UTILSTYPES_STATIC_ARRAYS_ASSERTS: () = { - assert!(std::mem::offset_of!(utils::types::StaticArrays, a) == 0); - assert!(std::mem::offset_of!(utils::types::StaticArrays, b) == 20); - assert!(std::mem::offset_of!(utils::types::StaticArrays, c) == 32); - assert!(std::mem::offset_of!(utils::types::StaticArrays, d) == 32800); - assert!(std::mem::size_of::() == 32864); - }; - const UTILSTYPES_NESTED_ASSERTS: () = { - assert!(std::mem::offset_of!(utils::types::Nested, a) == 0); - assert!(std::mem::offset_of!(utils::types::Nested, b) == 368); - assert!(std::mem::size_of::() == 416); - }; - const TESTBED_UNIFORMS_ASSERTS: () = { - assert!(std::mem::offset_of!(testbed::Uniforms, color_rgb) == 0); - assert!(std::mem::offset_of!(testbed::Uniforms, scalars) == 16); - assert!(std::mem::size_of::() == 32); - }; - const TRIANGLE_UNIFORMS_ASSERTS: () = { - assert!(std::mem::offset_of!(triangle::Uniforms, color_rgb) == 0); - assert!(std::mem::size_of::() == 16); - }; + use super::{_root, _root::*}; + const WGSL_BASE_TYPE_ASSERTS: () = { + assert!(std::mem::size_of:: < glam::Vec3A > () == 16); + assert!(std::mem::align_of:: < glam::Vec3A > () == 16); + assert!(std::mem::size_of:: < glam::Vec4 > () == 16); + assert!(std::mem::align_of:: < glam::Vec4 > () == 16); + assert!(std::mem::size_of:: < glam::Mat3A > () == 48); + assert!(std::mem::align_of:: < glam::Mat3A > () == 16); + assert!(std::mem::size_of:: < glam::Mat4 > () == 64); + assert!(std::mem::align_of:: < glam::Mat4 > () == 16); + }; + const UTILSTYPES_VECTORS_U32_ASSERTS: () = { + assert!(std::mem::offset_of!(utils::types::VectorsU32, a) == 0); + assert!(std::mem::offset_of!(utils::types::VectorsU32, b) == 16); + assert!(std::mem::offset_of!(utils::types::VectorsU32, c) == 32); + assert!(std::mem::size_of:: < utils::types::VectorsU32 > () == 64); + }; + const UTILSTYPES_VECTORS_I32_ASSERTS: () = { + assert!(std::mem::offset_of!(utils::types::VectorsI32, a) == 0); + assert!(std::mem::offset_of!(utils::types::VectorsI32, b) == 16); + assert!(std::mem::offset_of!(utils::types::VectorsI32, c) == 32); + assert!(std::mem::size_of:: < utils::types::VectorsI32 > () == 48); + }; + const UTILSTYPES_VECTORS_F32_ASSERTS: () = { + assert!(std::mem::offset_of!(utils::types::VectorsF32, a) == 0); + assert!(std::mem::offset_of!(utils::types::VectorsF32, b) == 16); + assert!(std::mem::offset_of!(utils::types::VectorsF32, c) == 32); + assert!(std::mem::size_of:: < utils::types::VectorsF32 > () == 48); + }; + const UTILSTYPES_MATRICES_F32_ASSERTS: () = { + assert!(std::mem::offset_of!(utils::types::MatricesF32, a) == 0); + assert!(std::mem::offset_of!(utils::types::MatricesF32, b) == 64); + assert!(std::mem::offset_of!(utils::types::MatricesF32, c) == 128); + assert!(std::mem::offset_of!(utils::types::MatricesF32, d) == 160); + assert!(std::mem::offset_of!(utils::types::MatricesF32, e) == 208); + assert!(std::mem::offset_of!(utils::types::MatricesF32, f) == 256); + assert!(std::mem::offset_of!(utils::types::MatricesF32, g) == 288); + assert!(std::mem::offset_of!(utils::types::MatricesF32, h) == 320); + assert!(std::mem::offset_of!(utils::types::MatricesF32, i) == 352); + assert!(std::mem::size_of:: < utils::types::MatricesF32 > () == 368); + }; + const UTILSTYPES_STATIC_ARRAYS_ASSERTS: () = { + assert!(std::mem::offset_of!(utils::types::StaticArrays, a) == 0); + assert!(std::mem::offset_of!(utils::types::StaticArrays, b) == 20); + assert!(std::mem::offset_of!(utils::types::StaticArrays, c) == 32); + assert!(std::mem::offset_of!(utils::types::StaticArrays, d) == 32800); + assert!(std::mem::size_of:: < utils::types::StaticArrays > () == 32864); + }; + const UTILSTYPES_NESTED_ASSERTS: () = { + assert!(std::mem::offset_of!(utils::types::Nested, a) == 0); + assert!(std::mem::offset_of!(utils::types::Nested, b) == 368); + assert!(std::mem::size_of:: < utils::types::Nested > () == 416); + }; + const TESTBED_UNIFORMS_ASSERTS: () = { + assert!(std::mem::offset_of!(testbed::Uniforms, color_rgb) == 0); + assert!(std::mem::offset_of!(testbed::Uniforms, scalars) == 16); + assert!(std::mem::size_of:: < testbed::Uniforms > () == 32); + }; + const TRIANGLE_UNIFORMS_ASSERTS: () = { + assert!(std::mem::offset_of!(triangle::Uniforms, color_rgb) == 0); + assert!(std::mem::size_of:: < triangle::Uniforms > () == 16); + }; + const TRIANGLE_PUSH_CONSTANTS_ASSERTS: () = { + assert!(std::mem::offset_of!(triangle::PushConstants, color_matrix) == 0); + assert!(std::mem::size_of:: < triangle::PushConstants > () == 64); + }; } pub mod utils { - use super::_root; - use super::_root::*; - pub mod types { - use super::_root; - use super::_root::*; - #[repr(C, align(16))] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct VectorsU32 { - /// size: 8, offset: 0x0, type: `vec2` - pub a: crate::MyTwoU32, - pub _pad_a: [u8; 0x10 - core::mem::size_of::<[u32; 2]>()], - /// size: 12, offset: 0x10, type: `vec3` - pub b: [u32; 4], - /// size: 16, offset: 0x20, type: `vec4` - pub c: [u32; 4], - pub _padding: [u8; 0x4], - pub _pad__padding: [u8; 0x10 - core::mem::size_of::()], - } - impl VectorsU32 { - pub const fn new(a: crate::MyTwoU32, b: [u32; 4], c: [u32; 4]) -> Self { - Self { - a, - _pad_a: [0; 0x10 - core::mem::size_of::<[u32; 2]>()], - b, - c, - _padding: [0; 0x4], - _pad__padding: [0; 0x10 - core::mem::size_of::()], - } - } - } - #[repr(C)] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct VectorsU32Init { - pub a: crate::MyTwoU32, - pub b: [u32; 4], - pub c: [u32; 4], - } - impl VectorsU32Init { - pub const fn build(&self) -> VectorsU32 { - VectorsU32 { - a: self.a, - _pad_a: [0; 0x10 - core::mem::size_of::<[u32; 2]>()], - b: self.b, - c: self.c, - _padding: [0; 0x4], - _pad__padding: [0; 0x10 - core::mem::size_of::()], - } - } - } - impl From for VectorsU32 { - fn from(data: VectorsU32Init) -> Self { - data.build() - } + use super::{_root, _root::*}; + pub mod types { + use super::{_root, _root::*}; + #[repr(C, align(16))] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct VectorsU32 { + /// size: 8, offset: 0x0, type: `vec2` + pub a: crate::MyTwoU32, + pub _pad_a: [u8; 0x10 - core::mem::size_of::<[u32; 2]>()], + /// size: 12, offset: 0x10, type: `vec3` + pub b: [u32; 4], + /// size: 16, offset: 0x20, type: `vec4` + pub c: [u32; 4], + pub _padding: [u8; 0x4], + pub _pad__padding: [u8; 0x10 - core::mem::size_of::()], + } + impl VectorsU32 { + pub const fn new(a: crate::MyTwoU32, b: [u32; 4], c: [u32; 4]) -> Self { + Self { + a, + _pad_a: [0; 0x10 - core::mem::size_of::<[u32; 2]>()], + b, + c, + _padding: [0; 0x4], + _pad__padding: [0; 0x10 - core::mem::size_of::()], + } + } + } + #[repr(C)] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct VectorsU32Init { + pub a: crate::MyTwoU32, + pub b: [u32; 4], + pub c: [u32; 4], + } + impl VectorsU32Init { + pub const fn build(&self) -> VectorsU32 { + VectorsU32 { + a: self.a, + _pad_a: [0; 0x10 - core::mem::size_of::<[u32; 2]>()], + b: self.b, + c: self.c, + _padding: [0; 0x4], + _pad__padding: [0; 0x10 - core::mem::size_of::()], + } + } + } + impl From for VectorsU32 { + fn from(data: VectorsU32Init) -> Self { + data.build() + } + } + #[repr(C, align(16))] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct VectorsI32 { + /// size: 8, offset: 0x0, type: `vec2` + pub a: [i32; 2], + pub _pad_a: [u8; 0x10 - core::mem::size_of::<[i32; 2]>()], + /// size: 12, offset: 0x10, type: `vec3` + pub b: [i32; 4], + /// size: 16, offset: 0x20, type: `vec4` + pub c: [i32; 4], + } + impl VectorsI32 { + pub const fn new(a: [i32; 2], b: [i32; 4], c: [i32; 4]) -> Self { + Self { + a, + _pad_a: [0; 0x10 - core::mem::size_of::<[i32; 2]>()], + b, + c, + } + } + } + #[repr(C)] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct VectorsI32Init { + pub a: [i32; 2], + pub b: [i32; 4], + pub c: [i32; 4], + } + impl VectorsI32Init { + pub const fn build(&self) -> VectorsI32 { + VectorsI32 { + a: self.a, + _pad_a: [0; 0x10 - core::mem::size_of::<[i32; 2]>()], + b: self.b, + c: self.c, + } + } + } + impl From for VectorsI32 { + fn from(data: VectorsI32Init) -> Self { + data.build() + } + } + #[repr(C, align(16))] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct VectorsF32 { + /// size: 8, offset: 0x0, type: `vec2` + pub a: [f32; 2], + pub _pad_a: [u8; 0x10 - core::mem::size_of::<[f32; 2]>()], + /// size: 12, offset: 0x10, type: `vec3` + pub b: glam::Vec3A, + /// size: 16, offset: 0x20, type: `vec4` + pub c: glam::Vec4, + } + impl VectorsF32 { + pub const fn new(a: [f32; 2], b: glam::Vec3A, c: glam::Vec4) -> Self { + Self { + a, + _pad_a: [0; 0x10 - core::mem::size_of::<[f32; 2]>()], + b, + c, + } + } + } + #[repr(C)] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct VectorsF32Init { + pub a: [f32; 2], + pub b: glam::Vec3A, + pub c: glam::Vec4, + } + impl VectorsF32Init { + pub const fn build(&self) -> VectorsF32 { + VectorsF32 { + a: self.a, + _pad_a: [0; 0x10 - core::mem::size_of::<[f32; 2]>()], + b: self.b, + c: self.c, + } + } + } + impl From for VectorsF32 { + fn from(data: VectorsF32Init) -> Self { + data.build() + } + } + #[repr(C, align(16))] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct MatricesF32 { + /// size: 64, offset: 0x0, type: `mat4x4` + pub a: glam::Mat4, + /// size: 64, offset: 0x40, type: `mat4x3` + pub b: [[f32; 4]; 4], + /// size: 32, offset: 0x80, type: `mat4x2` + pub c: [[f32; 2]; 4], + /// size: 48, offset: 0xA0, type: `mat3x4` + pub d: [[f32; 4]; 3], + /// size: 48, offset: 0xD0, type: `mat3x3` + pub e: glam::Mat3A, + /// size: 24, offset: 0x100, type: `mat3x2` + pub f: [[f32; 2]; 3], + pub _pad_f: [u8; 0x20 - core::mem::size_of::<[[f32; 2]; 3]>()], + /// size: 32, offset: 0x120, type: `mat2x4` + pub g: [[f32; 4]; 2], + /// size: 32, offset: 0x140, type: `mat2x3` + pub h: [[f32; 4]; 2], + /// size: 16, offset: 0x160, type: `mat2x2` + pub i: [[f32; 2]; 2], + } + impl MatricesF32 { + pub const fn new( + a: glam::Mat4, + b: [[f32; 4]; 4], + c: [[f32; 2]; 4], + d: [[f32; 4]; 3], + e: glam::Mat3A, + f: [[f32; 2]; 3], + g: [[f32; 4]; 2], + h: [[f32; 4]; 2], + i: [[f32; 2]; 2], + ) -> Self { + Self { + a, + b, + c, + d, + e, + f, + _pad_f: [0; 0x20 - core::mem::size_of::<[[f32; 2]; 3]>()], + g, + h, + i, + } + } + } + #[repr(C)] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct MatricesF32Init { + pub a: glam::Mat4, + pub b: [[f32; 4]; 4], + pub c: [[f32; 2]; 4], + pub d: [[f32; 4]; 3], + pub e: glam::Mat3A, + pub f: [[f32; 2]; 3], + pub g: [[f32; 4]; 2], + pub h: [[f32; 4]; 2], + pub i: [[f32; 2]; 2], + } + impl MatricesF32Init { + pub const fn build(&self) -> MatricesF32 { + MatricesF32 { + a: self.a, + b: self.b, + c: self.c, + d: self.d, + e: self.e, + f: self.f, + _pad_f: [0; 0x20 - core::mem::size_of::<[[f32; 2]; 3]>()], + g: self.g, + h: self.h, + i: self.i, + } + } + } + impl From for MatricesF32 { + fn from(data: MatricesF32Init) -> Self { + data.build() + } + } + #[repr(C, align(16))] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct StaticArrays { + /// size: 20, offset: 0x0, type: `array` + pub a: [u32; 5], + pub _pad_a: [u8; 0x14 - core::mem::size_of::<[u32; 5]>()], + /// size: 12, offset: 0x14, type: `array` + pub b: [f32; 3], + pub _pad_b: [u8; 0xC - core::mem::size_of::<[f32; 3]>()], + /// size: 32768, offset: 0x20, type: `array, 512>` + pub c: [glam::Mat4; 512], + pub _pad_c: [u8; 0x8000 - core::mem::size_of::<[glam::Mat4; 512]>()], + /// size: 64, offset: 0x8020, type: `array, 4>` + pub d: [glam::Vec3A; 4], + pub _pad_d: [u8; 0x40 - core::mem::size_of::<[glam::Vec3A; 4]>()], + } + impl StaticArrays { + pub const fn new( + a: [u32; 5], + b: [f32; 3], + c: [glam::Mat4; 512], + d: [glam::Vec3A; 4], + ) -> Self { + Self { + a, + _pad_a: [0; 0x14 - core::mem::size_of::<[u32; 5]>()], + b, + _pad_b: [0; 0xC - core::mem::size_of::<[f32; 3]>()], + c, + _pad_c: [0; 0x8000 - core::mem::size_of::<[glam::Mat4; 512]>()], + d, + _pad_d: [0; 0x40 - core::mem::size_of::<[glam::Vec3A; 4]>()], + } + } + } + #[repr(C)] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct StaticArraysInit { + pub a: [u32; 5], + pub b: [f32; 3], + pub c: [glam::Mat4; 512], + pub d: [glam::Vec3A; 4], + } + impl StaticArraysInit { + pub const fn build(&self) -> StaticArrays { + StaticArrays { + a: self.a, + _pad_a: [0; 0x14 - core::mem::size_of::<[u32; 5]>()], + b: self.b, + _pad_b: [0; 0xC - core::mem::size_of::<[f32; 3]>()], + c: self.c, + _pad_c: [0; 0x8000 - core::mem::size_of::<[glam::Mat4; 512]>()], + d: self.d, + _pad_d: [0; 0x40 - core::mem::size_of::<[glam::Vec3A; 4]>()], + } + } + } + impl From for StaticArrays { + fn from(data: StaticArraysInit) -> Self { + data.build() + } + } + #[repr(C, align(16))] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct Nested { + /// size: 368, offset: 0x0, type: `struct` + pub a: _root::utils::types::MatricesF32, + /// size: 48, offset: 0x170, type: `struct` + pub b: _root::utils::types::VectorsF32, + } + pub const fn Nested( + a: _root::utils::types::MatricesF32, + b: _root::utils::types::VectorsF32, + ) -> Nested { + Nested { a, b } + } + #[repr(C)] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct VertexIn { + pub position: glam::Vec4, + } + pub const fn VertexIn(position: glam::Vec4) -> VertexIn { + VertexIn { position } + } + impl VertexIn { + pub const VERTEX_ATTRIBUTES: [wgpu::VertexAttribute; 1] = [ + wgpu::VertexAttribute { + format: wgpu::VertexFormat::Float32x4, + offset: std::mem::offset_of!(Self, position) as u64, + shader_location: 0, + }, + ]; + pub const fn vertex_buffer_layout( + step_mode: wgpu::VertexStepMode, + ) -> wgpu::VertexBufferLayout<'static> { + wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as u64, + step_mode, + attributes: &Self::VERTEX_ATTRIBUTES, + } + } + } } +} +pub mod bytemuck_impls { + use super::{_root, _root::*}; + unsafe impl bytemuck::Zeroable for utils::types::VectorsU32 {} + unsafe impl bytemuck::Pod for utils::types::VectorsU32 {} + unsafe impl bytemuck::Zeroable for utils::types::VectorsI32 {} + unsafe impl bytemuck::Pod for utils::types::VectorsI32 {} + unsafe impl bytemuck::Zeroable for utils::types::VectorsF32 {} + unsafe impl bytemuck::Pod for utils::types::VectorsF32 {} + unsafe impl bytemuck::Zeroable for utils::types::MatricesF32 {} + unsafe impl bytemuck::Pod for utils::types::MatricesF32 {} + unsafe impl bytemuck::Zeroable for utils::types::StaticArrays {} + unsafe impl bytemuck::Pod for utils::types::StaticArrays {} + unsafe impl bytemuck::Zeroable for utils::types::Nested {} + unsafe impl bytemuck::Pod for utils::types::Nested {} + unsafe impl bytemuck::Zeroable for utils::types::VertexIn {} + unsafe impl bytemuck::Pod for utils::types::VertexIn {} + unsafe impl bytemuck::Zeroable for testbed::Uniforms {} + unsafe impl bytemuck::Pod for testbed::Uniforms {} + unsafe impl bytemuck::Zeroable for triangle::Uniforms {} + unsafe impl bytemuck::Pod for triangle::Uniforms {} + unsafe impl bytemuck::Zeroable for triangle::VertexInput {} + unsafe impl bytemuck::Pod for triangle::VertexInput {} + unsafe impl bytemuck::Zeroable for triangle::PushConstants {} + unsafe impl bytemuck::Pod for triangle::PushConstants {} +} +pub mod testbed { + use super::{_root, _root::*}; #[repr(C, align(16))] #[derive(Debug, PartialEq, Clone, Copy)] - pub struct VectorsI32 { - /// size: 8, offset: 0x0, type: `vec2` - pub a: [i32; 2], - pub _pad_a: [u8; 0x10 - core::mem::size_of::<[i32; 2]>()], - /// size: 12, offset: 0x10, type: `vec3` - pub b: [i32; 4], - /// size: 16, offset: 0x20, type: `vec4` - pub c: [i32; 4], - } - impl VectorsI32 { - pub const fn new(a: [i32; 2], b: [i32; 4], c: [i32; 4]) -> Self { - Self { - a, - _pad_a: [0; 0x10 - core::mem::size_of::<[i32; 2]>()], - b, - c, - } - } + pub struct Uniforms { + /// size: 16, offset: 0x0, type: `vec4` + pub color_rgb: glam::Vec4, + /// size: 16, offset: 0x10, type: `struct` + pub scalars: crate::MyScalars, + } + pub const fn Uniforms(color_rgb: glam::Vec4, scalars: crate::MyScalars) -> Uniforms { + Uniforms { color_rgb, scalars } + } + #[derive(Debug)] + pub struct WgpuBindGroup0EntriesParams<'a> { + pub color_texture: &'a wgpu::TextureView, + pub color_sampler: &'a wgpu::Sampler, + } + #[derive(Clone, Debug)] + pub struct WgpuBindGroup0Entries<'a> { + pub color_texture: wgpu::BindGroupEntry<'a>, + pub color_sampler: wgpu::BindGroupEntry<'a>, + } + impl<'a> WgpuBindGroup0Entries<'a> { + pub fn new(params: WgpuBindGroup0EntriesParams<'a>) -> Self { + Self { + color_texture: wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(params.color_texture), + }, + color_sampler: wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(params.color_sampler), + }, + } + } + pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 2] { + [self.color_texture, self.color_sampler] + } + pub fn collect>>(self) -> B { + self.as_array().into_iter().collect() + } } - #[repr(C)] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct VectorsI32Init { - pub a: [i32; 2], - pub b: [i32; 4], - pub c: [i32; 4], - } - impl VectorsI32Init { - pub const fn build(&self) -> VectorsI32 { - VectorsI32 { - a: self.a, - _pad_a: [0; 0x10 - core::mem::size_of::<[i32; 2]>()], - b: self.b, - c: self.c, - } - } - } - impl From for VectorsI32 { - fn from(data: VectorsI32Init) -> Self { - data.build() - } + #[derive(Debug)] + pub struct WgpuBindGroup0(wgpu::BindGroup); + impl WgpuBindGroup0 { + pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = wgpu::BindGroupLayoutDescriptor { + label: Some("Testbed::BindGroup0::LayoutDescriptor"), + entries: &[ + /// @binding(0): "color_texture" + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { + filterable: true, + }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + /// @binding(1): "color_sampler" + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + ], + }; + pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) + } + pub fn from_bindings( + device: &wgpu::Device, + bindings: WgpuBindGroup0Entries, + ) -> Self { + let bind_group_layout = Self::get_bind_group_layout(&device); + let entries = bindings.as_array(); + let bind_group = device + .create_bind_group( + &wgpu::BindGroupDescriptor { + label: Some("Testbed::BindGroup0"), + layout: &bind_group_layout, + entries: &entries, + }, + ); + Self(bind_group) + } + pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { + render_pass.set_bind_group(0, &self.0, &[]); + } } - #[repr(C, align(16))] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct VectorsF32 { - /// size: 8, offset: 0x0, type: `vec2` - pub a: [f32; 2], - pub _pad_a: [u8; 0x10 - core::mem::size_of::<[f32; 2]>()], - /// size: 12, offset: 0x10, type: `vec3` - pub b: glam::Vec3A, - /// size: 16, offset: 0x20, type: `vec4` - pub c: glam::Vec4, - } - impl VectorsF32 { - pub const fn new(a: [f32; 2], b: glam::Vec3A, c: glam::Vec4) -> Self { - Self { - a, - _pad_a: [0; 0x10 - core::mem::size_of::<[f32; 2]>()], - b, - c, - } - } + #[derive(Debug)] + pub struct WgpuBindGroup1EntriesParams<'a> { + pub uniforms: wgpu::BufferBinding<'a>, + } + #[derive(Clone, Debug)] + pub struct WgpuBindGroup1Entries<'a> { + pub uniforms: wgpu::BindGroupEntry<'a>, + } + impl<'a> WgpuBindGroup1Entries<'a> { + pub fn new(params: WgpuBindGroup1EntriesParams<'a>) -> Self { + Self { + uniforms: wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(params.uniforms), + }, + } + } + pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 1] { + [self.uniforms] + } + pub fn collect>>(self) -> B { + self.as_array().into_iter().collect() + } } - #[repr(C)] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct VectorsF32Init { - pub a: [f32; 2], - pub b: glam::Vec3A, - pub c: glam::Vec4, - } - impl VectorsF32Init { - pub const fn build(&self) -> VectorsF32 { - VectorsF32 { - a: self.a, - _pad_a: [0; 0x10 - core::mem::size_of::<[f32; 2]>()], - b: self.b, - c: self.c, - } - } - } - impl From for VectorsF32 { - fn from(data: VectorsF32Init) -> Self { - data.build() - } + #[derive(Debug)] + pub struct WgpuBindGroup1(wgpu::BindGroup); + impl WgpuBindGroup1 { + pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = wgpu::BindGroupLayoutDescriptor { + label: Some("Testbed::BindGroup1::LayoutDescriptor"), + entries: &[ + /// @binding(0): "uniforms" + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::<_root::testbed::Uniforms>() as _, + ), + }, + count: None, + }, + ], + }; + pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) + } + pub fn from_bindings( + device: &wgpu::Device, + bindings: WgpuBindGroup1Entries, + ) -> Self { + let bind_group_layout = Self::get_bind_group_layout(&device); + let entries = bindings.as_array(); + let bind_group = device + .create_bind_group( + &wgpu::BindGroupDescriptor { + label: Some("Testbed::BindGroup1"), + layout: &bind_group_layout, + entries: &entries, + }, + ); + Self(bind_group) + } + pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { + render_pass.set_bind_group(1, &self.0, &[]); + } } - #[repr(C, align(16))] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct MatricesF32 { - /// size: 64, offset: 0x0, type: `mat4x4` - pub a: glam::Mat4, - /// size: 64, offset: 0x40, type: `mat4x3` - pub b: [[f32; 4]; 4], - /// size: 32, offset: 0x80, type: `mat4x2` - pub c: [[f32; 2]; 4], - /// size: 48, offset: 0xA0, type: `mat3x4` - pub d: [[f32; 4]; 3], - /// size: 48, offset: 0xD0, type: `mat3x3` - pub e: glam::Mat3A, - /// size: 24, offset: 0x100, type: `mat3x2` - pub f: [[f32; 2]; 3], - pub _pad_f: [u8; 0x20 - core::mem::size_of::<[[f32; 2]; 3]>()], - /// size: 32, offset: 0x120, type: `mat2x4` - pub g: [[f32; 4]; 2], - /// size: 32, offset: 0x140, type: `mat2x3` - pub h: [[f32; 4]; 2], - /// size: 16, offset: 0x160, type: `mat2x2` - pub i: [[f32; 2]; 2], - } - impl MatricesF32 { - pub const fn new( - a: glam::Mat4, - b: [[f32; 4]; 4], - c: [[f32; 2]; 4], - d: [[f32; 4]; 3], - e: glam::Mat3A, - f: [[f32; 2]; 3], - g: [[f32; 4]; 2], - h: [[f32; 4]; 2], - i: [[f32; 2]; 2], - ) -> Self { - Self { - a, - b, - c, - d, - e, - f, - _pad_f: [0; 0x20 - core::mem::size_of::<[[f32; 2]; 3]>()], - g, - h, - i, - } - } + #[derive(Debug)] + pub struct WgpuBindGroup2EntriesParams<'a> { + pub a: wgpu::BufferBinding<'a>, + pub b: wgpu::BufferBinding<'a>, + pub c: wgpu::BufferBinding<'a>, + pub d: wgpu::BufferBinding<'a>, + pub f: wgpu::BufferBinding<'a>, + pub h: wgpu::BufferBinding<'a>, + pub i: wgpu::BufferBinding<'a>, + } + #[derive(Clone, Debug)] + pub struct WgpuBindGroup2Entries<'a> { + pub a: wgpu::BindGroupEntry<'a>, + pub b: wgpu::BindGroupEntry<'a>, + pub c: wgpu::BindGroupEntry<'a>, + pub d: wgpu::BindGroupEntry<'a>, + pub f: wgpu::BindGroupEntry<'a>, + pub h: wgpu::BindGroupEntry<'a>, + pub i: wgpu::BindGroupEntry<'a>, + } + impl<'a> WgpuBindGroup2Entries<'a> { + pub fn new(params: WgpuBindGroup2EntriesParams<'a>) -> Self { + Self { + a: wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::Buffer(params.a), + }, + b: wgpu::BindGroupEntry { + binding: 3, + resource: wgpu::BindingResource::Buffer(params.b), + }, + c: wgpu::BindGroupEntry { + binding: 4, + resource: wgpu::BindingResource::Buffer(params.c), + }, + d: wgpu::BindGroupEntry { + binding: 5, + resource: wgpu::BindingResource::Buffer(params.d), + }, + f: wgpu::BindGroupEntry { + binding: 6, + resource: wgpu::BindingResource::Buffer(params.f), + }, + h: wgpu::BindGroupEntry { + binding: 8, + resource: wgpu::BindingResource::Buffer(params.h), + }, + i: wgpu::BindGroupEntry { + binding: 9, + resource: wgpu::BindingResource::Buffer(params.i), + }, + } + } + pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 7] { + [self.a, self.b, self.c, self.d, self.f, self.h, self.i] + } + pub fn collect>>(self) -> B { + self.as_array().into_iter().collect() + } } - #[repr(C)] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct MatricesF32Init { - pub a: glam::Mat4, - pub b: [[f32; 4]; 4], - pub c: [[f32; 2]; 4], - pub d: [[f32; 4]; 3], - pub e: glam::Mat3A, - pub f: [[f32; 2]; 3], - pub g: [[f32; 4]; 2], - pub h: [[f32; 4]; 2], - pub i: [[f32; 2]; 2], - } - impl MatricesF32Init { - pub const fn build(&self) -> MatricesF32 { - MatricesF32 { - a: self.a, - b: self.b, - c: self.c, - d: self.d, - e: self.e, - f: self.f, - _pad_f: [0; 0x20 - core::mem::size_of::<[[f32; 2]; 3]>()], - g: self.g, - h: self.h, - i: self.i, - } - } - } - impl From for MatricesF32 { - fn from(data: MatricesF32Init) -> Self { - data.build() - } + #[derive(Debug)] + pub struct WgpuBindGroup2(wgpu::BindGroup); + impl WgpuBindGroup2 { + pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = wgpu::BindGroupLayoutDescriptor { + label: Some("Testbed::BindGroup2::LayoutDescriptor"), + entries: &[ + /// @binding(2): "a" + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { + read_only: true, + }, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::() as _, + ), + }, + count: None, + }, + /// @binding(3): "b" + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { + read_only: true, + }, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::<_root::utils::types::VectorsU32>() as _, + ), + }, + count: None, + }, + /// @binding(4): "c" + wgpu::BindGroupLayoutEntry { + binding: 4, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { + read_only: true, + }, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::<_root::utils::types::VectorsI32>() as _, + ), + }, + count: None, + }, + /// @binding(5): "d" + wgpu::BindGroupLayoutEntry { + binding: 5, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { + read_only: true, + }, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::<_root::utils::types::VectorsF32>() as _, + ), + }, + count: None, + }, + /// @binding(6): "f" + wgpu::BindGroupLayoutEntry { + binding: 6, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { + read_only: true, + }, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::<_root::utils::types::MatricesF32>() as _, + ), + }, + count: None, + }, + /// @binding(8): "h" + wgpu::BindGroupLayoutEntry { + binding: 8, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { + read_only: true, + }, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::<_root::utils::types::StaticArrays>() as _, + ), + }, + count: None, + }, + /// @binding(9): "i" + wgpu::BindGroupLayoutEntry { + binding: 9, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { + read_only: true, + }, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::<_root::utils::types::Nested>() as _, + ), + }, + count: None, + }, + ], + }; + pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) + } + pub fn from_bindings( + device: &wgpu::Device, + bindings: WgpuBindGroup2Entries, + ) -> Self { + let bind_group_layout = Self::get_bind_group_layout(&device); + let entries = bindings.as_array(); + let bind_group = device + .create_bind_group( + &wgpu::BindGroupDescriptor { + label: Some("Testbed::BindGroup2"), + layout: &bind_group_layout, + entries: &entries, + }, + ); + Self(bind_group) + } + pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { + render_pass.set_bind_group(2, &self.0, &[]); + } } - #[repr(C, align(16))] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct StaticArrays { - /// size: 20, offset: 0x0, type: `array` - pub a: [u32; 5], - pub _pad_a: [u8; 0x14 - core::mem::size_of::<[u32; 5]>()], - /// size: 12, offset: 0x14, type: `array` - pub b: [f32; 3], - pub _pad_b: [u8; 0xC - core::mem::size_of::<[f32; 3]>()], - /// size: 32768, offset: 0x20, type: `array, 512>` - pub c: [glam::Mat4; 512], - pub _pad_c: [u8; 0x8000 - core::mem::size_of::<[glam::Mat4; 512]>()], - /// size: 64, offset: 0x8020, type: `array, 4>` - pub d: [glam::Vec3A; 4], - pub _pad_d: [u8; 0x40 - core::mem::size_of::<[glam::Vec3A; 4]>()], - } - impl StaticArrays { - pub const fn new( - a: [u32; 5], - b: [f32; 3], - c: [glam::Mat4; 512], - d: [glam::Vec3A; 4], - ) -> Self { - Self { - a, - _pad_a: [0; 0x14 - core::mem::size_of::<[u32; 5]>()], - b, - _pad_b: [0; 0xC - core::mem::size_of::<[f32; 3]>()], - c, - _pad_c: [0; 0x8000 - core::mem::size_of::<[glam::Mat4; 512]>()], - d, - _pad_d: [0; 0x40 - core::mem::size_of::<[glam::Vec3A; 4]>()], - } - } + #[derive(Debug, Copy, Clone)] + pub struct WgpuBindGroups<'a> { + pub bind_group0: &'a WgpuBindGroup0, + pub bind_group1: &'a WgpuBindGroup1, + pub bind_group2: &'a WgpuBindGroup2, + } + impl<'a> WgpuBindGroups<'a> { + pub fn set(&self, pass: &mut wgpu::RenderPass<'a>) { + self.bind_group0.set(pass); + self.bind_group1.set(pass); + self.bind_group2.set(pass); + } } - #[repr(C)] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct StaticArraysInit { - pub a: [u32; 5], - pub b: [f32; 3], - pub c: [glam::Mat4; 512], - pub d: [glam::Vec3A; 4], - } - impl StaticArraysInit { - pub const fn build(&self) -> StaticArrays { - StaticArrays { - a: self.a, - _pad_a: [0; 0x14 - core::mem::size_of::<[u32; 5]>()], - b: self.b, - _pad_b: [0; 0xC - core::mem::size_of::<[f32; 3]>()], - c: self.c, - _pad_c: [0; 0x8000 - core::mem::size_of::<[glam::Mat4; 512]>()], - d: self.d, - _pad_d: [0; 0x40 - core::mem::size_of::<[glam::Vec3A; 4]>()], - } - } - } - impl From for StaticArrays { - fn from(data: StaticArraysInit) -> Self { - data.build() - } + pub fn set_bind_groups<'a>( + pass: &mut wgpu::RenderPass<'a>, + bind_group0: &'a WgpuBindGroup0, + bind_group1: &'a WgpuBindGroup1, + bind_group2: &'a WgpuBindGroup2, + ) { + bind_group0.set(pass); + bind_group1.set(pass); + bind_group2.set(pass); + } + pub const ENTRY_VERTEX_MAIN: &str = "vertex_main"; + pub const ENTRY_FRAGMENT_MAIN: &str = "fragment_main"; + #[derive(Debug)] + pub struct VertexEntry { + pub entry_point: &'static str, + pub buffers: [wgpu::VertexBufferLayout<'static>; N], + pub constants: std::collections::HashMap, + } + pub fn vertex_state<'a, const N: usize>( + module: &'a wgpu::ShaderModule, + entry: &'a VertexEntry, + ) -> wgpu::VertexState<'a> { + wgpu::VertexState { + module, + entry_point: entry.entry_point, + buffers: &entry.buffers, + compilation_options: wgpu::PipelineCompilationOptions { + constants: &entry.constants, + ..Default::default() + }, + } } - #[repr(C, align(16))] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct Nested { - /// size: 368, offset: 0x0, type: `struct` - pub a: _root::utils::types::MatricesF32, - /// size: 48, offset: 0x170, type: `struct` - pub b: _root::utils::types::VectorsF32, - } - pub const fn Nested( - a: _root::utils::types::MatricesF32, - b: _root::utils::types::VectorsF32, - ) -> Nested { - Nested { a, b } + pub fn vertex_main_entry(vertex_in: wgpu::VertexStepMode) -> VertexEntry<1> { + VertexEntry { + entry_point: ENTRY_VERTEX_MAIN, + buffers: [utils::types::VertexIn::vertex_buffer_layout(vertex_in)], + constants: Default::default(), + } } - #[repr(C)] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct VertexIn { - pub position: glam::Vec4, - } - pub const fn VertexIn(position: glam::Vec4) -> VertexIn { - VertexIn { position } - } - impl VertexIn { - pub const VERTEX_ATTRIBUTES: [wgpu::VertexAttribute; 1] = [wgpu::VertexAttribute { - format: wgpu::VertexFormat::Float32x4, - offset: std::mem::offset_of!(Self, position) as u64, - shader_location: 0, - }]; - pub const fn vertex_buffer_layout( - step_mode: wgpu::VertexStepMode, - ) -> wgpu::VertexBufferLayout<'static> { - wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::() as u64, - step_mode, - attributes: &Self::VERTEX_ATTRIBUTES, - } - } - } - } -} -pub mod bytemuck_impls { - use super::_root; - use super::_root::*; - unsafe impl bytemuck::Zeroable for utils::types::VectorsU32 {} - unsafe impl bytemuck::Pod for utils::types::VectorsU32 {} - unsafe impl bytemuck::Zeroable for utils::types::VectorsI32 {} - unsafe impl bytemuck::Pod for utils::types::VectorsI32 {} - unsafe impl bytemuck::Zeroable for utils::types::VectorsF32 {} - unsafe impl bytemuck::Pod for utils::types::VectorsF32 {} - unsafe impl bytemuck::Zeroable for utils::types::MatricesF32 {} - unsafe impl bytemuck::Pod for utils::types::MatricesF32 {} - unsafe impl bytemuck::Zeroable for utils::types::StaticArrays {} - unsafe impl bytemuck::Pod for utils::types::StaticArrays {} - unsafe impl bytemuck::Zeroable for utils::types::Nested {} - unsafe impl bytemuck::Pod for utils::types::Nested {} - unsafe impl bytemuck::Zeroable for utils::types::VertexIn {} - unsafe impl bytemuck::Pod for utils::types::VertexIn {} - unsafe impl bytemuck::Zeroable for testbed::Uniforms {} - unsafe impl bytemuck::Pod for testbed::Uniforms {} - unsafe impl bytemuck::Zeroable for triangle::Uniforms {} - unsafe impl bytemuck::Pod for triangle::Uniforms {} - unsafe impl bytemuck::Zeroable for triangle::VertexInput {} - unsafe impl bytemuck::Pod for triangle::VertexInput {} -} -pub mod testbed { - use super::_root; - use super::_root::*; - #[repr(C, align(16))] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct Uniforms { - /// size: 16, offset: 0x0, type: `vec4` - pub color_rgb: glam::Vec4, - /// size: 16, offset: 0x10, type: `struct` - pub scalars: crate::MyScalars, - } - pub const fn Uniforms(color_rgb: glam::Vec4, scalars: crate::MyScalars) -> Uniforms { - Uniforms { color_rgb, scalars } - } - #[derive(Debug)] - pub struct WgpuBindGroup0EntriesParams<'a> { - pub color_texture: &'a wgpu::TextureView, - pub color_sampler: &'a wgpu::Sampler, - } - #[derive(Clone, Debug)] - pub struct WgpuBindGroup0Entries<'a> { - pub color_texture: wgpu::BindGroupEntry<'a>, - pub color_sampler: wgpu::BindGroupEntry<'a>, - } - impl<'a> WgpuBindGroup0Entries<'a> { - pub fn new(params: WgpuBindGroup0EntriesParams<'a>) -> Self { - Self { - color_texture: wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(params.color_texture), - }, - color_sampler: wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(params.color_sampler), - }, - } - } - pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 2] { - [self.color_texture, self.color_sampler] - } - pub fn collect>>(self) -> B { - self.as_array().into_iter().collect() - } - } - #[derive(Debug)] - pub struct WgpuBindGroup0(wgpu::BindGroup); - impl WgpuBindGroup0 { - pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = - wgpu::BindGroupLayoutDescriptor { - label: Some("Testbed::BindGroup0::LayoutDescriptor"), - entries: &[ - /// @binding(0): "color_texture" - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - /// @binding(1): "color_sampler" - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - }; - pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) - } - pub fn from_bindings(device: &wgpu::Device, bindings: WgpuBindGroup0Entries) -> Self { - let bind_group_layout = Self::get_bind_group_layout(&device); - let entries = bindings.as_array(); - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("Testbed::BindGroup0"), - layout: &bind_group_layout, - entries: &entries, - }); - Self(bind_group) - } - pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { - render_pass.set_bind_group(0, &self.0, &[]); - } - } - #[derive(Debug)] - pub struct WgpuBindGroup1EntriesParams<'a> { - pub uniforms: wgpu::BufferBinding<'a>, - } - #[derive(Clone, Debug)] - pub struct WgpuBindGroup1Entries<'a> { - pub uniforms: wgpu::BindGroupEntry<'a>, - } - impl<'a> WgpuBindGroup1Entries<'a> { - pub fn new(params: WgpuBindGroup1EntriesParams<'a>) -> Self { - Self { - uniforms: wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(params.uniforms), - }, - } - } - pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 1] { - [self.uniforms] - } - pub fn collect>>(self) -> B { - self.as_array().into_iter().collect() - } - } - #[derive(Debug)] - pub struct WgpuBindGroup1(wgpu::BindGroup); - impl WgpuBindGroup1 { - pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = - wgpu::BindGroupLayoutDescriptor { - label: Some("Testbed::BindGroup1::LayoutDescriptor"), - entries: &[ - /// @binding(0): "uniforms" - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - _root::testbed::Uniforms, - >() as _), + #[derive(Debug)] + pub struct FragmentEntry { + pub entry_point: &'static str, + pub targets: [Option; N], + pub constants: std::collections::HashMap, + } + pub fn fragment_state<'a, const N: usize>( + module: &'a wgpu::ShaderModule, + entry: &'a FragmentEntry, + ) -> wgpu::FragmentState<'a> { + wgpu::FragmentState { + module, + entry_point: entry.entry_point, + targets: &entry.targets, + compilation_options: wgpu::PipelineCompilationOptions { + constants: &entry.constants, + ..Default::default() }, - count: None, - }, - ], - }; - pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) - } - pub fn from_bindings(device: &wgpu::Device, bindings: WgpuBindGroup1Entries) -> Self { - let bind_group_layout = Self::get_bind_group_layout(&device); - let entries = bindings.as_array(); - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("Testbed::BindGroup1"), - layout: &bind_group_layout, - entries: &entries, - }); - Self(bind_group) - } - pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { - render_pass.set_bind_group(1, &self.0, &[]); - } - } - #[derive(Debug)] - pub struct WgpuBindGroup2EntriesParams<'a> { - pub a: wgpu::BufferBinding<'a>, - pub b: wgpu::BufferBinding<'a>, - pub c: wgpu::BufferBinding<'a>, - pub d: wgpu::BufferBinding<'a>, - pub f: wgpu::BufferBinding<'a>, - pub h: wgpu::BufferBinding<'a>, - pub i: wgpu::BufferBinding<'a>, - } - #[derive(Clone, Debug)] - pub struct WgpuBindGroup2Entries<'a> { - pub a: wgpu::BindGroupEntry<'a>, - pub b: wgpu::BindGroupEntry<'a>, - pub c: wgpu::BindGroupEntry<'a>, - pub d: wgpu::BindGroupEntry<'a>, - pub f: wgpu::BindGroupEntry<'a>, - pub h: wgpu::BindGroupEntry<'a>, - pub i: wgpu::BindGroupEntry<'a>, - } - impl<'a> WgpuBindGroup2Entries<'a> { - pub fn new(params: WgpuBindGroup2EntriesParams<'a>) -> Self { - Self { - a: wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::Buffer(params.a), - }, - b: wgpu::BindGroupEntry { - binding: 3, - resource: wgpu::BindingResource::Buffer(params.b), - }, - c: wgpu::BindGroupEntry { - binding: 4, - resource: wgpu::BindingResource::Buffer(params.c), - }, - d: wgpu::BindGroupEntry { - binding: 5, - resource: wgpu::BindingResource::Buffer(params.d), - }, - f: wgpu::BindGroupEntry { - binding: 6, - resource: wgpu::BindingResource::Buffer(params.f), - }, - h: wgpu::BindGroupEntry { - binding: 8, - resource: wgpu::BindingResource::Buffer(params.h), - }, - i: wgpu::BindGroupEntry { - binding: 9, - resource: wgpu::BindingResource::Buffer(params.i), - }, - } - } - pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 7] { - [self.a, self.b, self.c, self.d, self.f, self.h, self.i] - } - pub fn collect>>(self) -> B { - self.as_array().into_iter().collect() - } - } - #[derive(Debug)] - pub struct WgpuBindGroup2(wgpu::BindGroup); - impl WgpuBindGroup2 { - pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = - wgpu::BindGroupLayoutDescriptor { - label: Some("Testbed::BindGroup2::LayoutDescriptor"), - entries: &[ - /// @binding(2): "a" - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - crate::MyScalars, - >() as _), - }, - count: None, - }, - /// @binding(3): "b" - wgpu::BindGroupLayoutEntry { - binding: 3, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - _root::utils::types::VectorsU32, - >() as _), - }, - count: None, - }, - /// @binding(4): "c" - wgpu::BindGroupLayoutEntry { - binding: 4, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - _root::utils::types::VectorsI32, - >() as _), - }, - count: None, - }, - /// @binding(5): "d" - wgpu::BindGroupLayoutEntry { - binding: 5, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - _root::utils::types::VectorsF32, - >() as _), - }, - count: None, - }, - /// @binding(6): "f" - wgpu::BindGroupLayoutEntry { - binding: 6, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - _root::utils::types::MatricesF32, - >() as _), - }, - count: None, - }, - /// @binding(8): "h" - wgpu::BindGroupLayoutEntry { - binding: 8, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - _root::utils::types::StaticArrays, - >() as _), - }, - count: None, - }, - /// @binding(9): "i" - wgpu::BindGroupLayoutEntry { - binding: 9, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - _root::utils::types::Nested, - >() as _), - }, - count: None, - }, - ], - }; - pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) - } - pub fn from_bindings(device: &wgpu::Device, bindings: WgpuBindGroup2Entries) -> Self { - let bind_group_layout = Self::get_bind_group_layout(&device); - let entries = bindings.as_array(); - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("Testbed::BindGroup2"), - layout: &bind_group_layout, - entries: &entries, - }); - Self(bind_group) - } - pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { - render_pass.set_bind_group(2, &self.0, &[]); - } - } - #[derive(Debug, Copy, Clone)] - pub struct WgpuBindGroups<'a> { - pub bind_group0: &'a WgpuBindGroup0, - pub bind_group1: &'a WgpuBindGroup1, - pub bind_group2: &'a WgpuBindGroup2, - } - impl<'a> WgpuBindGroups<'a> { - pub fn set(&self, pass: &mut wgpu::RenderPass<'a>) { - self.bind_group0.set(pass); - self.bind_group1.set(pass); - self.bind_group2.set(pass); - } - } - pub fn set_bind_groups<'a>( - pass: &mut wgpu::RenderPass<'a>, - bind_group0: &'a WgpuBindGroup0, - bind_group1: &'a WgpuBindGroup1, - bind_group2: &'a WgpuBindGroup2, - ) { - bind_group0.set(pass); - bind_group1.set(pass); - bind_group2.set(pass); - } - pub const ENTRY_VERTEX_MAIN: &str = "vertex_main"; - pub const ENTRY_FRAGMENT_MAIN: &str = "fragment_main"; - #[derive(Debug)] - pub struct VertexEntry { - pub entry_point: &'static str, - pub buffers: [wgpu::VertexBufferLayout<'static>; N], - pub constants: std::collections::HashMap, - } - pub fn vertex_state<'a, const N: usize>( - module: &'a wgpu::ShaderModule, - entry: &'a VertexEntry, - ) -> wgpu::VertexState<'a> { - wgpu::VertexState { - module, - entry_point: entry.entry_point, - buffers: &entry.buffers, - compilation_options: wgpu::PipelineCompilationOptions { - constants: &entry.constants, - ..Default::default() - }, - } - } - pub fn vertex_main_entry(vertex_in: wgpu::VertexStepMode) -> VertexEntry<1> { - VertexEntry { - entry_point: ENTRY_VERTEX_MAIN, - buffers: [utils::types::VertexIn::vertex_buffer_layout(vertex_in)], - constants: Default::default(), - } - } - #[derive(Debug)] - pub struct FragmentEntry { - pub entry_point: &'static str, - pub targets: [Option; N], - pub constants: std::collections::HashMap, - } - pub fn fragment_state<'a, const N: usize>( - module: &'a wgpu::ShaderModule, - entry: &'a FragmentEntry, - ) -> wgpu::FragmentState<'a> { - wgpu::FragmentState { - module, - entry_point: entry.entry_point, - targets: &entry.targets, - compilation_options: wgpu::PipelineCompilationOptions { - constants: &entry.constants, - ..Default::default() - }, - } - } - pub fn fragment_main_entry( - targets: [Option; 1], - ) -> FragmentEntry<1> { - FragmentEntry { - entry_point: ENTRY_FRAGMENT_MAIN, - targets, - constants: Default::default(), - } - } - #[derive(Debug)] - pub struct WgpuPipelineLayout; - impl WgpuPipelineLayout { - pub fn bind_group_layout_entries( - entries: [wgpu::BindGroupLayout; 3], - ) -> [wgpu::BindGroupLayout; 3] { - entries - } - } - pub fn create_pipeline_layout(device: &wgpu::Device) -> wgpu::PipelineLayout { - device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Testbed::PipelineLayout"), - bind_group_layouts: &[ - &WgpuBindGroup0::get_bind_group_layout(device), - &WgpuBindGroup1::get_bind_group_layout(device), - &WgpuBindGroup2::get_bind_group_layout(device), - ], - push_constant_ranges: &[], - }) - } - pub fn create_shader_module_embed_source(device: &wgpu::Device) -> wgpu::ShaderModule { - let source = std::borrow::Cow::Borrowed(SHADER_STRING); - device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("testbed.wgsl"), - source: wgpu::ShaderSource::Wgsl(source), - }) - } - pub const SHADER_STRING: &'static str = r#" + } + } + pub fn fragment_main_entry( + targets: [Option; 1], + ) -> FragmentEntry<1> { + FragmentEntry { + entry_point: ENTRY_FRAGMENT_MAIN, + targets, + constants: Default::default(), + } + } + #[derive(Debug)] + pub struct WgpuPipelineLayout; + impl WgpuPipelineLayout { + pub fn bind_group_layout_entries( + entries: [wgpu::BindGroupLayout; 3], + ) -> [wgpu::BindGroupLayout; 3] { + entries + } + } + pub fn create_pipeline_layout(device: &wgpu::Device) -> wgpu::PipelineLayout { + device + .create_pipeline_layout( + &wgpu::PipelineLayoutDescriptor { + label: Some("Testbed::PipelineLayout"), + bind_group_layouts: &[ + &WgpuBindGroup0::get_bind_group_layout(device), + &WgpuBindGroup1::get_bind_group_layout(device), + &WgpuBindGroup2::get_bind_group_layout(device), + ], + push_constant_ranges: &[], + }, + ) + } + pub fn create_shader_module_embed_source( + device: &wgpu::Device, + ) -> wgpu::ShaderModule { + let source = std::borrow::Cow::Borrowed(SHADER_STRING); + device + .create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("testbed.wgsl"), + source: wgpu::ShaderSource::Wgsl(source), + }) + } + pub const SHADER_STRING: &'static str = r#" struct ScalarsX_naga_oil_mod_XOV2GS3DTHI5HI6LQMVZQX { a: u32, b: i32, @@ -1012,391 +1056,442 @@ fn fragment_main(input_1: VertexOutput) -> @location(0) vec4 { return vec4(1f, 1f, 1f, 1f); } "#; - pub fn load_shader_modules_embedded( - composer: &mut naga_oil::compose::Composer, - shader_defs: &std::collections::HashMap, - ) -> () { - composer - .add_composable_module(naga_oil::compose::ComposableModuleDescriptor { - source: include_str!("../shaders/utils/types.wgsl"), - file_path: "../shaders/utils/types.wgsl", - language: naga_oil::compose::ShaderLanguage::Wgsl, - shader_defs: shader_defs.clone(), - as_name: Some("utils::types".into()), - ..Default::default() - }) - .expect("failed to add composer module"); - () - } - pub fn load_naga_module_embedded( - composer: &mut naga_oil::compose::Composer, - shader_defs: std::collections::HashMap, - ) -> wgpu::naga::Module { - composer - .make_naga_module(naga_oil::compose::NagaModuleDescriptor { - source: include_str!("../shaders/testbed.wgsl"), - file_path: "../shaders/testbed.wgsl", - shader_defs, - ..Default::default() - }) - .expect("failed to build naga module") - } - pub fn create_shader_module_embedded( - device: &wgpu::Device, - shader_defs: std::collections::HashMap, - ) -> wgpu::ShaderModule { - let mut composer = naga_oil::compose::Composer::default(); - load_shader_modules_embedded(&mut composer, &shader_defs); - let module = load_naga_module_embedded(&mut composer, shader_defs); - let info = wgpu::naga::valid::Validator::new( - wgpu::naga::valid::ValidationFlags::empty(), - wgpu::naga::valid::Capabilities::all(), - ) - .validate(&module) - .unwrap(); - let shader_string = wgpu::naga::back::wgsl::write_string( - &module, - &info, - wgpu::naga::back::wgsl::WriterFlags::empty(), - ) - .expect("failed to convert naga module to source"); - let source = std::borrow::Cow::Owned(shader_string); - device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("testbed.wgsl"), - source: wgpu::ShaderSource::Wgsl(source), - }) - } - pub const SHADER_ENTRY_PATH: &str = - include_absolute_path::include_absolute_path!("../shaders/testbed.wgsl"); - pub const UTILS_TYPES_PATH: &str = - include_absolute_path::include_absolute_path!("../shaders/utils/types.wgsl"); - pub const SHADER_PATHS: &[&str] = &[SHADER_ENTRY_PATH, UTILS_TYPES_PATH]; - pub fn load_shader_modules_from_path( - composer: &mut naga_oil::compose::Composer, - shader_defs: &std::collections::HashMap, - ) -> Result<(), naga_oil::compose::ComposerError> { - composer.add_composable_module(naga_oil::compose::ComposableModuleDescriptor { - source: &std::fs::read_to_string(UTILS_TYPES_PATH).unwrap(), - file_path: "../shaders/utils/types.wgsl", - language: naga_oil::compose::ShaderLanguage::Wgsl, - shader_defs: shader_defs.clone(), - as_name: Some("utils::types".into()), - ..Default::default() - })?; - Ok(()) - } - pub fn load_naga_module_from_path( - composer: &mut naga_oil::compose::Composer, - shader_defs: std::collections::HashMap, - ) -> Result { - composer.make_naga_module(naga_oil::compose::NagaModuleDescriptor { - source: &std::fs::read_to_string(SHADER_ENTRY_PATH).unwrap(), - file_path: "../shaders/testbed.wgsl", - shader_defs, - ..Default::default() - }) - } - pub fn create_shader_module_from_path( - device: &wgpu::Device, - shader_defs: std::collections::HashMap, - ) -> Result { - let mut composer = naga_oil::compose::Composer::default(); - load_shader_modules_from_path(&mut composer, &shader_defs)?; - let module = load_naga_module_from_path(&mut composer, shader_defs)?; - let info = wgpu::naga::valid::Validator::new( - wgpu::naga::valid::ValidationFlags::empty(), - wgpu::naga::valid::Capabilities::all(), - ) - .validate(&module) - .unwrap(); - let shader_string = wgpu::naga::back::wgsl::write_string( - &module, - &info, - wgpu::naga::back::wgsl::WriterFlags::empty(), - ) - .expect("failed to convert naga module to source"); - let source = std::borrow::Cow::Owned(shader_string); - Ok(device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("testbed.wgsl"), - source: wgpu::ShaderSource::Wgsl(source), - })) - } + pub fn load_shader_modules_embedded( + composer: &mut naga_oil::compose::Composer, + shader_defs: &std::collections::HashMap< + String, + naga_oil::compose::ShaderDefValue, + >, + ) -> () { + composer + .add_composable_module(naga_oil::compose::ComposableModuleDescriptor { + source: include_str!("../shaders/utils/types.wgsl"), + file_path: "../shaders/utils/types.wgsl", + language: naga_oil::compose::ShaderLanguage::Wgsl, + shader_defs: shader_defs.clone(), + as_name: Some("utils::types".into()), + ..Default::default() + }) + .expect("failed to add composer module"); + () + } + pub fn load_naga_module_embedded( + composer: &mut naga_oil::compose::Composer, + shader_defs: std::collections::HashMap, + ) -> wgpu::naga::Module { + composer + .make_naga_module(naga_oil::compose::NagaModuleDescriptor { + source: include_str!("../shaders/testbed.wgsl"), + file_path: "../shaders/testbed.wgsl", + shader_defs, + ..Default::default() + }) + .expect("failed to build naga module") + } + pub fn create_shader_module_embedded( + device: &wgpu::Device, + shader_defs: std::collections::HashMap, + ) -> wgpu::ShaderModule { + let mut composer = naga_oil::compose::Composer::default() + .with_capabilities(wgpu::naga::valid::Capabilities::from_bits_retain(1)); + load_shader_modules_embedded(&mut composer, &shader_defs); + let module = load_naga_module_embedded(&mut composer, shader_defs); + let info = wgpu::naga::valid::Validator::new( + wgpu::naga::valid::ValidationFlags::empty(), + wgpu::naga::valid::Capabilities::all(), + ) + .validate(&module) + .unwrap(); + let shader_string = wgpu::naga::back::wgsl::write_string( + &module, + &info, + wgpu::naga::back::wgsl::WriterFlags::empty(), + ) + .expect("failed to convert naga module to source"); + let source = std::borrow::Cow::Owned(shader_string); + device + .create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("testbed.wgsl"), + source: wgpu::ShaderSource::Wgsl(source), + }) + } + pub const SHADER_ENTRY_PATH: &str = include_absolute_path::include_absolute_path!( + "../shaders/testbed.wgsl" + ); + pub const UTILS_TYPES_PATH: &str = include_absolute_path::include_absolute_path!( + "../shaders/utils/types.wgsl" + ); + pub const SHADER_PATHS: &[&str] = &[SHADER_ENTRY_PATH, UTILS_TYPES_PATH]; + pub fn load_shader_modules_from_path( + composer: &mut naga_oil::compose::Composer, + shader_defs: &std::collections::HashMap< + String, + naga_oil::compose::ShaderDefValue, + >, + ) -> Result<(), naga_oil::compose::ComposerError> { + composer + .add_composable_module(naga_oil::compose::ComposableModuleDescriptor { + source: &std::fs::read_to_string(UTILS_TYPES_PATH).unwrap(), + file_path: "../shaders/utils/types.wgsl", + language: naga_oil::compose::ShaderLanguage::Wgsl, + shader_defs: shader_defs.clone(), + as_name: Some("utils::types".into()), + ..Default::default() + })?; + Ok(()) + } + pub fn load_naga_module_from_path( + composer: &mut naga_oil::compose::Composer, + shader_defs: std::collections::HashMap, + ) -> Result { + composer + .make_naga_module(naga_oil::compose::NagaModuleDescriptor { + source: &std::fs::read_to_string(SHADER_ENTRY_PATH).unwrap(), + file_path: "../shaders/testbed.wgsl", + shader_defs, + ..Default::default() + }) + } + pub fn create_shader_module_from_path( + device: &wgpu::Device, + shader_defs: std::collections::HashMap, + ) -> Result { + let mut composer = naga_oil::compose::Composer::default() + .with_capabilities(wgpu::naga::valid::Capabilities::from_bits_retain(1)); + load_shader_modules_from_path(&mut composer, &shader_defs)?; + let module = load_naga_module_from_path(&mut composer, shader_defs)?; + let info = wgpu::naga::valid::Validator::new( + wgpu::naga::valid::ValidationFlags::empty(), + wgpu::naga::valid::Capabilities::all(), + ) + .validate(&module) + .unwrap(); + let shader_string = wgpu::naga::back::wgsl::write_string( + &module, + &info, + wgpu::naga::back::wgsl::WriterFlags::empty(), + ) + .expect("failed to convert naga module to source"); + let source = std::borrow::Cow::Owned(shader_string); + Ok( + device + .create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("testbed.wgsl"), + source: wgpu::ShaderSource::Wgsl(source), + }), + ) + } } pub mod triangle { - use super::_root; - use super::_root::*; - #[repr(C, align(16))] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct Uniforms { - /// size: 16, offset: 0x0, type: `vec4` - pub color_rgb: glam::Vec4, - } - pub const fn Uniforms(color_rgb: glam::Vec4) -> Uniforms { - Uniforms { color_rgb } - } - #[repr(C)] - #[derive(Debug, PartialEq, Clone, Copy)] - pub struct VertexInput { - pub position: glam::Vec3A, - } - pub const fn VertexInput(position: glam::Vec3A) -> VertexInput { - VertexInput { position } - } - impl VertexInput { - pub const VERTEX_ATTRIBUTES: [wgpu::VertexAttribute; 1] = [wgpu::VertexAttribute { - format: wgpu::VertexFormat::Float32x3, - offset: std::mem::offset_of!(Self, position) as u64, - shader_location: 0, - }]; - pub const fn vertex_buffer_layout( - step_mode: wgpu::VertexStepMode, - ) -> wgpu::VertexBufferLayout<'static> { - wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::() as u64, - step_mode, - attributes: &Self::VERTEX_ATTRIBUTES, - } - } - } - #[derive(Debug)] - pub struct WgpuBindGroup0EntriesParams<'a> { - pub color_texture: &'a wgpu::TextureView, - pub color_sampler: &'a wgpu::Sampler, - } - #[derive(Clone, Debug)] - pub struct WgpuBindGroup0Entries<'a> { - pub color_texture: wgpu::BindGroupEntry<'a>, - pub color_sampler: wgpu::BindGroupEntry<'a>, - } - impl<'a> WgpuBindGroup0Entries<'a> { - pub fn new(params: WgpuBindGroup0EntriesParams<'a>) -> Self { - Self { - color_texture: wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(params.color_texture), - }, - color_sampler: wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(params.color_sampler), - }, - } - } - pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 2] { - [self.color_texture, self.color_sampler] - } - pub fn collect>>(self) -> B { - self.as_array().into_iter().collect() - } - } - #[derive(Debug)] - pub struct WgpuBindGroup0(wgpu::BindGroup); - impl WgpuBindGroup0 { - pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = - wgpu::BindGroupLayoutDescriptor { - label: Some("Triangle::BindGroup0::LayoutDescriptor"), - entries: &[ - /// @binding(0): "color_texture" - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, + use super::{_root, _root::*}; + #[repr(C, align(16))] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct Uniforms { + /// size: 16, offset: 0x0, type: `vec4` + pub color_rgb: glam::Vec4, + } + pub const fn Uniforms(color_rgb: glam::Vec4) -> Uniforms { + Uniforms { color_rgb } + } + #[repr(C)] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct VertexInput { + pub position: glam::Vec3A, + } + pub const fn VertexInput(position: glam::Vec3A) -> VertexInput { + VertexInput { position } + } + impl VertexInput { + pub const VERTEX_ATTRIBUTES: [wgpu::VertexAttribute; 1] = [ + wgpu::VertexAttribute { + format: wgpu::VertexFormat::Float32x3, + offset: std::mem::offset_of!(Self, position) as u64, + shader_location: 0, + }, + ]; + pub const fn vertex_buffer_layout( + step_mode: wgpu::VertexStepMode, + ) -> wgpu::VertexBufferLayout<'static> { + wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as u64, + step_mode, + attributes: &Self::VERTEX_ATTRIBUTES, + } + } + } + #[repr(C, align(16))] + #[derive(Debug, PartialEq, Clone, Copy)] + pub struct PushConstants { + /// size: 64, offset: 0x0, type: `mat4x4` + pub color_matrix: glam::Mat4, + } + pub const fn PushConstants(color_matrix: glam::Mat4) -> PushConstants { + PushConstants { color_matrix } + } + #[derive(Debug)] + pub struct WgpuBindGroup0EntriesParams<'a> { + pub color_texture: &'a wgpu::TextureView, + pub color_sampler: &'a wgpu::Sampler, + } + #[derive(Clone, Debug)] + pub struct WgpuBindGroup0Entries<'a> { + pub color_texture: wgpu::BindGroupEntry<'a>, + pub color_sampler: wgpu::BindGroupEntry<'a>, + } + impl<'a> WgpuBindGroup0Entries<'a> { + pub fn new(params: WgpuBindGroup0EntriesParams<'a>) -> Self { + Self { + color_texture: wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(params.color_texture), + }, + color_sampler: wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(params.color_sampler), + }, + } + } + pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 2] { + [self.color_texture, self.color_sampler] + } + pub fn collect>>(self) -> B { + self.as_array().into_iter().collect() + } + } + #[derive(Debug)] + pub struct WgpuBindGroup0(wgpu::BindGroup); + impl WgpuBindGroup0 { + pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = wgpu::BindGroupLayoutDescriptor { + label: Some("Triangle::BindGroup0::LayoutDescriptor"), + entries: &[ + /// @binding(0): "color_texture" + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { + filterable: true, + }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + /// @binding(1): "color_sampler" + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + ], + }; + pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) + } + pub fn from_bindings( + device: &wgpu::Device, + bindings: WgpuBindGroup0Entries, + ) -> Self { + let bind_group_layout = Self::get_bind_group_layout(&device); + let entries = bindings.as_array(); + let bind_group = device + .create_bind_group( + &wgpu::BindGroupDescriptor { + label: Some("Triangle::BindGroup0"), + layout: &bind_group_layout, + entries: &entries, + }, + ); + Self(bind_group) + } + pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { + render_pass.set_bind_group(0, &self.0, &[]); + } + } + #[derive(Debug)] + pub struct WgpuBindGroup1EntriesParams<'a> { + pub uniforms: wgpu::BufferBinding<'a>, + } + #[derive(Clone, Debug)] + pub struct WgpuBindGroup1Entries<'a> { + pub uniforms: wgpu::BindGroupEntry<'a>, + } + impl<'a> WgpuBindGroup1Entries<'a> { + pub fn new(params: WgpuBindGroup1EntriesParams<'a>) -> Self { + Self { + uniforms: wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(params.uniforms), + }, + } + } + pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 1] { + [self.uniforms] + } + pub fn collect>>(self) -> B { + self.as_array().into_iter().collect() + } + } + #[derive(Debug)] + pub struct WgpuBindGroup1(wgpu::BindGroup); + impl WgpuBindGroup1 { + pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = wgpu::BindGroupLayoutDescriptor { + label: Some("Triangle::BindGroup1::LayoutDescriptor"), + entries: &[ + /// @binding(0): "uniforms" + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: std::num::NonZeroU64::new( + std::mem::size_of::<_root::triangle::Uniforms>() as _, + ), + }, + count: None, + }, + ], + }; + pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { + device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) + } + pub fn from_bindings( + device: &wgpu::Device, + bindings: WgpuBindGroup1Entries, + ) -> Self { + let bind_group_layout = Self::get_bind_group_layout(&device); + let entries = bindings.as_array(); + let bind_group = device + .create_bind_group( + &wgpu::BindGroupDescriptor { + label: Some("Triangle::BindGroup1"), + layout: &bind_group_layout, + entries: &entries, + }, + ); + Self(bind_group) + } + pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { + render_pass.set_bind_group(1, &self.0, &[]); + } + } + #[derive(Debug, Copy, Clone)] + pub struct WgpuBindGroups<'a> { + pub bind_group0: &'a WgpuBindGroup0, + pub bind_group1: &'a WgpuBindGroup1, + } + impl<'a> WgpuBindGroups<'a> { + pub fn set(&self, pass: &mut wgpu::RenderPass<'a>) { + self.bind_group0.set(pass); + self.bind_group1.set(pass); + } + } + pub fn set_bind_groups<'a>( + pass: &mut wgpu::RenderPass<'a>, + bind_group0: &'a WgpuBindGroup0, + bind_group1: &'a WgpuBindGroup1, + ) { + bind_group0.set(pass); + bind_group1.set(pass); + } + pub const ENTRY_VS_MAIN: &str = "vs_main"; + pub const ENTRY_FS_MAIN: &str = "fs_main"; + #[derive(Debug)] + pub struct VertexEntry { + pub entry_point: &'static str, + pub buffers: [wgpu::VertexBufferLayout<'static>; N], + pub constants: std::collections::HashMap, + } + pub fn vertex_state<'a, const N: usize>( + module: &'a wgpu::ShaderModule, + entry: &'a VertexEntry, + ) -> wgpu::VertexState<'a> { + wgpu::VertexState { + module, + entry_point: entry.entry_point, + buffers: &entry.buffers, + compilation_options: wgpu::PipelineCompilationOptions { + constants: &entry.constants, + ..Default::default() }, - count: None, - }, - /// @binding(1): "color_sampler" - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - }; - pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) - } - pub fn from_bindings(device: &wgpu::Device, bindings: WgpuBindGroup0Entries) -> Self { - let bind_group_layout = Self::get_bind_group_layout(&device); - let entries = bindings.as_array(); - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("Triangle::BindGroup0"), - layout: &bind_group_layout, - entries: &entries, - }); - Self(bind_group) - } - pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { - render_pass.set_bind_group(0, &self.0, &[]); - } - } - #[derive(Debug)] - pub struct WgpuBindGroup1EntriesParams<'a> { - pub uniforms: wgpu::BufferBinding<'a>, - } - #[derive(Clone, Debug)] - pub struct WgpuBindGroup1Entries<'a> { - pub uniforms: wgpu::BindGroupEntry<'a>, - } - impl<'a> WgpuBindGroup1Entries<'a> { - pub fn new(params: WgpuBindGroup1EntriesParams<'a>) -> Self { - Self { - uniforms: wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(params.uniforms), - }, - } - } - pub fn as_array(self) -> [wgpu::BindGroupEntry<'a>; 1] { - [self.uniforms] - } - pub fn collect>>(self) -> B { - self.as_array().into_iter().collect() - } - } - #[derive(Debug)] - pub struct WgpuBindGroup1(wgpu::BindGroup); - impl WgpuBindGroup1 { - pub const LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor<'static> = - wgpu::BindGroupLayoutDescriptor { - label: Some("Triangle::BindGroup1::LayoutDescriptor"), - entries: &[ - /// @binding(0): "uniforms" - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::< - _root::triangle::Uniforms, - >() as _), + } + } + pub fn vs_main_entry(vertex_input: wgpu::VertexStepMode) -> VertexEntry<1> { + VertexEntry { + entry_point: ENTRY_VS_MAIN, + buffers: [VertexInput::vertex_buffer_layout(vertex_input)], + constants: Default::default(), + } + } + #[derive(Debug)] + pub struct FragmentEntry { + pub entry_point: &'static str, + pub targets: [Option; N], + pub constants: std::collections::HashMap, + } + pub fn fragment_state<'a, const N: usize>( + module: &'a wgpu::ShaderModule, + entry: &'a FragmentEntry, + ) -> wgpu::FragmentState<'a> { + wgpu::FragmentState { + module, + entry_point: entry.entry_point, + targets: &entry.targets, + compilation_options: wgpu::PipelineCompilationOptions { + constants: &entry.constants, + ..Default::default() }, - count: None, - }, - ], - }; - pub fn get_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout { - device.create_bind_group_layout(&Self::LAYOUT_DESCRIPTOR) - } - pub fn from_bindings(device: &wgpu::Device, bindings: WgpuBindGroup1Entries) -> Self { - let bind_group_layout = Self::get_bind_group_layout(&device); - let entries = bindings.as_array(); - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("Triangle::BindGroup1"), - layout: &bind_group_layout, - entries: &entries, - }); - Self(bind_group) - } - pub fn set<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { - render_pass.set_bind_group(1, &self.0, &[]); - } - } - #[derive(Debug, Copy, Clone)] - pub struct WgpuBindGroups<'a> { - pub bind_group0: &'a WgpuBindGroup0, - pub bind_group1: &'a WgpuBindGroup1, - } - impl<'a> WgpuBindGroups<'a> { - pub fn set(&self, pass: &mut wgpu::RenderPass<'a>) { - self.bind_group0.set(pass); - self.bind_group1.set(pass); - } - } - pub fn set_bind_groups<'a>( - pass: &mut wgpu::RenderPass<'a>, - bind_group0: &'a WgpuBindGroup0, - bind_group1: &'a WgpuBindGroup1, - ) { - bind_group0.set(pass); - bind_group1.set(pass); - } - pub const ENTRY_VS_MAIN: &str = "vs_main"; - pub const ENTRY_FS_MAIN: &str = "fs_main"; - #[derive(Debug)] - pub struct VertexEntry { - pub entry_point: &'static str, - pub buffers: [wgpu::VertexBufferLayout<'static>; N], - pub constants: std::collections::HashMap, - } - pub fn vertex_state<'a, const N: usize>( - module: &'a wgpu::ShaderModule, - entry: &'a VertexEntry, - ) -> wgpu::VertexState<'a> { - wgpu::VertexState { - module, - entry_point: entry.entry_point, - buffers: &entry.buffers, - compilation_options: wgpu::PipelineCompilationOptions { - constants: &entry.constants, - ..Default::default() - }, - } - } - pub fn vs_main_entry(vertex_input: wgpu::VertexStepMode) -> VertexEntry<1> { - VertexEntry { - entry_point: ENTRY_VS_MAIN, - buffers: [VertexInput::vertex_buffer_layout(vertex_input)], - constants: Default::default(), - } - } - #[derive(Debug)] - pub struct FragmentEntry { - pub entry_point: &'static str, - pub targets: [Option; N], - pub constants: std::collections::HashMap, - } - pub fn fragment_state<'a, const N: usize>( - module: &'a wgpu::ShaderModule, - entry: &'a FragmentEntry, - ) -> wgpu::FragmentState<'a> { - wgpu::FragmentState { - module, - entry_point: entry.entry_point, - targets: &entry.targets, - compilation_options: wgpu::PipelineCompilationOptions { - constants: &entry.constants, - ..Default::default() - }, - } - } - pub fn fs_main_entry(targets: [Option; 1]) -> FragmentEntry<1> { - FragmentEntry { - entry_point: ENTRY_FS_MAIN, - targets, - constants: Default::default(), - } - } - #[derive(Debug)] - pub struct WgpuPipelineLayout; - impl WgpuPipelineLayout { - pub fn bind_group_layout_entries( - entries: [wgpu::BindGroupLayout; 2], - ) -> [wgpu::BindGroupLayout; 2] { - entries - } - } - pub fn create_pipeline_layout(device: &wgpu::Device) -> wgpu::PipelineLayout { - device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Triangle::PipelineLayout"), - bind_group_layouts: &[ - &WgpuBindGroup0::get_bind_group_layout(device), - &WgpuBindGroup1::get_bind_group_layout(device), - ], - push_constant_ranges: &[], - }) - } - pub fn create_shader_module_embed_source(device: &wgpu::Device) -> wgpu::ShaderModule { - let source = std::borrow::Cow::Borrowed(SHADER_STRING); - device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("triangle.wgsl"), - source: wgpu::ShaderSource::Wgsl(source), - }) - } - pub const SHADER_STRING: &'static str = r#" + } + } + pub fn fs_main_entry( + targets: [Option; 1], + ) -> FragmentEntry<1> { + FragmentEntry { + entry_point: ENTRY_FS_MAIN, + targets, + constants: Default::default(), + } + } + #[derive(Debug)] + pub struct WgpuPipelineLayout; + impl WgpuPipelineLayout { + pub fn bind_group_layout_entries( + entries: [wgpu::BindGroupLayout; 2], + ) -> [wgpu::BindGroupLayout; 2] { + entries + } + } + pub fn create_pipeline_layout(device: &wgpu::Device) -> wgpu::PipelineLayout { + device + .create_pipeline_layout( + &wgpu::PipelineLayoutDescriptor { + label: Some("Triangle::PipelineLayout"), + bind_group_layouts: &[ + &WgpuBindGroup0::get_bind_group_layout(device), + &WgpuBindGroup1::get_bind_group_layout(device), + ], + push_constant_ranges: &[ + wgpu::PushConstantRange { + stages: wgpu::ShaderStages::VERTEX_FRAGMENT, + range: 0..64, + }, + ], + }, + ) + } + pub fn create_shader_module_embed_source( + device: &wgpu::Device, + ) -> wgpu::ShaderModule { + let source = std::borrow::Cow::Borrowed(SHADER_STRING); + device + .create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("triangle.wgsl"), + source: wgpu::ShaderSource::Wgsl(source), + }) + } + pub const SHADER_STRING: &'static str = r#" struct Uniforms { color_rgb: vec4, } @@ -1410,12 +1505,17 @@ struct VertexOutput { @location(0) tex_coords: vec2, } +struct PushConstants { + color_matrix: mat4x4, +} + @group(0) @binding(0) var color_texture: texture_2d; @group(0) @binding(1) var color_sampler: sampler; @group(1) @binding(0) var uniforms: Uniforms; +var constants: PushConstants; @vertex fn vs_main(in: VertexInput) -> VertexOutput { @@ -1431,97 +1531,112 @@ fn vs_main(in: VertexInput) -> VertexOutput { fn fs_main(in_1: VertexOutput) -> @location(0) vec4 { let _e4 = textureSample(color_texture, color_sampler, in_1.tex_coords); let color = _e4.xyz; - let _e8 = uniforms.color_rgb; - return vec4((color * _e8.xyz), 1f); + let _e8 = constants.color_matrix; + let _e11 = uniforms.color_rgb; + return (_e8 * vec4((color * _e11.xyz), 1f)); } "#; - pub fn load_shader_modules_embedded( - composer: &mut naga_oil::compose::Composer, - shader_defs: &std::collections::HashMap, - ) -> () { - () - } - pub fn load_naga_module_embedded( - composer: &mut naga_oil::compose::Composer, - shader_defs: std::collections::HashMap, - ) -> wgpu::naga::Module { - composer - .make_naga_module(naga_oil::compose::NagaModuleDescriptor { - source: include_str!("../shaders/triangle.wgsl"), - file_path: "../shaders/triangle.wgsl", - shader_defs, - ..Default::default() - }) - .expect("failed to build naga module") - } - pub fn create_shader_module_embedded( - device: &wgpu::Device, - shader_defs: std::collections::HashMap, - ) -> wgpu::ShaderModule { - let mut composer = naga_oil::compose::Composer::default(); - load_shader_modules_embedded(&mut composer, &shader_defs); - let module = load_naga_module_embedded(&mut composer, shader_defs); - let info = wgpu::naga::valid::Validator::new( - wgpu::naga::valid::ValidationFlags::empty(), - wgpu::naga::valid::Capabilities::all(), - ) - .validate(&module) - .unwrap(); - let shader_string = wgpu::naga::back::wgsl::write_string( - &module, - &info, - wgpu::naga::back::wgsl::WriterFlags::empty(), - ) - .expect("failed to convert naga module to source"); - let source = std::borrow::Cow::Owned(shader_string); - device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("triangle.wgsl"), - source: wgpu::ShaderSource::Wgsl(source), - }) - } - pub const SHADER_ENTRY_PATH: &str = - include_absolute_path::include_absolute_path!("../shaders/triangle.wgsl"); - pub const SHADER_PATHS: &[&str] = &[SHADER_ENTRY_PATH]; - pub fn load_shader_modules_from_path( - composer: &mut naga_oil::compose::Composer, - shader_defs: &std::collections::HashMap, - ) -> Result<(), naga_oil::compose::ComposerError> { - Ok(()) - } - pub fn load_naga_module_from_path( - composer: &mut naga_oil::compose::Composer, - shader_defs: std::collections::HashMap, - ) -> Result { - composer.make_naga_module(naga_oil::compose::NagaModuleDescriptor { - source: &std::fs::read_to_string(SHADER_ENTRY_PATH).unwrap(), - file_path: "../shaders/triangle.wgsl", - shader_defs, - ..Default::default() - }) - } - pub fn create_shader_module_from_path( - device: &wgpu::Device, - shader_defs: std::collections::HashMap, - ) -> Result { - let mut composer = naga_oil::compose::Composer::default(); - load_shader_modules_from_path(&mut composer, &shader_defs)?; - let module = load_naga_module_from_path(&mut composer, shader_defs)?; - let info = wgpu::naga::valid::Validator::new( - wgpu::naga::valid::ValidationFlags::empty(), - wgpu::naga::valid::Capabilities::all(), - ) - .validate(&module) - .unwrap(); - let shader_string = wgpu::naga::back::wgsl::write_string( - &module, - &info, - wgpu::naga::back::wgsl::WriterFlags::empty(), - ) - .expect("failed to convert naga module to source"); - let source = std::borrow::Cow::Owned(shader_string); - Ok(device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("triangle.wgsl"), - source: wgpu::ShaderSource::Wgsl(source), - })) - } + pub fn load_shader_modules_embedded( + composer: &mut naga_oil::compose::Composer, + shader_defs: &std::collections::HashMap< + String, + naga_oil::compose::ShaderDefValue, + >, + ) -> () { + () + } + pub fn load_naga_module_embedded( + composer: &mut naga_oil::compose::Composer, + shader_defs: std::collections::HashMap, + ) -> wgpu::naga::Module { + composer + .make_naga_module(naga_oil::compose::NagaModuleDescriptor { + source: include_str!("../shaders/triangle.wgsl"), + file_path: "../shaders/triangle.wgsl", + shader_defs, + ..Default::default() + }) + .expect("failed to build naga module") + } + pub fn create_shader_module_embedded( + device: &wgpu::Device, + shader_defs: std::collections::HashMap, + ) -> wgpu::ShaderModule { + let mut composer = naga_oil::compose::Composer::default() + .with_capabilities(wgpu::naga::valid::Capabilities::from_bits_retain(1)); + load_shader_modules_embedded(&mut composer, &shader_defs); + let module = load_naga_module_embedded(&mut composer, shader_defs); + let info = wgpu::naga::valid::Validator::new( + wgpu::naga::valid::ValidationFlags::empty(), + wgpu::naga::valid::Capabilities::all(), + ) + .validate(&module) + .unwrap(); + let shader_string = wgpu::naga::back::wgsl::write_string( + &module, + &info, + wgpu::naga::back::wgsl::WriterFlags::empty(), + ) + .expect("failed to convert naga module to source"); + let source = std::borrow::Cow::Owned(shader_string); + device + .create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("triangle.wgsl"), + source: wgpu::ShaderSource::Wgsl(source), + }) + } + pub const SHADER_ENTRY_PATH: &str = include_absolute_path::include_absolute_path!( + "../shaders/triangle.wgsl" + ); + pub const SHADER_PATHS: &[&str] = &[SHADER_ENTRY_PATH]; + pub fn load_shader_modules_from_path( + composer: &mut naga_oil::compose::Composer, + shader_defs: &std::collections::HashMap< + String, + naga_oil::compose::ShaderDefValue, + >, + ) -> Result<(), naga_oil::compose::ComposerError> { + Ok(()) + } + pub fn load_naga_module_from_path( + composer: &mut naga_oil::compose::Composer, + shader_defs: std::collections::HashMap, + ) -> Result { + composer + .make_naga_module(naga_oil::compose::NagaModuleDescriptor { + source: &std::fs::read_to_string(SHADER_ENTRY_PATH).unwrap(), + file_path: "../shaders/triangle.wgsl", + shader_defs, + ..Default::default() + }) + } + pub fn create_shader_module_from_path( + device: &wgpu::Device, + shader_defs: std::collections::HashMap, + ) -> Result { + let mut composer = naga_oil::compose::Composer::default() + .with_capabilities(wgpu::naga::valid::Capabilities::from_bits_retain(1)); + load_shader_modules_from_path(&mut composer, &shader_defs)?; + let module = load_naga_module_from_path(&mut composer, shader_defs)?; + let info = wgpu::naga::valid::Validator::new( + wgpu::naga::valid::ValidationFlags::empty(), + wgpu::naga::valid::Capabilities::all(), + ) + .validate(&module) + .unwrap(); + let shader_string = wgpu::naga::back::wgsl::write_string( + &module, + &info, + wgpu::naga::back::wgsl::WriterFlags::empty(), + ) + .expect("failed to convert naga module to source"); + let source = std::borrow::Cow::Owned(shader_string); + Ok( + device + .create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("triangle.wgsl"), + source: wgpu::ShaderSource::Wgsl(source), + }), + ) + } } diff --git a/wgsl_bindgen/src/bindgen/bindgen.rs b/wgsl_bindgen/src/bindgen/bindgen.rs index b2fbb7b..13490c9 100644 --- a/wgsl_bindgen/src/bindgen/bindgen.rs +++ b/wgsl_bindgen/src/bindgen/bindgen.rs @@ -86,9 +86,7 @@ impl WGSLBindgen { }; let mut composer = match ir_capabilities { - Some(WgslShaderIrCapabilities { capabilities }) => { - Composer::default().with_capabilities(capabilities) - } + Some(capabilities) => Composer::default().with_capabilities(capabilities), _ => Composer::default(), }; let source = entry.source_file; diff --git a/wgsl_bindgen/src/bindgen/options/mod.rs b/wgsl_bindgen/src/bindgen/options/mod.rs index c87d730..b530633 100644 --- a/wgsl_bindgen/src/bindgen/options/mod.rs +++ b/wgsl_bindgen/src/bindgen/options/mod.rs @@ -7,6 +7,7 @@ pub use bindings::*; use derive_builder::Builder; use derive_more::IsVariant; use enumflags2::{bitflags, BitFlags}; +pub use naga::valid::Capabilities as WgslShaderIrCapabilities; use proc_macro2::TokenStream; use regex::Regex; pub use types::*; @@ -15,12 +16,6 @@ use crate::{ FastIndexMap, WGSLBindgen, WgslBindgenError, WgslType, WgslTypeSerializeStrategy, }; -/// The [wgpu::naga::valid::Capabilities](https://docs.rs/wgpu/latest/wgpu/naga/valid/struct.Capabilities.html) to use for the module. -#[derive(Clone, Copy, Debug)] -pub struct WgslShaderIrCapabilities { - pub capabilities: naga::valid::Capabilities, -} - /// An enum representing the source type that will be generated for the output. #[bitflags(default = UseEmbed)] #[repr(u8)] diff --git a/wgsl_bindgen/src/generate/bind_group/mod.rs b/wgsl_bindgen/src/generate/bind_group/mod.rs index 94ad361..33f964e 100644 --- a/wgsl_bindgen/src/generate/bind_group/mod.rs +++ b/wgsl_bindgen/src/generate/bind_group/mod.rs @@ -1,6 +1,7 @@ use std::collections::BTreeMap; use derive_more::Constructor; +use generate::quote_shader_stages; use quote::{format_ident, quote}; use quote_gen::{demangle_and_fully_qualify_str, rust_type}; @@ -275,26 +276,7 @@ fn bind_group_layout_entry( // TODO: Assume storage is only used for compute? // TODO: Support just vertex or fragment? // TODO: Visible from all stages? - let stages = match shader_stages { - wgpu::ShaderStages::VERTEX_FRAGMENT => quote!(wgpu::ShaderStages::VERTEX_FRAGMENT), - wgpu::ShaderStages::COMPUTE => quote!(wgpu::ShaderStages::COMPUTE), - wgpu::ShaderStages::VERTEX => quote!(wgpu::ShaderStages::VERTEX), - wgpu::ShaderStages::FRAGMENT => quote!(wgpu::ShaderStages::FRAGMENT), - _ => { - let mut stage_tokens = vec![]; - if shader_stages.contains(wgpu::ShaderStages::VERTEX) { - stage_tokens.push(quote!(wgpu::ShaderStages::VERTEX)); - } - if shader_stages.contains(wgpu::ShaderStages::FRAGMENT) { - stage_tokens.push(quote!(wgpu::ShaderStages::FRAGMENT)); - } - if shader_stages.contains(wgpu::ShaderStages::COMPUTE) { - stage_tokens.push(quote!(wgpu::ShaderStages::COMPUTE)); - } - // quote!(#(#stage_tokens)|*) - unimplemented!() - } - }; + let stages = quote_shader_stages(shader_stages); let binding_index = Index::from(binding.binding_index as usize); // TODO: Support more types. diff --git a/wgsl_bindgen/src/generate/mod.rs b/wgsl_bindgen/src/generate/mod.rs index e6e41b0..df5c024 100644 --- a/wgsl_bindgen/src/generate/mod.rs +++ b/wgsl_bindgen/src/generate/mod.rs @@ -1,6 +1,32 @@ +use proc_macro2::TokenStream; +use quote::quote; + pub(crate) mod bind_group; pub(crate) mod consts; pub(crate) mod entry; pub(crate) mod pipeline; pub(crate) mod shader_module; pub(crate) mod shader_registry; + +pub(crate) fn quote_shader_stages(shader_stages: wgpu::ShaderStages) -> TokenStream { + match shader_stages { + wgpu::ShaderStages::VERTEX_FRAGMENT => quote!(wgpu::ShaderStages::VERTEX_FRAGMENT), + wgpu::ShaderStages::COMPUTE => quote!(wgpu::ShaderStages::COMPUTE), + wgpu::ShaderStages::VERTEX => quote!(wgpu::ShaderStages::VERTEX), + wgpu::ShaderStages::FRAGMENT => quote!(wgpu::ShaderStages::FRAGMENT), + _ => { + let mut stage_tokens = vec![]; + if shader_stages.contains(wgpu::ShaderStages::VERTEX) { + stage_tokens.push(quote!(wgpu::ShaderStages::VERTEX)); + } + if shader_stages.contains(wgpu::ShaderStages::FRAGMENT) { + stage_tokens.push(quote!(wgpu::ShaderStages::FRAGMENT)); + } + if shader_stages.contains(wgpu::ShaderStages::COMPUTE) { + stage_tokens.push(quote!(wgpu::ShaderStages::COMPUTE)); + } + // quote!(#(#stage_tokens)|*) + unimplemented!() + } + } +} diff --git a/wgsl_bindgen/src/generate/pipeline.rs b/wgsl_bindgen/src/generate/pipeline.rs index d60ecff..dfb54a6 100644 --- a/wgsl_bindgen/src/generate/pipeline.rs +++ b/wgsl_bindgen/src/generate/pipeline.rs @@ -1,6 +1,7 @@ use std::collections::BTreeMap; use derive_more::Constructor; +use generate::quote_shader_stages; use super::bind_group::GroupData; use crate::*; @@ -38,8 +39,39 @@ impl<'a> PipelineLayoutDataEntriesBuilder<'a> { } } +fn push_constant_range( + module: &naga::Module, + shader_stages: wgpu::ShaderStages, +) -> Option { + // Assume only one variable is used with var in WGSL. + let push_constant_size = module.global_variables.iter().find_map(|g| { + if g.1.space == naga::AddressSpace::PushConstant { + Some(module.types[g.1.ty].inner.size(module.to_ctx())) + } else { + None + } + }); + + let stages = quote_shader_stages(shader_stages); + + // Use a single push constant range for all shader stages. + // This allows easily setting push constants in a single call with offset 0. + let push_constant_range = push_constant_size.map(|size| { + let size = Index::from(size as usize); + quote! { + wgpu::PushConstantRange { + stages: #stages, + range: 0..#size + } + } + }); + push_constant_range +} + pub fn create_pipeline_layout_fn( entry_name: &str, + naga_module: &naga::Module, + shader_stages: wgpu::ShaderStages, options: &WgslBindgenOption, bind_group_data: &BTreeMap, ) -> TokenStream { @@ -65,6 +97,8 @@ pub fn create_pipeline_layout_fn( quote!() }; + let push_constant_range = push_constant_range(&naga_module, shader_stages); + let pipeline_layout_name = format!("{}::PipelineLayout", entry_name); quote! { @@ -76,7 +110,7 @@ pub fn create_pipeline_layout_fn( bind_group_layouts: &[ #(&#bind_group_layouts),* ], - push_constant_ranges: &[], + push_constant_ranges: &[#push_constant_range], }) } } diff --git a/wgsl_bindgen/src/generate/shader_module.rs b/wgsl_bindgen/src/generate/shader_module.rs index 13a12a6..aa64809 100644 --- a/wgsl_bindgen/src/generate/shader_module.rs +++ b/wgsl_bindgen/src/generate/shader_module.rs @@ -286,6 +286,7 @@ fn generate_shader_module_embedded(entry: &WgslEntryResult) -> TokenStream { struct ComposeShaderModuleBuilder<'a, 'b> { entry: &'a WgslEntryResult<'b>, + capabilities: Option, entry_source_path: &'a Path, output_dir: &'a Path, source_type: WgslShaderSourceType, @@ -294,6 +295,7 @@ struct ComposeShaderModuleBuilder<'a, 'b> { impl<'a, 'b> ComposeShaderModuleBuilder<'a, 'b> { fn new( entry: &'a WgslEntryResult<'b>, + capabilities: Option, output_dir: &'a Path, source_type: WgslShaderSourceType, ) -> Self { @@ -301,6 +303,7 @@ impl<'a, 'b> ComposeShaderModuleBuilder<'a, 'b> { Self { entry, + capabilities, output_dir, source_type, entry_source_path, @@ -467,13 +470,27 @@ impl<'a, 'b> ComposeShaderModuleBuilder<'a, 'b> { }) }); + let composer = quote!(naga_oil::compose::Composer::default()); + + let composer_with_capabilities = match self.capabilities { + Some(capabilities) => { + let capabilities = Index::from(capabilities.bits() as usize); + quote! { + #composer.with_capabilities(wgpu::naga::valid::Capabilities::from_bits_retain(#capabilities)) + } + } + None => quote! { + #composer + }, + }; + quote! { pub fn #create_shader_module_fn( device: &wgpu::Device, shader_defs: std::collections::HashMap ) -> #return_type { - let mut composer = naga_oil::compose::Composer::default(); + let mut composer = #composer_with_capabilities; #load_shader_module_fn (&mut composer, &shader_defs) #propagate_operator; let module = #load_naga_module_fn (&mut composer, shader_defs) #propagate_operator; @@ -535,14 +552,21 @@ pub(crate) fn shader_module( token_stream.append_all(generate_shader_module_embedded(entry)); } + let capabilities = options.ir_capabilities.clone(); + if source_type.contains(UseComposerEmbed) { - let builder = ComposeShaderModuleBuilder::new(entry, &output_dir, UseComposerEmbed); + let builder = + ComposeShaderModuleBuilder::new(entry, capabilities, &output_dir, UseComposerEmbed); token_stream.append_all(builder.build()); } if source_type.contains(UseComposerWithPath) { - let builder = - ComposeShaderModuleBuilder::new(entry, &output_dir, UseComposerWithPath); + let builder = ComposeShaderModuleBuilder::new( + entry, + capabilities, + &output_dir, + UseComposerWithPath, + ); token_stream.append_all(builder.build()); } diff --git a/wgsl_bindgen/src/lib.rs b/wgsl_bindgen/src/lib.rs index 64e1b6b..f3b5eca 100644 --- a/wgsl_bindgen/src/lib.rs +++ b/wgsl_bindgen/src/lib.rs @@ -120,7 +120,7 @@ fn create_rust_bindings( naga_module, .. } = entry; - let entry_name = sanitize_and_pascal_case(&entry.mod_name); + let entry_name = sanitize_and_pascal_case(&mod_name); let bind_group_data = bind_group::get_bind_group_data(naga_module)?; let shader_stages = wgsl::shader_stages(naga_module); @@ -160,8 +160,14 @@ fn create_rust_bindings( mod_builder.add(mod_name, entry::vertex_states(mod_name, naga_module)); mod_builder.add(mod_name, entry::fragment_states(naga_module)); - let create_pipeline_layout = - pipeline::create_pipeline_layout_fn(&entry_name, &options, &bind_group_data); + let create_pipeline_layout = pipeline::create_pipeline_layout_fn( + &entry_name, + naga_module, + shader_stages, + &options, + &bind_group_data, + ); + mod_builder.add(mod_name, create_pipeline_layout); mod_builder.add(mod_name, shader_module::shader_module(entry, options)); } @@ -243,9 +249,11 @@ mod test { #[test] fn create_shader_module_embed_source() { let source = indoc! {r#" - @fragment - fn fs_main() {} - "#}; + var consts: vec4; + + @fragment + fn fs_main() {} + "#}; let actual = create_shader_module(source, WgslBindgenOption::default()).unwrap(); @@ -321,7 +329,12 @@ mod test { &wgpu::PipelineLayoutDescriptor { label: Some("Test::PipelineLayout"), bind_group_layouts: &[], - push_constant_ranges: &[], + push_constant_ranges: &[ + wgpu::PushConstantRange { + stages: wgpu::ShaderStages::FRAGMENT, + range: 0..16, + }, + ], }, ) } @@ -336,6 +349,8 @@ mod test { }) } pub const SHADER_STRING: &'static str = r#" + var consts: vec4; + @fragment fn fs_main() { return; diff --git a/wgsl_bindgen/tests/bindgen_tests.rs b/wgsl_bindgen/tests/bindgen_tests.rs index d51acfd..8fb2cb7 100644 --- a/wgsl_bindgen/tests/bindgen_tests.rs +++ b/wgsl_bindgen/tests/bindgen_tests.rs @@ -37,9 +37,7 @@ fn test_main_bindgen() -> Result<()> { .type_map(GlamWgslTypeMap) .emit_rerun_if_change(false) .skip_header_comments(true) - .ir_capabilities(WgslShaderIrCapabilities { - capabilities: naga::valid::Capabilities::PUSH_CONSTANT, - }) + .ir_capabilities(naga::valid::Capabilities::PUSH_CONSTANT) .shader_source_type( WgslShaderSourceType::UseEmbed | WgslShaderSourceType::UseComposerWithPath, ) diff --git a/wgsl_bindgen/tests/output/bindgen_main.expected.rs b/wgsl_bindgen/tests/output/bindgen_main.expected.rs index 613e22c..def1dbf 100644 --- a/wgsl_bindgen/tests/output/bindgen_main.expected.rs +++ b/wgsl_bindgen/tests/output/bindgen_main.expected.rs @@ -365,7 +365,12 @@ pub mod main { &WgpuBindGroup0::get_bind_group_layout(device), &WgpuBindGroup1::get_bind_group_layout(device), ], - push_constant_ranges: &[], + push_constant_ranges: &[ + wgpu::PushConstantRange { + stages: wgpu::ShaderStages::COMPUTE, + range: 0..32, + }, + ], }, ) } @@ -460,7 +465,8 @@ fn main(@builtin(global_invocation_id) id: vec3) { device: &wgpu::Device, shader_defs: std::collections::HashMap, ) -> Result { - let mut composer = naga_oil::compose::Composer::default(); + let mut composer = naga_oil::compose::Composer::default() + .with_capabilities(wgpu::naga::valid::Capabilities::from_bits_retain(1)); load_shader_modules_from_path(&mut composer, &shader_defs)?; let module = load_naga_module_from_path(&mut composer, shader_defs)?; let info = wgpu::naga::valid::Validator::new(