diff --git a/Cargo.toml b/Cargo.toml index 71de75b118..5f11951cfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,8 @@ erased-serde = "0.3" type-uuid = "0.1" shaderc = "0.6" libloading = "0.5.2" -rspirv = "0.5.4" +# rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "baa469eae2932271174593eb066894d7a7a38439" } +spirv-reflect = "0.2.3" bevy_derive = { path = "bevy_derive" } bevy_transform = { path = "bevy_transform" } diff --git a/src/render/mod.rs b/src/render/mod.rs index 5fcdec500a..2e119b7b39 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -4,6 +4,7 @@ pub mod passes; pub mod render_graph_2; pub mod render_resources; pub mod shader; +pub mod shader_reflect; mod light; mod material; diff --git a/src/render/shader.rs b/src/render/shader.rs index fc9ff31c6e..4c4b1d2be3 100644 --- a/src/render/shader.rs +++ b/src/render/shader.rs @@ -1,4 +1,4 @@ -use crate::asset::Handle; +use crate::{asset::Handle, render::shader_reflect::get_shader_layout}; use std::marker::Copy; #[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)] @@ -68,10 +68,14 @@ impl Shader { } pub fn get_spirv(&self, macros: Option<&[String]>) -> Vec { - match self.source { + let result = match self.source { ShaderSource::Spirv(ref bytes) => bytes.clone(), ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, self.stage, macros), - } + }; + + get_shader_layout(&result); + + result } pub fn get_spirv_shader(&self, macros: Option<&[String]>) -> Shader { @@ -96,4 +100,4 @@ impl ShaderStages { fragment: None, } } -} \ No newline at end of file +} diff --git a/src/render/shader_reflect.rs b/src/render/shader_reflect.rs new file mode 100644 index 0000000000..c08c10be13 --- /dev/null +++ b/src/render/shader_reflect.rs @@ -0,0 +1,73 @@ +use crate::render::render_graph_2::{BindGroup, UniformPropertyType, Binding, BindType}; +use spirv_reflect::{ + types::{ReflectDescriptorSet, ReflectTypeDescription, ReflectDescriptorBinding, ReflectDescriptorType}, + ShaderModule, +}; +use zerocopy::AsBytes; +// use rspirv::{binary::Parser, dr::Loader, lift::LiftContext}; + +// TODO: pick rspirv vs spirv-reflect +// pub fn get_shader_layout(spirv_data: &[u32]) { +// let mut loader = Loader::new(); // You can use your own consumer here. +// { +// let p = Parser::new(spirv_data.as_bytes(), &mut loader); +// p.parse().unwrap(); +// } +// let module = loader.module(); +// let structured = LiftContext::convert(&module).unwrap(); +// println!("{:?}", structured.types); +// } + +pub fn get_shader_layout(spirv_data: &[u32]) { + match ShaderModule::load_u8_data(spirv_data.as_bytes()) { + Ok(ref mut module) => { + let entry_point_name = module.get_entry_point_name(); + let shader_stage = module.get_shader_stage(); + println!("entry point: {}", entry_point_name); + println!("shader stage: {:?}", shader_stage); + + let mut bind_groups = Vec::new(); + for descriptor_set in module.enumerate_descriptor_sets(None).unwrap() { + let bind_group = reflect_bind_group(&descriptor_set); + bind_groups.push(bind_group); + } + + println!(" result {:?}", &bind_groups); + + println!(); + } + _ => {} + } +} + +fn reflect_bind_group(descriptor_set: &ReflectDescriptorSet) -> BindGroup { + println!(" set {}", descriptor_set.set); + let mut bindings = Vec::new(); + for descriptor_binding in descriptor_set.bindings.iter() { + let binding = reflect_binding(descriptor_binding); + bindings.push(binding); + } + + BindGroup::new(bindings) +} + +fn reflect_binding(binding: &ReflectDescriptorBinding) -> Binding { + let type_description = binding.type_description.as_ref().unwrap(); + let bind_type = match binding.descriptor_type { + ReflectDescriptorType::UniformBuffer => reflect_uniform(type_description), + _ => panic!("unsupported bind type {:?}", binding.descriptor_type), + }; + + // println!(" {:?}", binding); + Binding{ + bind_type: bind_type, + name: type_description.type_name.to_string() + } +} + +fn reflect_uniform(binding: &ReflectTypeDescription) -> BindType { + BindType::Uniform { + dynamic: false, + properties: Vec::new() + } +}