From 478d4752198c4780d151240a7d3cc0f45617ab0d Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sat, 15 Feb 2020 13:58:40 -0800 Subject: [PATCH] more shader assignment work --- src/app/app_builder.rs | 2 + src/asset/mod.rs | 8 +++- src/render/passes/forward/forward_pipeline.rs | 4 +- src/render/passes/forward_instanced/mod.rs | 2 +- src/render/passes/forward_shadow/mod.rs | 2 +- src/render/passes/shadow/shadow_pipeline.rs | 2 +- src/render/passes/ui/mod.rs | 2 +- .../draw_targets/mesh_draw_target.rs | 2 +- .../draw_targets/ui_draw_target.rs | 2 +- src/render/render_graph_2/renderable.rs | 41 +++++++++++++++++-- src/render/shader.rs | 5 ++- 11 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/app/app_builder.rs b/src/app/app_builder.rs index 5276602113..2f4d89dd8f 100644 --- a/src/app/app_builder.rs +++ b/src/app/app_builder.rs @@ -16,6 +16,7 @@ use crate::{ }; use bevy_transform::{prelude::LocalToWorld, transform_system_bundle}; +use render_graph_2::CompiledShaderMap; use std::collections::HashMap; pub struct AppBuilder { @@ -166,6 +167,7 @@ impl AppBuilder { resources.insert(AssetStorage::::new()); resources.insert(AssetStorage::::new()); resources.insert(ShaderAssignments::new()); + resources.insert(CompiledShaderMap::new()); self } diff --git a/src/asset/mod.rs b/src/asset/mod.rs index a2ad7d4126..00a30068ec 100644 --- a/src/asset/mod.rs +++ b/src/asset/mod.rs @@ -8,7 +8,7 @@ pub use texture::*; use std::{collections::HashMap, marker::PhantomData}; -#[derive(Hash)] +#[derive(Hash, Eq, PartialEq)] pub struct Handle { pub id: usize, marker: PhantomData, @@ -75,7 +75,11 @@ impl AssetStorage { handle } - pub fn get(&mut self, id: usize) -> Option<&mut T> { + pub fn get_id(&mut self, id: usize) -> Option<&mut T> { self.assets.get_mut(&id) } + + pub fn get(&mut self, handle: &Handle) -> Option<&mut T> { + self.assets.get_mut(&handle.id) + } } diff --git a/src/render/passes/forward/forward_pipeline.rs b/src/render/passes/forward/forward_pipeline.rs index 097e83ca63..128b214b21 100644 --- a/src/render/passes/forward/forward_pipeline.rs +++ b/src/render/passes/forward/forward_pipeline.rs @@ -157,14 +157,14 @@ impl Pipeline for ForwardPipeline { } if should_load_mesh { - if let Some(mesh_asset) = mesh_storage.get(mesh.id) { + if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { mesh_asset.setup_buffers(&render_graph.device); pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); }; } - if let Some(ref mesh_asset) = mesh_storage.get(mesh.id) { + if let Some(ref mesh_asset) = mesh_storage.get_id(mesh.id) { pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1); }; diff --git a/src/render/passes/forward_instanced/mod.rs b/src/render/passes/forward_instanced/mod.rs index ca66974f92..75099ab869 100644 --- a/src/render/passes/forward_instanced/mod.rs +++ b/src/render/passes/forward_instanced/mod.rs @@ -285,7 +285,7 @@ impl Pipeline for ForwardInstancedPipeline { let mut mesh_storage = world.resources.get_mut::>().unwrap(); for instance_buffer_info in self.instance_buffer_infos.as_ref().unwrap().iter() { - if let Some(mesh_asset) = mesh_storage.get(instance_buffer_info.mesh_id) { + if let Some(mesh_asset) = mesh_storage.get_id(instance_buffer_info.mesh_id) { mesh_asset.setup_buffers(&render_graph.device); pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); diff --git a/src/render/passes/forward_shadow/mod.rs b/src/render/passes/forward_shadow/mod.rs index cd7f233ea4..279f071214 100644 --- a/src/render/passes/forward_shadow/mod.rs +++ b/src/render/passes/forward_shadow/mod.rs @@ -176,7 +176,7 @@ impl Pipeline for ForwardShadowPassNew { let mut mesh_storage = world.resources.get_mut::>().unwrap(); for (material, mesh) in mesh_query.iter(world) { - if let Some(mesh_asset) = mesh_storage.get(mesh.id) { + if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { mesh_asset.setup_buffers(&render_graph.device); pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); diff --git a/src/render/passes/shadow/shadow_pipeline.rs b/src/render/passes/shadow/shadow_pipeline.rs index 582eea8dd2..e357b761a0 100644 --- a/src/render/passes/shadow/shadow_pipeline.rs +++ b/src/render/passes/shadow/shadow_pipeline.rs @@ -166,7 +166,7 @@ impl Pipeline for ShadowPipeline { let mut mesh_storage = world.resources.get_mut::>().unwrap(); for (material, mesh) in mesh_query.iter(world) { - if let Some(mesh_asset) = mesh_storage.get(mesh.id) { + if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { mesh_asset.setup_buffers(&render_graph.device); pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); diff --git a/src/render/passes/ui/mod.rs b/src/render/passes/ui/mod.rs index 9b191c36e3..528792de9e 100644 --- a/src/render/passes/ui/mod.rs +++ b/src/render/passes/ui/mod.rs @@ -242,7 +242,7 @@ impl Pipeline for UiPipeline { let mut mesh_storage = world.resources.get_mut::>().unwrap(); for instance_buffer_info in instance_buffer_infos.as_ref().unwrap().iter() { - if let Some(mesh_asset) = mesh_storage.get(instance_buffer_info.mesh_id) { + if let Some(mesh_asset) = mesh_storage.get_id(instance_buffer_info.mesh_id) { mesh_asset.setup_buffers(&render_graph.device); pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); diff --git a/src/render/render_graph_2/draw_targets/mesh_draw_target.rs b/src/render/render_graph_2/draw_targets/mesh_draw_target.rs index c6b3e64ef2..8b5b1f7cf5 100644 --- a/src/render/render_graph_2/draw_targets/mesh_draw_target.rs +++ b/src/render/render_graph_2/draw_targets/mesh_draw_target.rs @@ -26,7 +26,7 @@ pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) { } if should_load_mesh { - if let Some(mesh_asset) = mesh_storage.get(mesh.id) { + if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { let renderer = render_pass.get_renderer(); renderer.create_buffer_with_data( resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME, diff --git a/src/render/render_graph_2/draw_targets/ui_draw_target.rs b/src/render/render_graph_2/draw_targets/ui_draw_target.rs index 927e2975e1..6d4040e062 100644 --- a/src/render/render_graph_2/draw_targets/ui_draw_target.rs +++ b/src/render/render_graph_2/draw_targets/ui_draw_target.rs @@ -20,7 +20,7 @@ pub fn ui_draw_target(world: &World, render_pass: &mut dyn RenderPass) { }; if let Some((instance_count, mesh_id)) = result { - if let Some(mesh_asset) = mesh_storage.get(mesh_id) { + if let Some(mesh_asset) = mesh_storage.get_id(mesh_id) { renderer.create_buffer_with_data( resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME, mesh_asset.vertices.as_bytes(), diff --git a/src/render/render_graph_2/renderable.rs b/src/render/render_graph_2/renderable.rs index 93999abe94..f414cd2232 100644 --- a/src/render/render_graph_2/renderable.rs +++ b/src/render/render_graph_2/renderable.rs @@ -1,4 +1,7 @@ -use crate::{asset::{AssetStorage, Handle}, render::Shader, render::render_graph_2::RenderGraph}; +use crate::{ + asset::{AssetStorage, Handle}, + render::{render_graph_2::RenderGraph, Shader}, +}; use legion::prelude::*; use std::collections::{HashMap, HashSet}; @@ -18,6 +21,19 @@ impl Default for Renderable { } } +pub struct CompiledShaderMap { + // TODO: need macro hash lookup + pub source_to_compiled: HashMap, Vec<(HashSet, Handle)>>, +} + +impl CompiledShaderMap { + pub fn new() -> Self { + CompiledShaderMap { + source_to_compiled: HashMap::new(), + } + } +} + pub struct ShaderAssignments { pub assignments: HashMap>, } @@ -35,10 +51,27 @@ pub fn update_shader_assignments(world: &mut World, render_graph: &mut RenderGra // lots of string + hashset allocations. sees uniform_resource_provider for more context { let shader_assignments = world.resources.get_mut::().unwrap(); - let shader_storage = world.resources.get_mut::>().unwrap(); + let mut compiled_shader_map = world.resources.get_mut::().unwrap(); + let mut shader_storage = world.resources.get_mut::>().unwrap(); for (entity, renderable) in >::query().iter_entities(world) { for shader in renderable.shaders.iter() { - + if let None = compiled_shader_map.source_to_compiled.get(shader) { + compiled_shader_map + .source_to_compiled + .insert(shader.clone(), Vec::new()); + } + + let compiled_shaders = compiled_shader_map.source_to_compiled.get_mut(shader).unwrap(); + if let None = compiled_shaders.iter().find(|(shader_defs, _shader)| *shader_defs == renderable.shader_defs) { + let shader_resource = shader_storage.get(shader).unwrap(); + let shader_def_vec = renderable.shader_defs.iter().cloned().collect::>(); + let compiled_shader = shader_resource.get_spirv_shader(Some(&shader_def_vec)); + compiled_shaders.push((renderable.shader_defs.clone(), shader.clone())); + let compiled_shader_handle = shader_storage.add(compiled_shader); + // TODO: collecting assigments in a map means they won't be removed when the macro changes + // TODO: need to somehow grab base shader's pipeline, then copy it + // shader_assignments.assignments.insert() + } } } } @@ -47,4 +80,4 @@ pub fn update_shader_assignments(world: &mut World, render_graph: &mut RenderGra for mut renderable in >::query().iter_mut(world) { renderable.shader_defs = HashSet::new(); } -} \ No newline at end of file +} diff --git a/src/render/shader.rs b/src/render/shader.rs index 7d28247f6f..03df701cd6 100644 --- a/src/render/shader.rs +++ b/src/render/shader.rs @@ -1,6 +1,6 @@ use std::marker::Copy; -#[derive(Copy, Clone)] +#[derive(Hash, Eq, PartialEq, Copy, Clone)] pub enum ShaderStage { Vertex, Fragment, @@ -43,15 +43,18 @@ pub fn glsl_to_spirv( binary_result.as_binary().into() } +#[derive(Hash, Eq, PartialEq)] pub enum ShaderSource { Spirv(Vec), Glsl(String), } +#[derive(Hash, Eq, PartialEq)] pub struct Shader { pub source: ShaderSource, pub stage: ShaderStage, pub entry_point: String, + // TODO: add "precompile" flag? } impl Shader {