RenderResourceAssignment refactor

This commit is contained in:
Carter Anderson 2020-05-11 13:55:23 -07:00
parent ef2e5a1ba3
commit 7a71873a32
12 changed files with 206 additions and 184 deletions

View File

@ -1,6 +1,8 @@
use bevy_render::{ use bevy_render::{
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, render_resource::{
resource_name, BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
},
renderer::{RenderContext, RenderResources}, renderer::{RenderContext, RenderResources},
}; };
@ -78,7 +80,14 @@ impl SystemNode for LightsNode {
| BufferUsage::COPY_DST, | BufferUsage::COPY_DST,
..Default::default() ..Default::default()
}); });
render_resource_assignments.set(resource_name::uniform::LIGHTS, buffer); render_resource_assignments.set(
resource_name::uniform::LIGHTS,
RenderResourceAssignment::Buffer {
resource: buffer,
range: 0..light_uniform_size as u64,
dynamic_index: None,
},
);
light_buffer = Some(buffer); light_buffer = Some(buffer);
} }

View File

@ -4,12 +4,15 @@ use super::{
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat, CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat,
PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor, PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor,
}, },
PipelineLayout, VertexBufferDescriptors, BindType, BindType, PipelineLayout, VertexBufferDescriptors,
}; };
use crate::{ use crate::{
render_resource::{ResourceInfo, RenderResourceAssignments, BufferInfo}, render_resource::{
BufferInfo, RenderResourceAssignment, RenderResourceAssignments, ResourceInfo,
},
renderer::RenderResourceContext,
shader::{Shader, ShaderStages}, shader::{Shader, ShaderStages},
texture::TextureFormat, renderer::RenderResourceContext, texture::TextureFormat,
}; };
use bevy_asset::AssetStorage; use bevy_asset::AssetStorage;
@ -141,14 +144,14 @@ impl PipelineDescriptor {
/// If `vertex_buffer_descriptors` is set, the pipeline's vertex buffers /// If `vertex_buffer_descriptors` is set, the pipeline's vertex buffers
/// will inherit their layouts from global descriptors, otherwise the layout will be assumed to be complete / local. /// will inherit their layouts from global descriptors, otherwise the layout will be assumed to be complete / local.
/// ///
/// If `dynamic_uniform_lookup` is set, shader uniforms will be set to "dynamic" if there is a matching "dynamic uniform" /// If `render_resource_assignments` is set, shader uniforms will be set to "dynamic" if there is a matching "dynamic uniform"
/// render resource. /// render resource.
pub fn reflect_layout( pub fn reflect_layout(
&mut self, &mut self,
shaders: &AssetStorage<Shader>, shaders: &AssetStorage<Shader>,
bevy_conventions: bool, bevy_conventions: bool,
vertex_buffer_descriptors: Option<&VertexBufferDescriptors>, vertex_buffer_descriptors: Option<&VertexBufferDescriptors>,
dynamic_uniform_lookup: Option<(&RenderResourceAssignments, &dyn RenderResourceContext)>, render_resource_assignments: Option<&RenderResourceAssignments>,
) { ) {
let vertex_spirv = shaders.get(&self.shader_stages.vertex).unwrap(); let vertex_spirv = shaders.get(&self.shader_stages.vertex).unwrap();
let fragment_spirv = self let fragment_spirv = self
@ -167,31 +170,24 @@ impl PipelineDescriptor {
layout.sync_vertex_buffer_descriptors(vertex_buffer_descriptors); layout.sync_vertex_buffer_descriptors(vertex_buffer_descriptors);
} }
if let Some((render_resource_assignments, render_resource_context)) = dynamic_uniform_lookup { if let Some(render_resource_assignments) = render_resource_assignments
{
// set binding uniforms to dynamic if render resource assignments use dynamic // 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. // 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 // 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 all permutations of dynamic/non-dynamic
for bind_group in layout.bind_groups.iter_mut() { for bind_group in layout.bind_groups.iter_mut() {
for binding in bind_group.bindings.iter_mut() { for binding in bind_group.bindings.iter_mut() {
if let Some(render_resource) = render_resource_assignments.get(&binding.name) { if let Some(RenderResourceAssignment::Buffer { dynamic_index: Some(_), .. }) =
render_resource_context.get_resource_info( render_resource_assignments.get(&binding.name)
render_resource,
&mut |resource_info| {
if let Some(ResourceInfo::Buffer(BufferInfo {
is_dynamic, ..
})) = resource_info
{ {
if let BindType::Uniform { if let BindType::Uniform {
ref mut dynamic, .. ref mut dynamic, ..
} = binding.bind_type } = binding.bind_type
{ {
*dynamic = *is_dynamic *dynamic = true;
} }
} }
},
);
}
} }
} }
} }

View File

@ -84,7 +84,6 @@ impl PipelineCompiler {
&mut self, &mut self,
vertex_buffer_descriptors: &VertexBufferDescriptors, vertex_buffer_descriptors: &VertexBufferDescriptors,
shaders: &mut AssetStorage<Shader>, shaders: &mut AssetStorage<Shader>,
render_resource_context: &dyn RenderResourceContext,
pipeline_descriptor: &PipelineDescriptor, pipeline_descriptor: &PipelineDescriptor,
render_resource_assignments: &RenderResourceAssignments, render_resource_assignments: &RenderResourceAssignments,
) -> PipelineDescriptor { ) -> PipelineDescriptor {
@ -115,7 +114,7 @@ impl PipelineCompiler {
shaders, shaders,
true, true,
Some(vertex_buffer_descriptors), Some(vertex_buffer_descriptors),
Some((render_resource_assignments, render_resource_context)), Some(render_resource_assignments),
); );
compiled_pipeline_descriptor.primitive_topology = render_resource_assignments compiled_pipeline_descriptor.primitive_topology = render_resource_assignments
@ -128,7 +127,6 @@ impl PipelineCompiler {
&mut self, &mut self,
vertex_buffer_descriptors: &VertexBufferDescriptors, vertex_buffer_descriptors: &VertexBufferDescriptors,
shader_pipeline_assignments: &mut PipelineAssignments, shader_pipeline_assignments: &mut PipelineAssignments,
render_resource_context: &dyn RenderResourceContext,
pipeline_storage: &mut AssetStorage<PipelineDescriptor>, pipeline_storage: &mut AssetStorage<PipelineDescriptor>,
shader_storage: &mut AssetStorage<Shader>, shader_storage: &mut AssetStorage<Shader>,
pipelines: &[Handle<PipelineDescriptor>], pipelines: &[Handle<PipelineDescriptor>],
@ -154,7 +152,6 @@ impl PipelineCompiler {
let compiled_pipeline = self.compile_pipeline( let compiled_pipeline = self.compile_pipeline(
vertex_buffer_descriptors, vertex_buffer_descriptors,
shader_storage, shader_storage,
render_resource_context,
pipeline_descriptor, pipeline_descriptor,
render_resource_assignments, render_resource_assignments,
); );
@ -230,7 +227,6 @@ pub fn update_shader_assignments(world: &mut World, resources: &Resources) {
let mut pipeline_compiler = resources.get_mut::<PipelineCompiler>().unwrap(); let mut pipeline_compiler = resources.get_mut::<PipelineCompiler>().unwrap();
let mut shader_storage = resources.get_mut::<AssetStorage<Shader>>().unwrap(); let mut shader_storage = resources.get_mut::<AssetStorage<Shader>>().unwrap();
let vertex_buffer_descriptors = resources.get::<VertexBufferDescriptors>().unwrap(); let vertex_buffer_descriptors = resources.get::<VertexBufferDescriptors>().unwrap();
let render_resources = resources.get::<RenderResources>().unwrap();
let mut pipeline_descriptor_storage = resources let mut pipeline_descriptor_storage = resources
.get_mut::<AssetStorage<PipelineDescriptor>>() .get_mut::<AssetStorage<PipelineDescriptor>>()
.unwrap(); .unwrap();
@ -248,7 +244,6 @@ pub fn update_shader_assignments(world: &mut World, resources: &Resources) {
pipeline_compiler.update_shader_assignments( pipeline_compiler.update_shader_assignments(
&vertex_buffer_descriptors, &vertex_buffer_descriptors,
&mut shader_pipeline_assignments, &mut shader_pipeline_assignments,
&*render_resources.context,
&mut pipeline_descriptor_storage, &mut pipeline_descriptor_storage,
&mut shader_storage, &mut shader_storage,
&renderable.pipelines, &renderable.pipelines,

View File

@ -4,7 +4,7 @@ use bevy_window::WindowResized;
use crate::{ use crate::{
camera::{ActiveCamera2d, Camera}, camera::{ActiveCamera2d, Camera},
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments, RenderResourceAssignment},
renderer::{RenderContext, RenderResources}, renderer::{RenderContext, RenderResources},
}; };
@ -52,12 +52,20 @@ impl SystemNode for Camera2dNode {
query| { query| {
let render_resources = &render_resource_context.context; let render_resources = &render_resource_context.context;
if camera_buffer.is_none() { if camera_buffer.is_none() {
let size = std::mem::size_of::<[[f32; 4]; 4]>();
let buffer = render_resources.create_buffer(BufferInfo { let buffer = render_resources.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>(), size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default() ..Default::default()
}); });
render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer); render_resource_assignments.set(
resource_name::uniform::CAMERA2D,
RenderResourceAssignment::Buffer {
resource: buffer,
range: 0..size as u64,
dynamic_index: None,
},
);
camera_buffer = Some(buffer); camera_buffer = Some(buffer);
} }

View File

@ -1,6 +1,8 @@
use crate::{ use crate::{
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, render_resource::{
resource_name, BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
},
renderer::{RenderContext, RenderResources}, renderer::{RenderContext, RenderResources},
ActiveCamera, Camera, ActiveCamera, Camera,
}; };
@ -52,12 +54,20 @@ impl SystemNode for CameraNode {
query| { query| {
let render_resources = &render_resource_context.context; let render_resources = &render_resource_context.context;
if camera_buffer.is_none() { if camera_buffer.is_none() {
let size = std::mem::size_of::<[[f32; 4]; 4]>();
let buffer = render_resources.create_buffer(BufferInfo { let buffer = render_resources.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>(), size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default() ..Default::default()
}); });
render_resource_assignments.set(resource_name::uniform::CAMERA, buffer); render_resource_assignments.set(
resource_name::uniform::CAMERA,
RenderResourceAssignment::Buffer {
resource: buffer,
range: 0..size as u64,
dynamic_index: None,
},
);
camera_buffer = Some(buffer); camera_buffer = Some(buffer);
} }

View File

@ -2,8 +2,8 @@ use crate::{
pipeline::VertexBufferDescriptors, pipeline::VertexBufferDescriptors,
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
render_resource::{ render_resource::{
BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignment,
RenderResourceAssignmentsId, ResourceInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo,
}, },
renderer::{RenderContext, RenderResourceContext, RenderResources}, renderer::{RenderContext, RenderResourceContext, RenderResources},
shader::{AsUniforms, FieldBindType}, shader::{AsUniforms, FieldBindType},
@ -224,39 +224,37 @@ where
let (_name, uniform_buffer_status) = self.uniform_arrays[i].as_mut().unwrap(); let (_name, uniform_buffer_status) = self.uniform_arrays[i].as_mut().unwrap();
let (target_buffer, target_offset) = if dynamic_uniforms { let (target_buffer, target_offset) = if dynamic_uniforms {
let buffer = uniform_buffer_status.buffer.unwrap(); let buffer = uniform_buffer_status.buffer.unwrap();
let mut offset = 0;
render_resources.get_resource_info(buffer, &mut |resource_info| {
if let Some(ResourceInfo::Buffer(BufferInfo {
array_info: Some(ref array_info),
is_dynamic: true,
..
})) = resource_info
{
let index = uniform_buffer_status let index = uniform_buffer_status
.get_or_assign_index(render_resource_assignments.id); .get_or_assign_index(render_resource_assignments.id);
render_resource_assignments.set_indexed( render_resource_assignments.set(
&field_info.uniform_name, &field_info.uniform_name,
buffer, RenderResourceAssignment::Buffer {
(index * array_info.item_size) as u32, resource: buffer,
dynamic_index: Some(
(index * uniform_buffer_status.aligned_size) as u32,
),
range: 0..size as u64,
},
); );
offset = index * uniform_buffer_status.aligned_size; (buffer, index * uniform_buffer_status.aligned_size)
} else { } else {
panic!("Expected a dynamic uniform buffer"); let resource =
} match render_resource_assignments.get(field_info.uniform_name) {
}); Some(assignment) => assignment.get_resource(),
(buffer, offset)
} else {
let resource = match render_resource_assignments
.get(field_info.uniform_name)
{
Some(render_resource) => render_resource,
None => { None => {
let resource = render_resources.create_buffer(BufferInfo { let resource = render_resources.create_buffer(BufferInfo {
size, size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default() ..Default::default()
}); });
render_resource_assignments.set(&field_info.uniform_name, resource); render_resource_assignments.set(
&field_info.uniform_name,
RenderResourceAssignment::Buffer {
resource,
range: 0..size as u64,
dynamic_index: None,
},
);
resource resource
} }
}; };
@ -791,8 +789,14 @@ fn setup_uniform_texture_resources<T>(
} }
}; };
render_resource_assignments.set(field_info.texture_name, texture_resource); render_resource_assignments.set(
render_resource_assignments.set(field_info.sampler_name, sampler_resource); field_info.texture_name,
RenderResourceAssignment::Texture(texture_resource),
);
render_resource_assignments.set(
field_info.sampler_name,
RenderResourceAssignment::Sampler(sampler_resource),
);
} }
_ => {} _ => {}
} }

View File

@ -2,46 +2,63 @@ use super::RenderResource;
use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization}; use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization};
use std::{ use std::{
collections::{hash_map::DefaultHasher, HashMap, HashSet}, collections::{hash_map::DefaultHasher, HashMap, HashSet},
hash::{Hash, Hasher}, hash::{Hash, Hasher}, ops::Range,
}; };
use uuid::Uuid; use uuid::Uuid;
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum RenderResourceAssignment {
Buffer {
resource: RenderResource,
range: Range<u64>,
dynamic_index: Option<u32>,
},
Texture(RenderResource),
Sampler(RenderResource),
}
impl RenderResourceAssignment {
pub fn get_resource(&self) -> RenderResource {
match self {
RenderResourceAssignment::Buffer { resource, .. } => *resource,
RenderResourceAssignment::Texture(resource) => *resource,
RenderResourceAssignment::Sampler(resource) => *resource,
}
}
}
#[derive(Eq, PartialEq, Debug)]
pub struct RenderResourceSet {
pub id: RenderResourceSetId,
pub dynamic_uniform_indices: Option<Vec<u32>>,
}
// PERF: if the assignments are scoped to a specific pipeline layout, then names could be replaced with indices here for a perf boost // PERF: if the assignments are scoped to a specific pipeline layout, then names could be replaced with indices here for a perf boost
#[derive(Eq, PartialEq, Debug, Default)] #[derive(Eq, PartialEq, Debug, Default)]
pub struct RenderResourceAssignments { pub struct RenderResourceAssignments {
pub id: RenderResourceAssignmentsId, pub id: RenderResourceAssignmentsId,
render_resources: HashMap<String, (RenderResource, Option<u32>)>, render_resources: HashMap<String, RenderResourceAssignment>,
vertex_buffers: HashMap<String, (RenderResource, Option<RenderResource>)>, vertex_buffers: HashMap<String, (RenderResource, Option<RenderResource>)>,
bind_group_resource_sets: bind_group_resource_sets:
HashMap<BindGroupDescriptorId, (RenderResourceSetId, Option<Vec<u32>>)>, HashMap<BindGroupDescriptorId, RenderResourceSet>,
dirty_bind_groups: HashSet<BindGroupDescriptorId>, dirty_bind_groups: HashSet<BindGroupDescriptorId>,
pub pipeline_specialization: PipelineSpecialization, pub pipeline_specialization: PipelineSpecialization,
} }
impl RenderResourceAssignments { impl RenderResourceAssignments {
pub fn get(&self, name: &str) -> Option<RenderResource> { pub fn get(&self, name: &str) -> Option<&RenderResourceAssignment> {
self.render_resources.get(name).map(|(r, _i)| *r) self.render_resources.get(name)
} }
pub fn get_indexed(&self, name: &str) -> Option<(RenderResource, Option<u32>)> { pub fn set(&mut self, name: &str, assignment: RenderResourceAssignment) {
self.render_resources.get(name).cloned() self.try_set_dirty(name, &assignment);
}
pub fn set(&mut self, name: &str, resource: RenderResource) {
self.try_set_dirty(name, resource);
self.render_resources self.render_resources
.insert(name.to_string(), (resource, None)); .insert(name.to_string(), assignment);
} }
pub fn set_indexed(&mut self, name: &str, resource: RenderResource, index: u32) { fn try_set_dirty(&mut self, name: &str, assignment: &RenderResourceAssignment) {
self.try_set_dirty(name, resource); if let Some(current_assignment) = self.render_resources.get(name) {
self.render_resources if current_assignment != assignment {
.insert(name.to_string(), (resource, Some(index)));
}
fn try_set_dirty(&mut self, name: &str, resource: RenderResource) {
if let Some((render_resource, _)) = self.render_resources.get(name) {
if *render_resource != resource {
// TODO: this is pretty crude. can we do better? // TODO: this is pretty crude. can we do better?
for bind_group_id in self.bind_group_resource_sets.keys() { for bind_group_id in self.bind_group_resource_sets.keys() {
self.dirty_bind_groups.insert(*bind_group_id); self.dirty_bind_groups.insert(*bind_group_id);
@ -76,53 +93,55 @@ impl RenderResourceAssignments {
.contains_key(&bind_group_descriptor.id) .contains_key(&bind_group_descriptor.id)
|| self.dirty_bind_groups.contains(&bind_group_descriptor.id) || self.dirty_bind_groups.contains(&bind_group_descriptor.id)
{ {
let result = self.generate_render_resource_set_id(bind_group_descriptor); let resource_set = self.generate_render_resource_set(bind_group_descriptor);
if let Some((set_id, indices)) = result { if let Some(resource_set) = resource_set {
let id = resource_set.id;
self.bind_group_resource_sets self.bind_group_resource_sets
.insert(bind_group_descriptor.id, (set_id, indices)); .insert(bind_group_descriptor.id, resource_set);
Some(set_id) Some(id)
} else { } else {
None None
} }
} else { } else {
self.bind_group_resource_sets self.bind_group_resource_sets
.get(&bind_group_descriptor.id) .get(&bind_group_descriptor.id)
.map(|(set_id, _indices)| *set_id) .map(|set| set.id)
} }
} }
pub fn get_render_resource_set_id( pub fn get_render_resource_set(
&self, &self,
bind_group_descriptor_id: BindGroupDescriptorId, bind_group_descriptor_id: BindGroupDescriptorId,
) -> Option<&(RenderResourceSetId, Option<Vec<u32>>)> { ) -> Option<&RenderResourceSet> {
self.bind_group_resource_sets.get(&bind_group_descriptor_id) self.bind_group_resource_sets.get(&bind_group_descriptor_id)
} }
fn generate_render_resource_set_id( fn generate_render_resource_set(
&self, &self,
bind_group_descriptor: &BindGroupDescriptor, bind_group_descriptor: &BindGroupDescriptor,
) -> Option<(RenderResourceSetId, Option<Vec<u32>>)> { ) -> Option<RenderResourceSet> {
let mut hasher = DefaultHasher::new(); let mut hasher = DefaultHasher::new();
let mut indices = Vec::new(); let mut indices = Vec::new();
for binding_descriptor in bind_group_descriptor.bindings.iter() { for binding_descriptor in bind_group_descriptor.bindings.iter() {
if let Some((render_resource, index)) = self.get_indexed(&binding_descriptor.name) { if let Some(assignment) = self.get(&binding_descriptor.name) {
render_resource.hash(&mut hasher); let resource = assignment.get_resource();
if let Some(index) = index { resource.hash(&mut hasher);
indices.push(index); if let RenderResourceAssignment::Buffer { dynamic_index: Some(index), .. } = assignment {
indices.push(*index);
} }
} else { } else {
return None; return None;
} }
} }
Some(( Some(RenderResourceSet {
RenderResourceSetId(hasher.finish()), id: RenderResourceSetId(hasher.finish()),
if indices.is_empty() { dynamic_uniform_indices: if indices.is_empty() {
None None
} else { } else {
Some(indices) Some(indices)
}, },
)) })
} }
} }
@ -176,22 +195,22 @@ mod tests {
], ],
); );
let resource1 = RenderResource::new(); let resource1 = RenderResourceAssignment::Texture(RenderResource::new());
let resource2 = RenderResource::new(); let resource2 = RenderResourceAssignment::Texture(RenderResource::new());
let resource3 = RenderResource::new(); let resource3 = RenderResourceAssignment::Texture(RenderResource::new());
let resource4 = RenderResource::new(); let resource4 = RenderResourceAssignment::Texture(RenderResource::new());
let mut assignments = RenderResourceAssignments::default(); let mut assignments = RenderResourceAssignments::default();
assignments.set("a", resource1); assignments.set("a", resource1.clone());
assignments.set("b", resource2); assignments.set("b", resource2.clone());
let mut different_assignments = RenderResourceAssignments::default(); let mut different_assignments = RenderResourceAssignments::default();
different_assignments.set("a", resource3); different_assignments.set("a", resource3.clone());
different_assignments.set("b", resource4); different_assignments.set("b", resource4.clone());
let mut equal_assignments = RenderResourceAssignments::default(); let mut equal_assignments = RenderResourceAssignments::default();
equal_assignments.set("a", resource1); equal_assignments.set("a", resource1.clone());
equal_assignments.set("b", resource2); equal_assignments.set("b", resource2.clone());
let set_id = assignments.update_render_resource_set_id(&bind_group_descriptor); let set_id = assignments.update_render_resource_set_id(&bind_group_descriptor);
assert_ne!(set_id, None); assert_ne!(set_id, None);
@ -206,7 +225,7 @@ mod tests {
assert_eq!(equal_set_id, set_id); assert_eq!(equal_set_id, set_id);
let mut unmatched_assignments = RenderResourceAssignments::default(); let mut unmatched_assignments = RenderResourceAssignments::default();
unmatched_assignments.set("a", resource1); unmatched_assignments.set("a", resource1.clone());
let unmatched_set_id = let unmatched_set_id =
unmatched_assignments.update_render_resource_set_id(&bind_group_descriptor); unmatched_assignments.update_render_resource_set_id(&bind_group_descriptor);
assert_eq!(unmatched_set_id, None); assert_eq!(unmatched_set_id, None);

View File

@ -10,6 +10,7 @@ pub struct BufferArrayInfo {
pub struct BufferInfo { pub struct BufferInfo {
pub size: usize, pub size: usize,
pub buffer_usage: BufferUsage, pub buffer_usage: BufferUsage,
// TODO: remove array info and is_dynamic
pub array_info: Option<BufferArrayInfo>, pub array_info: Option<BufferArrayInfo>,
pub is_dynamic: bool, pub is_dynamic: bool,
} }

View File

@ -121,10 +121,10 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
bind_group_descriptor: &BindGroupDescriptor, bind_group_descriptor: &BindGroupDescriptor,
render_resource_assignments: &RenderResourceAssignments, render_resource_assignments: &RenderResourceAssignments,
) -> Option<RenderResourceSetId> { ) -> Option<RenderResourceSetId> {
if let Some((render_resource_set_id, _indices)) = if let Some(resource_set) =
render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id) render_resource_assignments.get_render_resource_set(bind_group_descriptor.id)
{ {
Some(*render_resource_set_id) Some(resource_set.id)
} else { } else {
None None
} }

View File

@ -6,7 +6,7 @@ use bevy_render::{
PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor, PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor,
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment, RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
}, },
render_resource::{RenderResource, RenderResourceAssignments}, render_resource::{RenderResource, RenderResourceAssignments, RenderResourceAssignment},
renderer::{RenderContext, RenderResourceContext}, renderer::{RenderContext, RenderResourceContext},
texture::{Extent3d, TextureDescriptor}, texture::{Extent3d, TextureDescriptor},
}; };
@ -195,8 +195,8 @@ fn get_texture_view<'a>(
) -> &'a wgpu::TextureView { ) -> &'a wgpu::TextureView {
match attachment { match attachment {
TextureAttachment::Name(name) => match global_render_resource_assignments.get(&name) { TextureAttachment::Name(name) => match global_render_resource_assignments.get(&name) {
Some(resource) => refs.textures.get(&resource).unwrap(), Some(RenderResourceAssignment::Texture(resource)) => refs.textures.get(&resource).unwrap(),
None => { _ => {
panic!("Color attachment {} does not exist", name); panic!("Color attachment {} does not exist", name);
} }
}, },

View File

@ -7,7 +7,8 @@ use bevy_asset::{AssetStorage, Handle, HandleUntyped};
use bevy_render::{ use bevy_render::{
pipeline::{BindGroupDescriptor, BindType, PipelineDescriptor}, pipeline::{BindGroupDescriptor, BindType, PipelineDescriptor},
render_resource::{ render_resource::{
BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo, BufferInfo, RenderResource, RenderResourceAssignment, RenderResourceAssignments,
RenderResourceSetId, ResourceInfo,
}, },
renderer::RenderResourceContext, renderer::RenderResourceContext,
shader::Shader, shader::Shader,
@ -287,11 +288,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
handle_info(info); handle_info(info);
} }
fn create_shader_module_from_source( fn create_shader_module_from_source(&self, shader_handle: Handle<Shader>, shader: &Shader) {
&self,
shader_handle: Handle<Shader>,
shader: &Shader,
) {
let mut shader_modules = self.resources.shader_modules.write().unwrap(); let mut shader_modules = self.resources.shader_modules.write().unwrap();
let shader_module = self.device.create_shader_module(&shader.get_spirv(None)); let shader_module = self.device.create_shader_module(&shader.get_spirv(None));
shader_modules.insert(shader_handle, shader_module); shader_modules.insert(shader_handle, shader_module);
@ -484,21 +481,20 @@ impl RenderResourceContext for WgpuRenderResourceContext {
bind_group_descriptor: &BindGroupDescriptor, bind_group_descriptor: &BindGroupDescriptor,
render_resource_assignments: &RenderResourceAssignments, render_resource_assignments: &RenderResourceAssignments,
) -> Option<RenderResourceSetId> { ) -> Option<RenderResourceSetId> {
if let Some((render_resource_set_id, _indices)) = if let Some(render_resource_set) =
render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id) render_resource_assignments.get_render_resource_set(bind_group_descriptor.id)
{ {
if !self if !self
.resources .resources
.has_bind_group(bind_group_descriptor.id, *render_resource_set_id) .has_bind_group(bind_group_descriptor.id, render_resource_set.id)
{ {
log::trace!( log::trace!(
"start creating bind group for RenderResourceSet {:?}", "start creating bind group for RenderResourceSet {:?}",
render_resource_set_id render_resource_set.id
); );
let texture_views = self.resources.texture_views.read().unwrap(); let texture_views = self.resources.texture_views.read().unwrap();
let samplers = self.resources.samplers.read().unwrap(); let samplers = self.resources.samplers.read().unwrap();
let buffers = self.resources.buffers.read().unwrap(); let buffers = self.resources.buffers.read().unwrap();
let resource_info = self.resources.resource_info.read().unwrap();
let bind_group_layouts = self.resources.bind_group_layouts.read().unwrap(); let bind_group_layouts = self.resources.bind_group_layouts.read().unwrap();
let mut bind_groups = self.resources.bind_groups.write().unwrap(); let mut bind_groups = self.resources.bind_groups.write().unwrap();
@ -506,43 +502,27 @@ impl RenderResourceContext for WgpuRenderResourceContext {
.bindings .bindings
.iter() .iter()
.map(|binding| { .map(|binding| {
if let Some(resource) = render_resource_assignments.get(&binding.name) { if let Some(assignment) = render_resource_assignments.get(&binding.name) {
let info = resource_info
.get(&resource)
.expect("referenced resource does not exist");
log::trace!( log::trace!(
"found binding {} ({}) resource: {:?} {:?}", "found binding {} ({}) assignment: {:?}",
binding.index, binding.index,
binding.name, binding.name,
resource, assignment,
resource_info
); );
let wgpu_resource = match &binding.bind_type { let wgpu_resource = match assignment {
BindType::SampledTexture { .. } => { RenderResourceAssignment::Texture(resource) => {
if let ResourceInfo::Texture = info {
let texture = texture_views.get(&resource).unwrap(); let texture = texture_views.get(&resource).unwrap();
wgpu::BindingResource::TextureView(texture) wgpu::BindingResource::TextureView(texture)
} else {
panic!("expected a Texture resource");
} }
} RenderResourceAssignment::Sampler(resource) => {
BindType::Sampler { .. } => {
if let ResourceInfo::Sampler = info {
let sampler = samplers.get(&resource).unwrap(); let sampler = samplers.get(&resource).unwrap();
wgpu::BindingResource::Sampler(sampler) wgpu::BindingResource::Sampler(sampler)
} else {
panic!("expected a Sampler resource");
} }
} RenderResourceAssignment::Buffer { resource, range , .. } => {
BindType::Uniform { .. } => {
if let ResourceInfo::Buffer(buffer_info) = info {
let buffer = buffers.get(&resource).unwrap(); let buffer = buffers.get(&resource).unwrap();
wgpu::BindingResource::Buffer { wgpu::BindingResource::Buffer {
buffer, buffer,
range: 0..buffer_info.size as u64, range: range.clone(),
}
} else {
panic!("expected a Buffer resource");
} }
} }
_ => panic!("unsupported bind type"), _ => panic!("unsupported bind type"),
@ -574,12 +554,12 @@ impl RenderResourceContext for WgpuRenderResourceContext {
.or_insert_with(|| WgpuBindGroupInfo::default()); .or_insert_with(|| WgpuBindGroupInfo::default());
bind_group_info bind_group_info
.bind_groups .bind_groups
.insert(*render_resource_set_id, wgpu_bind_group); .insert(render_resource_set.id, wgpu_bind_group);
log::trace!( log::trace!(
"created bind group for RenderResourceSet {:?}", "created bind group for RenderResourceSet {:?}",
render_resource_set_id render_resource_set.id
); );
return Some(*render_resource_set_id); return Some(render_resource_set.id);
} }
} }

View File

@ -89,17 +89,17 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
} }
for bind_group in pipeline_layout.bind_groups.iter() { for bind_group in pipeline_layout.bind_groups.iter() {
if let Some((render_resource_set_id, dynamic_uniform_indices)) = if let Some(resource_set) =
render_resource_assignments.get_render_resource_set_id(bind_group.id) render_resource_assignments.get_render_resource_set(bind_group.id)
{ {
if let Some(bind_group_info) = self.render_resources.bind_groups.get(&bind_group.id) if let Some(bind_group_info) = self.render_resources.bind_groups.get(&bind_group.id)
{ {
if let Some(wgpu_bind_group) = if let Some(wgpu_bind_group) =
bind_group_info.bind_groups.get(render_resource_set_id) bind_group_info.bind_groups.get(&resource_set.id)
{ {
const EMPTY: &'static [u32] = &[]; const EMPTY: &'static [u32] = &[];
let dynamic_uniform_indices = let dynamic_uniform_indices =
if let Some(dynamic_uniform_indices) = dynamic_uniform_indices { if let Some(ref dynamic_uniform_indices) = resource_set.dynamic_uniform_indices {
dynamic_uniform_indices.as_slice() dynamic_uniform_indices.as_slice()
} else { } else {
EMPTY EMPTY
@ -110,7 +110,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
if let Some(bound_render_resource_set) = if let Some(bound_render_resource_set) =
self.bound_bind_groups.get(&bind_group.index) self.bound_bind_groups.get(&bind_group.index)
{ {
if *bound_render_resource_set == *render_resource_set_id if *bound_render_resource_set == resource_set.id
&& dynamic_uniform_indices.len() == 0 && dynamic_uniform_indices.len() == 0
{ {
continue; continue;
@ -119,7 +119,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
if dynamic_uniform_indices.len() == 0 { if dynamic_uniform_indices.len() == 0 {
self.bound_bind_groups self.bound_bind_groups
.insert(bind_group.index, *render_resource_set_id); .insert(bind_group.index, resource_set.id);
} else { } else {
self.bound_bind_groups.remove(&bind_group.index); self.bound_bind_groups.remove(&bind_group.index);
} }
@ -128,7 +128,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
"set bind group {} {:?}: {:?}", "set bind group {} {:?}: {:?}",
bind_group.index, bind_group.index,
dynamic_uniform_indices, dynamic_uniform_indices,
render_resource_set_id resource_set.id
); );
self.render_pass.set_bind_group( self.render_pass.set_bind_group(
bind_group.index, bind_group.index,