mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
Shader reflection works for everything but dynamic uniforms
This commit is contained in:
parent
c29a6f7dd2
commit
2fe9710c04
10 changed files with 289 additions and 163 deletions
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
|
@ -30,11 +30,11 @@
|
|||
"cargo": {
|
||||
"args": [
|
||||
"build",
|
||||
"--example=simple_new_graph",
|
||||
"--example=simple_new",
|
||||
"--package=bevy"
|
||||
],
|
||||
"filter": {
|
||||
"name": "simple_new_graph",
|
||||
"name": "simple_new",
|
||||
"kind": "example"
|
||||
}
|
||||
},
|
||||
|
@ -48,12 +48,12 @@
|
|||
"cargo": {
|
||||
"args": [
|
||||
"run",
|
||||
"--example=simple",
|
||||
"--example=simple_new",
|
||||
"--package=bevy",
|
||||
"--release"
|
||||
],
|
||||
"filter": {
|
||||
"name": "simple",
|
||||
"name": "simple_new",
|
||||
"kind": "example"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -14,6 +14,9 @@ Here is the current list of planned features. All items are sorted in approximat
|
|||
* Add runtime type safety to uniform bindings (and maybe compile time)
|
||||
* Dynamic / user defined shaders
|
||||
* consider using shaderc-rs. but this introduces compile complexity and requires other C++ build systems
|
||||
* Error Handling
|
||||
* Custom error type?
|
||||
* Remove as many panics / unwraps as possible
|
||||
* Input
|
||||
* Keyboard and mouse events
|
||||
* Gamepad events
|
||||
|
|
|
@ -20,10 +20,16 @@ impl<'a> Into<wgpu::VertexBufferDescriptor<'a>> for &'a VertexBufferDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PipelineLayoutType {
|
||||
Manual(PipelineLayout),
|
||||
Reflected(Option<PipelineLayout>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PipelineDescriptor {
|
||||
pub draw_targets: Vec<String>,
|
||||
pub pipeline_layout: PipelineLayout,
|
||||
pub layout: PipelineLayoutType,
|
||||
pub shader_stages: ShaderStages,
|
||||
pub rasterization_state: Option<wgpu::RasterizationStateDescriptor>,
|
||||
|
||||
|
@ -59,7 +65,7 @@ pub struct PipelineDescriptor {
|
|||
impl PipelineDescriptor {
|
||||
fn new(vertex_shader: Handle<Shader>) -> Self {
|
||||
PipelineDescriptor {
|
||||
pipeline_layout: PipelineLayout::new(),
|
||||
layout: PipelineLayoutType::Reflected(None),
|
||||
color_states: Vec::new(),
|
||||
depth_stencil_state: None,
|
||||
draw_targets: Vec::new(),
|
||||
|
@ -79,6 +85,20 @@ impl PipelineDescriptor {
|
|||
alpha_to_coverage_enabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_layout(&self) -> Option<&PipelineLayout> {
|
||||
match self.layout {
|
||||
PipelineLayoutType::Reflected(ref layout) => layout.as_ref(),
|
||||
PipelineLayoutType::Manual(ref layout) => Some(layout),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_layout_mut(&mut self) -> Option<&mut PipelineLayout> {
|
||||
match self.layout {
|
||||
PipelineLayoutType::Reflected(ref mut layout) => layout.as_mut(),
|
||||
PipelineLayoutType::Manual(ref mut layout) => Some(layout),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PipelineDescriptor {
|
||||
|
@ -128,7 +148,14 @@ impl<'a> PipelineBuilder<'a> {
|
|||
}
|
||||
|
||||
pub fn add_bind_group(mut self, bind_group: BindGroup) -> Self {
|
||||
self.pipeline.pipeline_layout.bind_groups.push(bind_group);
|
||||
if let PipelineLayoutType::Reflected(_) = self.pipeline.layout {
|
||||
self.pipeline.layout = PipelineLayoutType::Manual(PipelineLayout::new());
|
||||
}
|
||||
|
||||
if let PipelineLayoutType::Manual(ref mut layout) = self.pipeline.layout {
|
||||
layout.bind_groups.push(bind_group);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::render::shader_reflect::ShaderLayout;
|
||||
use std::{
|
||||
collections::hash_map::DefaultHasher,
|
||||
collections::{HashMap, hash_map::DefaultHasher, BTreeSet},
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
|
@ -14,23 +15,61 @@ impl PipelineLayout {
|
|||
bind_groups: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_shader_layouts(shader_layouts: &mut [ShaderLayout]) -> Self {
|
||||
let mut bind_groups = HashMap::<u32, BindGroup>::new();
|
||||
for shader_layout in shader_layouts {
|
||||
for shader_bind_group in shader_layout.bind_groups.iter_mut() {
|
||||
match bind_groups.get_mut(&shader_bind_group.index) {
|
||||
Some(bind_group) => {
|
||||
for shader_binding in shader_bind_group.bindings.iter() {
|
||||
if let Some(binding) = bind_group.bindings.iter().find(|binding| binding.index == shader_binding.index) {
|
||||
if binding != shader_binding {
|
||||
panic!("Binding {} in BindGroup {} does not match across all shader types: {:?} {:?}", binding.index, bind_group.index, binding, shader_binding);
|
||||
}
|
||||
} else {
|
||||
bind_group.bindings.insert(shader_binding.clone());
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
bind_groups.insert(shader_bind_group.index, shader_bind_group.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PipelineLayout {
|
||||
bind_groups: bind_groups.drain().map(|(_, value)| value).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, Clone, Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BindGroup {
|
||||
pub bindings: Vec<Binding>,
|
||||
pub index: u32,
|
||||
pub bindings: BTreeSet<Binding>,
|
||||
hash: Option<u64>,
|
||||
}
|
||||
|
||||
impl BindGroup {
|
||||
pub fn new(bindings: Vec<Binding>) -> Self {
|
||||
pub fn new(index: u32, bindings: Vec<Binding>) -> Self {
|
||||
BindGroup {
|
||||
bindings,
|
||||
index,
|
||||
bindings: bindings.iter().cloned().collect(),
|
||||
hash: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_hash(&self) -> u64 {
|
||||
pub fn get_hash(&self) -> Option<u64> {
|
||||
self.hash
|
||||
}
|
||||
|
||||
pub fn get_or_update_hash(&mut self) -> u64 {
|
||||
if self.hash.is_none() {
|
||||
self.update_hash();
|
||||
}
|
||||
|
||||
self.hash.unwrap()
|
||||
}
|
||||
|
||||
|
@ -41,14 +80,22 @@ impl BindGroup {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, Clone, Debug)]
|
||||
impl Hash for BindGroup {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.index.hash(state);
|
||||
self.bindings.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct Binding {
|
||||
pub name: String,
|
||||
pub index: u32,
|
||||
pub bind_type: BindType,
|
||||
// TODO: ADD SHADER STAGE VISIBILITY
|
||||
}
|
||||
|
||||
#[derive(Hash, Clone, Debug)]
|
||||
#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum BindType {
|
||||
Uniform {
|
||||
dynamic: bool,
|
||||
|
@ -81,13 +128,13 @@ impl BindType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, Clone, Debug)]
|
||||
#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct UniformProperty {
|
||||
pub name: String,
|
||||
pub property_type: UniformPropertyType,
|
||||
}
|
||||
|
||||
#[derive(Hash, Clone, Debug)]
|
||||
#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum UniformPropertyType {
|
||||
// TODO: Add all types here
|
||||
Int,
|
||||
|
@ -95,6 +142,7 @@ pub enum UniformPropertyType {
|
|||
UVec4,
|
||||
Vec3,
|
||||
Vec4,
|
||||
Mat3,
|
||||
Mat4,
|
||||
Struct(Vec<UniformProperty>),
|
||||
Array(Box<UniformPropertyType>, usize),
|
||||
|
@ -108,6 +156,7 @@ impl UniformPropertyType {
|
|||
UniformPropertyType::UVec4 => 4 * 4,
|
||||
UniformPropertyType::Vec3 => 4 * 3,
|
||||
UniformPropertyType::Vec4 => 4 * 4,
|
||||
UniformPropertyType::Mat3 => 4 * 4 * 3,
|
||||
UniformPropertyType::Mat4 => 4 * 4 * 4,
|
||||
UniformPropertyType::Struct(properties) => properties
|
||||
.iter()
|
||||
|
@ -118,7 +167,7 @@ impl UniformPropertyType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum TextureViewDimension {
|
||||
D1,
|
||||
D2,
|
||||
|
|
|
@ -21,72 +21,76 @@ impl ForwardPipelineBuilder for RenderGraphBuilder {
|
|||
include_str!("forward.frag"),
|
||||
ShaderStage::Fragment,
|
||||
))
|
||||
.add_bind_group(BindGroup::new(vec![
|
||||
Binding {
|
||||
name: "Camera".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![UniformProperty {
|
||||
name: "ViewProj".to_string(),
|
||||
property_type: UniformPropertyType::Mat4,
|
||||
}],
|
||||
},
|
||||
},
|
||||
Binding {
|
||||
name: "Lights".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![
|
||||
UniformProperty {
|
||||
name: "NumLights".to_string(),
|
||||
property_type: UniformPropertyType::UVec4,
|
||||
},
|
||||
UniformProperty {
|
||||
name: "SceneLights".to_string(),
|
||||
property_type: UniformPropertyType::Array(
|
||||
Box::new(UniformPropertyType::Struct(vec![
|
||||
UniformProperty {
|
||||
name: "proj".to_string(),
|
||||
property_type: UniformPropertyType::Mat4,
|
||||
},
|
||||
UniformProperty {
|
||||
name: "pos".to_string(),
|
||||
property_type: UniformPropertyType::Vec4,
|
||||
},
|
||||
UniformProperty {
|
||||
name: "color".to_string(),
|
||||
property_type: UniformPropertyType::Vec4,
|
||||
},
|
||||
])),
|
||||
10, // max lights
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]))
|
||||
.add_bind_group(BindGroup::new(vec![
|
||||
Binding {
|
||||
name: "Object".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: true,
|
||||
properties: vec![UniformProperty {
|
||||
name: "Model".to_string(),
|
||||
property_type: UniformPropertyType::Mat4,
|
||||
}],
|
||||
},
|
||||
},
|
||||
Binding {
|
||||
name: "StandardMaterial_albedo".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: true,
|
||||
properties: vec![UniformProperty {
|
||||
name: "Albedo".to_string(),
|
||||
property_type: UniformPropertyType::Vec4,
|
||||
}],
|
||||
},
|
||||
},
|
||||
]))
|
||||
// .add_bind_group(BindGroup::new(0, vec![
|
||||
// Binding {
|
||||
// index: 0,
|
||||
// name: "Camera".to_string(),
|
||||
// bind_type: BindType::Uniform {
|
||||
// dynamic: false,
|
||||
// properties: vec![UniformProperty {
|
||||
// name: "ViewProj".to_string(),
|
||||
// property_type: UniformPropertyType::Mat4,
|
||||
// }],
|
||||
// },
|
||||
// },
|
||||
// Binding {
|
||||
// index: 1,
|
||||
// name: "Lights".to_string(),
|
||||
// bind_type: BindType::Uniform {
|
||||
// dynamic: false,
|
||||
// properties: vec![
|
||||
// UniformProperty {
|
||||
// name: "NumLights".to_string(),
|
||||
// property_type: UniformPropertyType::UVec4,
|
||||
// },
|
||||
// UniformProperty {
|
||||
// name: "SceneLights".to_string(),
|
||||
// property_type: UniformPropertyType::Array(
|
||||
// Box::new(UniformPropertyType::Struct(vec![
|
||||
// UniformProperty {
|
||||
// name: "proj".to_string(),
|
||||
// property_type: UniformPropertyType::Mat4,
|
||||
// },
|
||||
// UniformProperty {
|
||||
// name: "pos".to_string(),
|
||||
// property_type: UniformPropertyType::Vec4,
|
||||
// },
|
||||
// UniformProperty {
|
||||
// name: "color".to_string(),
|
||||
// property_type: UniformPropertyType::Vec4,
|
||||
// },
|
||||
// ])),
|
||||
// 10, // max lights
|
||||
// ),
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// ]))
|
||||
// .add_bind_group(BindGroup::new(1, vec![
|
||||
// Binding {
|
||||
// index: 0,
|
||||
// name: "Object".to_string(),
|
||||
// bind_type: BindType::Uniform {
|
||||
// dynamic: true,
|
||||
// properties: vec![UniformProperty {
|
||||
// name: "Model".to_string(),
|
||||
// property_type: UniformPropertyType::Mat4,
|
||||
// }],
|
||||
// },
|
||||
// },
|
||||
// Binding {
|
||||
// index: 1,
|
||||
// name: "StandardMaterial_albedo".to_string(),
|
||||
// bind_type: BindType::Uniform {
|
||||
// dynamic: true,
|
||||
// properties: vec![UniformProperty {
|
||||
// name: "Albedo".to_string(),
|
||||
// property_type: UniformPropertyType::Vec4,
|
||||
// }],
|
||||
// },
|
||||
// },
|
||||
// ]))
|
||||
.with_rasterization_state(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
|
|
|
@ -34,7 +34,8 @@ impl ForwardFlatPipelineBuilder for RenderGraphBuilder {
|
|||
include_str!("forward_flat.frag"),
|
||||
ShaderStage::Fragment,
|
||||
))
|
||||
.add_bind_group(BindGroup::new(vec![Binding {
|
||||
.add_bind_group(BindGroup::new(0, vec![Binding {
|
||||
index: 0,
|
||||
name: "Camera".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
|
@ -44,8 +45,9 @@ impl ForwardFlatPipelineBuilder for RenderGraphBuilder {
|
|||
}],
|
||||
},
|
||||
}]))
|
||||
.add_bind_group(BindGroup::new(vec![
|
||||
.add_bind_group(BindGroup::new(1, vec![
|
||||
Binding {
|
||||
index: 0,
|
||||
name: "Object".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: true,
|
||||
|
@ -56,6 +58,7 @@ impl ForwardFlatPipelineBuilder for RenderGraphBuilder {
|
|||
},
|
||||
},
|
||||
Binding {
|
||||
index: 1,
|
||||
name: "StandardMaterial_albedo".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: true,
|
||||
|
|
|
@ -33,7 +33,8 @@ impl UiPipelineBuilder for RenderGraphBuilder {
|
|||
include_str!("ui.frag"),
|
||||
ShaderStage::Fragment,
|
||||
))
|
||||
.add_bind_group(BindGroup::new(vec![Binding {
|
||||
.add_bind_group(BindGroup::new(0, vec![Binding {
|
||||
index: 0,
|
||||
name: "Camera2d".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
|
|
|
@ -4,9 +4,9 @@ use crate::{
|
|||
render::{
|
||||
render_graph_2::{
|
||||
resource_name, update_shader_assignments, BindGroup, BindType,
|
||||
DynamicUniformBufferInfo, PassDescriptor, PipelineDescriptor, RenderGraph, RenderPass,
|
||||
RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor,
|
||||
Renderer, ResourceInfo, TextureDescriptor,
|
||||
DynamicUniformBufferInfo, PassDescriptor, PipelineDescriptor, PipelineLayout,
|
||||
PipelineLayoutType, RenderGraph, RenderPass, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, Renderer, ResourceInfo, TextureDescriptor,
|
||||
},
|
||||
Shader,
|
||||
},
|
||||
|
@ -76,25 +76,37 @@ impl WgpuRenderer {
|
|||
vertex_shader: &Shader,
|
||||
fragment_shader: Option<&Shader>,
|
||||
) -> wgpu::RenderPipeline {
|
||||
let vertex_shader_module = Self::create_shader_module(device, vertex_shader, None);
|
||||
let vertex_spirv = vertex_shader.get_spirv_shader(None);
|
||||
let fragment_spirv = fragment_shader.map(|f| f.get_spirv_shader(None));
|
||||
|
||||
let vertex_shader_module = Self::create_shader_module(device, &vertex_spirv, None);
|
||||
let fragment_shader_module = match fragment_shader {
|
||||
Some(fragment_shader) => {
|
||||
Some(Self::create_shader_module(device, fragment_shader, None))
|
||||
}
|
||||
Some(fragment_spirv) => Some(Self::create_shader_module(device, fragment_spirv, None)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
if let PipelineLayoutType::Reflected(None) = pipeline_descriptor.layout {
|
||||
let mut layouts = vec![vertex_spirv.reflect_layout().unwrap()];
|
||||
|
||||
if let Some(ref fragment_spirv) = fragment_spirv {
|
||||
layouts.push(fragment_spirv.reflect_layout().unwrap());
|
||||
}
|
||||
|
||||
pipeline_descriptor.layout =
|
||||
PipelineLayoutType::Reflected(Some(PipelineLayout::from_shader_layouts(&mut layouts)));
|
||||
}
|
||||
|
||||
let layout = pipeline_descriptor.get_layout_mut().unwrap();
|
||||
|
||||
// setup new bind group layouts
|
||||
for bind_group in pipeline_descriptor.pipeline_layout.bind_groups.iter_mut() {
|
||||
bind_group.update_hash();
|
||||
let bind_group_id = bind_group.get_hash();
|
||||
for bind_group in layout.bind_groups.iter_mut() {
|
||||
let bind_group_id = bind_group.get_or_update_hash();
|
||||
if let None = bind_group_layouts.get(&bind_group_id) {
|
||||
let bind_group_layout_binding = bind_group
|
||||
.bindings
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, binding)| wgpu::BindGroupLayoutBinding {
|
||||
binding: i as u32,
|
||||
.map(|binding| wgpu::BindGroupLayoutBinding {
|
||||
binding: binding.index,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: (&binding.bind_type).into(),
|
||||
})
|
||||
|
@ -109,12 +121,11 @@ impl WgpuRenderer {
|
|||
}
|
||||
|
||||
// collect bind group layout references
|
||||
let bind_group_layouts = pipeline_descriptor
|
||||
.pipeline_layout
|
||||
let bind_group_layouts = layout
|
||||
.bind_groups
|
||||
.iter()
|
||||
.map(|bind_group| {
|
||||
let bind_group_id = bind_group.get_hash();
|
||||
let bind_group_id = bind_group.get_hash().unwrap();
|
||||
bind_group_layouts.get(&bind_group_id).unwrap()
|
||||
})
|
||||
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
||||
|
@ -127,11 +138,11 @@ impl WgpuRenderer {
|
|||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vertex_shader_module,
|
||||
entry_point: &vertex_shader.entry_point,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: match fragment_shader {
|
||||
Some(fragment_shader) => Some(wgpu::ProgrammableStageDescriptor {
|
||||
entry_point: &fragment_shader.entry_point,
|
||||
entry_point: "main",
|
||||
module: fragment_shader_module.as_ref().unwrap(),
|
||||
}),
|
||||
None => None,
|
||||
|
@ -233,7 +244,7 @@ impl WgpuRenderer {
|
|||
|
||||
// TODO: consider moving this to a resource provider
|
||||
fn setup_bind_group(&mut self, bind_group: &BindGroup) -> u64 {
|
||||
let bind_group_id = bind_group.get_hash();
|
||||
let bind_group_id = bind_group.get_hash().unwrap();
|
||||
|
||||
if let None = self.bind_groups.get(&bind_group_id) {
|
||||
let mut unset_uniforms = Vec::new();
|
||||
|
@ -260,12 +271,11 @@ impl WgpuRenderer {
|
|||
let bindings = bind_group
|
||||
.bindings
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, b)| {
|
||||
let resource_info = self.resource_info.get(&b.name).unwrap();
|
||||
.map(|binding| {
|
||||
let resource_info = self.resource_info.get(&binding.name).unwrap();
|
||||
wgpu::Binding {
|
||||
binding: i as u32,
|
||||
resource: match &b.bind_type {
|
||||
binding: binding.index,
|
||||
resource: match &binding.bind_type {
|
||||
BindType::Uniform {
|
||||
dynamic: _,
|
||||
properties: _,
|
||||
|
@ -275,7 +285,7 @@ impl WgpuRenderer {
|
|||
buffer_usage: _,
|
||||
} = resource_info
|
||||
{
|
||||
let buffer = self.buffers.get(&b.name).unwrap();
|
||||
let buffer = self.buffers.get(&binding.name).unwrap();
|
||||
wgpu::BindingResource::Buffer {
|
||||
buffer,
|
||||
range: 0..*size,
|
||||
|
@ -426,7 +436,8 @@ impl Renderer for WgpuRenderer {
|
|||
}
|
||||
|
||||
// create bind groups
|
||||
for bind_group in pipeline_descriptor.pipeline_layout.bind_groups.iter() {
|
||||
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
|
||||
for bind_group in pipeline_layout.bind_groups.iter() {
|
||||
self.setup_bind_group(bind_group);
|
||||
}
|
||||
}
|
||||
|
@ -641,14 +652,9 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
}
|
||||
|
||||
fn setup_bind_groups(&mut self, entity: Option<&Entity>) {
|
||||
for (i, bind_group) in self
|
||||
.pipeline_descriptor
|
||||
.pipeline_layout
|
||||
.bind_groups
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
let bind_group_id = bind_group.get_hash();
|
||||
let pipeline_layout = self.pipeline_descriptor.get_layout().unwrap();
|
||||
for bind_group in pipeline_layout.bind_groups.iter() {
|
||||
let bind_group_id = bind_group.get_hash().unwrap();
|
||||
let bind_group_info = self.renderer.bind_groups.get(&bind_group_id).unwrap();
|
||||
|
||||
let mut dynamic_uniform_indices = Vec::new();
|
||||
|
@ -658,7 +664,7 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
continue;
|
||||
}
|
||||
|
||||
// PERF: This hashmap get is pretty expensive (10 fps per 10000 entities)
|
||||
// PERF: This hashmap get is pretty expensive (10 fps for 10000 entities)
|
||||
if let Some(dynamic_uniform_buffer_info) =
|
||||
self.renderer.dynamic_uniform_buffer_info.get(&binding.name)
|
||||
{
|
||||
|
@ -674,7 +680,7 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
|
||||
// TODO: check to see if bind group is already set
|
||||
self.render_pass.set_bind_group(
|
||||
i as u32,
|
||||
bind_group.index,
|
||||
&bind_group_info.bind_group,
|
||||
dynamic_uniform_indices.as_slice(),
|
||||
);
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use crate::{asset::Handle, render::shader_reflect::get_shader_layout};
|
||||
use crate::{
|
||||
asset::Handle,
|
||||
render::shader_reflect::{get_shader_layout, ShaderLayout},
|
||||
};
|
||||
use std::marker::Copy;
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)]
|
||||
|
@ -50,11 +53,10 @@ pub enum ShaderSource {
|
|||
Glsl(String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Shader {
|
||||
pub source: ShaderSource,
|
||||
pub stage: ShaderStage,
|
||||
pub entry_point: String,
|
||||
// TODO: add "precompile" flag?
|
||||
}
|
||||
|
||||
|
@ -62,29 +64,31 @@ impl Shader {
|
|||
pub fn from_glsl(glsl: &str, stage: ShaderStage) -> Shader {
|
||||
Shader {
|
||||
source: ShaderSource::Glsl(glsl.to_string()),
|
||||
entry_point: "main".to_string(),
|
||||
stage,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_spirv(&self, macros: Option<&[String]>) -> Vec<u32> {
|
||||
let result = match self.source {
|
||||
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 {
|
||||
Shader {
|
||||
source: ShaderSource::Spirv(self.get_spirv(macros)),
|
||||
entry_point: self.entry_point.clone(),
|
||||
stage: self.stage,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reflect_layout(&self) -> Option<ShaderLayout> {
|
||||
if let ShaderSource::Spirv(ref spirv) = self.source {
|
||||
Some(get_shader_layout(spirv.as_slice()))
|
||||
} else {
|
||||
panic!("Cannot reflect layout of non-SpirV shader. Try compiling this shader to SpirV first using self.get_spirv_shader()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
use crate::render::render_graph_2::{BindGroup, UniformPropertyType, Binding, BindType, UniformProperty};
|
||||
use crate::render::render_graph_2::{
|
||||
BindGroup, BindType, Binding, UniformProperty, UniformPropertyType,
|
||||
};
|
||||
use spirv_reflect::{
|
||||
types::{ReflectDescriptorSet, ReflectTypeDescription, ReflectDescriptorBinding, ReflectDescriptorType, ReflectTypeFlags},
|
||||
types::{
|
||||
ReflectDescriptorBinding, ReflectDescriptorSet, ReflectDescriptorType,
|
||||
ReflectTypeDescription, ReflectTypeFlags,
|
||||
},
|
||||
ShaderModule,
|
||||
};
|
||||
use zerocopy::AsBytes;
|
||||
// use rspirv::{binary::Parser, dr::Loader, lift::LiftContext};
|
||||
|
||||
// TODO: pick rspirv vs spirv-reflect
|
||||
// TODO: use rspirv when structured representation is ready. this way we can remove spirv_reflect, which is a non-rust dependency
|
||||
// pub fn get_shader_layout(spirv_data: &[u32]) {
|
||||
// let mut loader = Loader::new(); // You can use your own consumer here.
|
||||
// {
|
||||
|
@ -18,37 +23,39 @@ use zerocopy::AsBytes;
|
|||
// println!("{:?}", structured.types);
|
||||
// }
|
||||
|
||||
pub fn get_shader_layout(spirv_data: &[u32]) {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ShaderLayout {
|
||||
pub bind_groups: Vec<BindGroup>,
|
||||
pub entry_point: String,
|
||||
}
|
||||
|
||||
pub fn get_shader_layout(spirv_data: &[u32]) -> ShaderLayout {
|
||||
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!();
|
||||
ShaderLayout {
|
||||
bind_groups,
|
||||
entry_point: entry_point_name,
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
Err(err) => panic!("Failed to reflect shader layout: {:?}", err)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
BindGroup::new(descriptor_set.set, bindings)
|
||||
}
|
||||
|
||||
fn reflect_binding(binding: &ReflectDescriptorBinding) -> Binding {
|
||||
|
@ -61,10 +68,10 @@ fn reflect_binding(binding: &ReflectDescriptorBinding) -> Binding {
|
|||
_ => panic!("unsupported bind type {:?}", binding.descriptor_type),
|
||||
};
|
||||
|
||||
// println!(" {:?}", binding);
|
||||
Binding{
|
||||
bind_type: bind_type,
|
||||
name: type_description.type_name.to_string()
|
||||
Binding {
|
||||
index: binding.binding,
|
||||
bind_type,
|
||||
name: type_description.type_name.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +83,10 @@ enum NumberType {
|
|||
}
|
||||
|
||||
fn reflect_uniform(type_description: &ReflectTypeDescription) -> UniformProperty {
|
||||
let uniform_property_type = if type_description.type_flags.contains(ReflectTypeFlags::STRUCT) {
|
||||
let uniform_property_type = if type_description
|
||||
.type_flags
|
||||
.contains(ReflectTypeFlags::STRUCT)
|
||||
{
|
||||
reflect_uniform_struct(type_description)
|
||||
} else {
|
||||
reflect_uniform_numeric(type_description)
|
||||
|
@ -89,8 +99,7 @@ fn reflect_uniform(type_description: &ReflectTypeDescription) -> UniformProperty
|
|||
}
|
||||
|
||||
fn reflect_uniform_struct(type_description: &ReflectTypeDescription) -> UniformPropertyType {
|
||||
println!("reflecting struct");
|
||||
let mut properties = Vec::new();
|
||||
let mut properties = Vec::new();
|
||||
for member in type_description.members.iter() {
|
||||
properties.push(reflect_uniform(member));
|
||||
}
|
||||
|
@ -104,9 +113,12 @@ fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> Uniform
|
|||
match traits.numeric.scalar.signedness {
|
||||
0 => NumberType::UInt,
|
||||
1 => NumberType::Int,
|
||||
signedness => panic!("unexpected signedness {}", signedness)
|
||||
signedness => panic!("unexpected signedness {}", signedness),
|
||||
}
|
||||
} else if type_description.type_flags.contains(ReflectTypeFlags::FLOAT) {
|
||||
} else if type_description
|
||||
.type_flags
|
||||
.contains(ReflectTypeFlags::FLOAT)
|
||||
{
|
||||
NumberType::Float
|
||||
} else {
|
||||
panic!("unexpected type flag {:?}", type_description.type_flags);
|
||||
|
@ -114,11 +126,28 @@ fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> Uniform
|
|||
|
||||
// TODO: handle scalar width here
|
||||
|
||||
match (number_type, traits.numeric.vector.component_count) {
|
||||
(NumberType::Int, 1) => UniformPropertyType::Int,
|
||||
(NumberType::Float, 3) => UniformPropertyType::Vec3,
|
||||
(NumberType::Float, 4) => UniformPropertyType::Vec4,
|
||||
(NumberType::UInt, 4) => UniformPropertyType::UVec4,
|
||||
(number_type, component_count) => panic!("unexpected uniform property format {:?} {}", number_type, component_count),
|
||||
if type_description
|
||||
.type_flags
|
||||
.contains(ReflectTypeFlags::MATRIX)
|
||||
{
|
||||
match (number_type, traits.numeric.matrix.column_count, traits.numeric.matrix.row_count) {
|
||||
(NumberType::Float, 3, 3) => UniformPropertyType::Mat3,
|
||||
(NumberType::Float, 4, 4) => UniformPropertyType::Mat4,
|
||||
(number_type, column_count, row_count) => panic!(
|
||||
"unexpected uniform property matrix format {:?} {}x{}",
|
||||
number_type, column_count, row_count
|
||||
),
|
||||
}
|
||||
} else {
|
||||
match (number_type, traits.numeric.vector.component_count) {
|
||||
(NumberType::Int, 1) => UniformPropertyType::Int,
|
||||
(NumberType::Float, 3) => UniformPropertyType::Vec3,
|
||||
(NumberType::Float, 4) => UniformPropertyType::Vec4,
|
||||
(NumberType::UInt, 4) => UniformPropertyType::UVec4,
|
||||
(number_type, component_count) => panic!(
|
||||
"unexpected uniform property format {:?} {}",
|
||||
number_type, component_count
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue