fix dynamic uniforms and unit tests
This commit is contained in:
parent
92c421b5e1
commit
78de2fe2a1
@ -232,8 +232,8 @@ impl AppBuilder {
|
||||
.add_resource_provider(LightResourceProvider::new(10))
|
||||
.add_resource_provider(UiResourceProvider::new())
|
||||
.add_resource_provider(MeshResourceProvider::new())
|
||||
.add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(false))
|
||||
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(false))
|
||||
.add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true))
|
||||
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true))
|
||||
.add_forward_pass()
|
||||
.add_forward_pipeline();
|
||||
// .add_ui_pipeline();
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
use super::BindingDescriptor;
|
||||
use std::{
|
||||
collections::{hash_map::DefaultHasher, BTreeSet},
|
||||
collections::hash_map::DefaultHasher,
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct BindGroupDescriptor {
|
||||
pub index: u32,
|
||||
pub bindings: BTreeSet<BindingDescriptor>,
|
||||
pub bindings: Vec<BindingDescriptor>,
|
||||
pub id: BindGroupDescriptorId,
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ impl BindGroupDescriptor {
|
||||
pub fn new(index: u32, bindings: Vec<BindingDescriptor>) -> Self {
|
||||
let mut descriptor = BindGroupDescriptor {
|
||||
index,
|
||||
bindings: bindings.iter().cloned().collect(),
|
||||
bindings,
|
||||
id: BindGroupDescriptorId(0),
|
||||
};
|
||||
|
||||
@ -42,11 +42,3 @@ impl Hash for BindGroupDescriptor {
|
||||
self.bindings.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for BindGroupDescriptor {
|
||||
fn eq(&self, other: &BindGroupDescriptor) -> bool {
|
||||
self.index == other.index && self.bindings == other.bindings
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for BindGroupDescriptor {}
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
use super::{PipelineDescriptor, PipelineLayout, PipelineLayoutType};
|
||||
use super::{BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType};
|
||||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
prelude::{Renderable, Resources, Shader, World},
|
||||
render::{
|
||||
render_graph::RenderGraph,
|
||||
render_resource::{RenderResourceAssignments, RenderResourceAssignmentsId},
|
||||
render_resource::{
|
||||
BufferInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo,
|
||||
},
|
||||
renderer::Renderer,
|
||||
shader::ShaderSource,
|
||||
},
|
||||
};
|
||||
@ -31,6 +34,8 @@ impl PipelineCompiler {
|
||||
shader_storage: &AssetStorage<Shader>,
|
||||
render_graph: &RenderGraph,
|
||||
pipeline_descriptor: &mut PipelineDescriptor,
|
||||
renderer: &dyn Renderer,
|
||||
render_resource_assignments: &RenderResourceAssignments,
|
||||
) {
|
||||
let vertex_spirv = shader_storage
|
||||
.get(&pipeline_descriptor.shader_stages.vertex)
|
||||
@ -49,8 +54,25 @@ impl PipelineCompiler {
|
||||
let mut layout = PipelineLayout::from_shader_layouts(&mut layouts);
|
||||
layout.sync_vertex_buffer_descriptors_with_render_graph(render_graph);
|
||||
|
||||
for mut _bind_group in layout.bind_groups.iter_mut() {
|
||||
// TODO: set dynamic here
|
||||
// set binding uniforms to dynamic if render resource assignments use dynamic
|
||||
// TODO: this breaks down if different assignments have different "dynamic" status or if the dynamic status changes.
|
||||
// the fix would be to add "dynamic bindings" to the existing shader_def sets. this would ensure new pipelines are generated
|
||||
// for all permutations of dynamic/non-dynamic
|
||||
for bind_group in layout.bind_groups.iter_mut() {
|
||||
for binding in bind_group.bindings.iter_mut() {
|
||||
if let Some(render_resource) = render_resource_assignments.get(&binding.name) {
|
||||
if let Some(ResourceInfo::Buffer(BufferInfo { is_dynamic, .. })) =
|
||||
renderer.get_resource_info(render_resource)
|
||||
{
|
||||
if let BindType::Uniform {
|
||||
ref mut dynamic, ..
|
||||
} = binding.bind_type
|
||||
{
|
||||
*dynamic = *is_dynamic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pipeline_descriptor.layout = PipelineLayoutType::Reflected(Some(layout));
|
||||
@ -93,26 +115,35 @@ impl PipelineCompiler {
|
||||
&mut self,
|
||||
render_graph: &RenderGraph,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
renderer: &dyn Renderer,
|
||||
pipeline_descriptor: &PipelineDescriptor,
|
||||
shader_defs: &HashSet<String>,
|
||||
render_resource_assignments: &RenderResourceAssignments,
|
||||
) -> PipelineDescriptor {
|
||||
let mut compiled_pipeline_descriptor = pipeline_descriptor.clone();
|
||||
|
||||
compiled_pipeline_descriptor.shader_stages.vertex = self.compile_shader(
|
||||
shader_storage,
|
||||
&pipeline_descriptor.shader_stages.vertex,
|
||||
&shader_defs,
|
||||
&render_resource_assignments.shader_defs,
|
||||
);
|
||||
compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor
|
||||
.shader_stages
|
||||
.fragment
|
||||
.as_ref()
|
||||
.map(|fragment| self.compile_shader(shader_storage, fragment, &shader_defs));
|
||||
.map(|fragment| {
|
||||
self.compile_shader(
|
||||
shader_storage,
|
||||
fragment,
|
||||
&render_resource_assignments.shader_defs,
|
||||
)
|
||||
});
|
||||
|
||||
Self::reflect_layout(
|
||||
shader_storage,
|
||||
render_graph,
|
||||
&mut compiled_pipeline_descriptor,
|
||||
renderer,
|
||||
render_resource_assignments,
|
||||
);
|
||||
|
||||
compiled_pipeline_descriptor
|
||||
@ -122,6 +153,7 @@ impl PipelineCompiler {
|
||||
&mut self,
|
||||
render_graph: &RenderGraph,
|
||||
shader_pipeline_assignments: &mut ShaderPipelineAssignments,
|
||||
renderer: &dyn Renderer,
|
||||
pipeline_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
pipelines: &[Handle<PipelineDescriptor>],
|
||||
@ -147,8 +179,9 @@ impl PipelineCompiler {
|
||||
let compiled_pipeline = self.compile_pipeline(
|
||||
render_graph,
|
||||
shader_storage,
|
||||
renderer,
|
||||
pipeline_descriptor,
|
||||
&render_resource_assignments.shader_defs,
|
||||
render_resource_assignments,
|
||||
);
|
||||
let compiled_pipeline_handle = pipeline_storage.add(compiled_pipeline);
|
||||
|
||||
@ -203,7 +236,7 @@ impl ShaderPipelineAssignments {
|
||||
}
|
||||
|
||||
// TODO: make this a system
|
||||
pub fn update_shader_assignments(world: &mut World, resources: &mut Resources) {
|
||||
pub fn update_shader_assignments(world: &mut World, resources: &mut Resources, renderer: &dyn Renderer) {
|
||||
// PERF: this seems like a lot of work for things that don't change that often.
|
||||
// lots of string + hashset allocations. sees uniform_resource_provider for more context
|
||||
{
|
||||
@ -229,6 +262,7 @@ pub fn update_shader_assignments(world: &mut World, resources: &mut Resources) {
|
||||
pipeline_compiler.update_shader_assignments(
|
||||
&mut render_graph,
|
||||
&mut shader_pipeline_assignments,
|
||||
renderer,
|
||||
&mut pipeline_descriptor_storage,
|
||||
&mut shader_storage,
|
||||
&renderable.pipelines,
|
||||
|
||||
@ -26,7 +26,7 @@ impl PipelineLayout {
|
||||
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());
|
||||
bind_group.bindings.push(shader_binding.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,7 +183,9 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
expected_batch.add_entity(entities[0]);
|
||||
assert_eq!(asset_batchers.get_batch2(a1, b1).unwrap(), &expected_batch);
|
||||
let actual_batch = asset_batchers.get_batch2(a1, b1).unwrap();
|
||||
copy_ignored_fields(actual_batch, &mut expected_batch);
|
||||
assert_eq!(actual_batch, &expected_batch);
|
||||
asset_batchers.set_entity_handle(entities[0], c1);
|
||||
|
||||
asset_batchers.set_entity_handle(entities[1], a1);
|
||||
@ -196,7 +198,9 @@ mod tests {
|
||||
};
|
||||
expected_batch.add_entity(entities[0]);
|
||||
expected_batch.add_entity(entities[1]);
|
||||
assert_eq!(asset_batchers.get_batch2(a1, b1).unwrap(), &expected_batch);
|
||||
let actual_batch = asset_batchers.get_batch2(a1, b1).unwrap();
|
||||
copy_ignored_fields(actual_batch, &mut expected_batch);
|
||||
assert_eq!(actual_batch, &expected_batch);
|
||||
|
||||
// uncreated batches are empty
|
||||
assert_eq!(asset_batchers.get_batch2(a1, c1), None);
|
||||
@ -239,6 +243,11 @@ mod tests {
|
||||
),
|
||||
];
|
||||
expected_batches.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
// copy ignored fields
|
||||
batches
|
||||
.iter()
|
||||
.zip(expected_batches.iter_mut())
|
||||
.for_each(|((_, ref actual), (_, ref mut expected))| copy_ignored_fields(actual, expected));
|
||||
assert_eq!(
|
||||
batches,
|
||||
expected_batches
|
||||
@ -247,4 +256,8 @@ mod tests {
|
||||
.collect::<Vec<(&BatchKey2, &Batch)>>()
|
||||
);
|
||||
}
|
||||
|
||||
fn copy_ignored_fields(source: &Batch, destination: &mut Batch) {
|
||||
destination.render_resource_assignments.id = source.render_resource_assignments.id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,6 @@ pub trait Renderer {
|
||||
}
|
||||
|
||||
pub trait RenderPass {
|
||||
// TODO: consider using static dispatch for the renderer: Renderer<WgpuBackend>. compare compile times
|
||||
fn get_renderer(&self) -> &dyn Renderer;
|
||||
fn get_pipeline_descriptor(&self) -> &PipelineDescriptor;
|
||||
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64);
|
||||
|
||||
@ -384,7 +384,7 @@ impl Renderer for WgpuRenderer {
|
||||
);
|
||||
|
||||
self.update_resource_providers(world, resources);
|
||||
update_shader_assignments(world, resources);
|
||||
update_shader_assignments(world, resources, self);
|
||||
self.create_queued_textures(resources);
|
||||
|
||||
let mut encoder = self.encoder.take().unwrap();
|
||||
|
||||
@ -28,7 +28,7 @@ use zerocopy::AsBytes;
|
||||
// println!("{:?}", structured.types);
|
||||
// }
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ShaderLayout {
|
||||
pub bind_groups: Vec<BindGroupDescriptor>,
|
||||
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user