mirror of
https://github.com/bevyengine/bevy
synced 2024-09-20 06:22:01 +00:00
RenderResourceAssignment refactor
This commit is contained in:
parent
ef2e5a1ba3
commit
7a71873a32
12 changed files with 206 additions and 184 deletions
|
@ -1,6 +1,8 @@
|
|||
use bevy_render::{
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
|
||||
render_resource::{
|
||||
resource_name, BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
|
||||
},
|
||||
renderer::{RenderContext, RenderResources},
|
||||
};
|
||||
|
||||
|
@ -78,7 +80,14 @@ impl SystemNode for LightsNode {
|
|||
| BufferUsage::COPY_DST,
|
||||
..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);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,15 @@ use super::{
|
|||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat,
|
||||
PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
},
|
||||
PipelineLayout, VertexBufferDescriptors, BindType,
|
||||
BindType, PipelineLayout, VertexBufferDescriptors,
|
||||
};
|
||||
use crate::{
|
||||
render_resource::{ResourceInfo, RenderResourceAssignments, BufferInfo},
|
||||
render_resource::{
|
||||
BufferInfo, RenderResourceAssignment, RenderResourceAssignments, ResourceInfo,
|
||||
},
|
||||
renderer::RenderResourceContext,
|
||||
shader::{Shader, ShaderStages},
|
||||
texture::TextureFormat, renderer::RenderResourceContext,
|
||||
texture::TextureFormat,
|
||||
};
|
||||
use bevy_asset::AssetStorage;
|
||||
|
||||
|
@ -134,21 +137,21 @@ impl PipelineDescriptor {
|
|||
}
|
||||
|
||||
/// Reflects the pipeline layout from its shaders.
|
||||
///
|
||||
///
|
||||
/// If `bevy_conventions` is true, it will be assumed that the shader follows "bevy shader conventions". These allow
|
||||
/// richer reflection, such as inferred Vertex Buffer names and inferred instancing.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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.
|
||||
pub fn reflect_layout(
|
||||
&mut self,
|
||||
shaders: &AssetStorage<Shader>,
|
||||
bevy_conventions: bool,
|
||||
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 fragment_spirv = self
|
||||
|
@ -167,30 +170,23 @@ impl PipelineDescriptor {
|
|||
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
|
||||
// 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) {
|
||||
render_resource_context.get_resource_info(
|
||||
render_resource,
|
||||
&mut |resource_info| {
|
||||
if let Some(ResourceInfo::Buffer(BufferInfo {
|
||||
is_dynamic, ..
|
||||
})) = resource_info
|
||||
{
|
||||
if let BindType::Uniform {
|
||||
ref mut dynamic, ..
|
||||
} = binding.bind_type
|
||||
{
|
||||
*dynamic = *is_dynamic
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
if let Some(RenderResourceAssignment::Buffer { dynamic_index: Some(_), .. }) =
|
||||
render_resource_assignments.get(&binding.name)
|
||||
{
|
||||
if let BindType::Uniform {
|
||||
ref mut dynamic, ..
|
||||
} = binding.bind_type
|
||||
{
|
||||
*dynamic = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ impl PipelineCompiler {
|
|||
&mut self,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
shaders: &mut AssetStorage<Shader>,
|
||||
render_resource_context: &dyn RenderResourceContext,
|
||||
pipeline_descriptor: &PipelineDescriptor,
|
||||
render_resource_assignments: &RenderResourceAssignments,
|
||||
) -> PipelineDescriptor {
|
||||
|
@ -115,7 +114,7 @@ impl PipelineCompiler {
|
|||
shaders,
|
||||
true,
|
||||
Some(vertex_buffer_descriptors),
|
||||
Some((render_resource_assignments, render_resource_context)),
|
||||
Some(render_resource_assignments),
|
||||
);
|
||||
|
||||
compiled_pipeline_descriptor.primitive_topology = render_resource_assignments
|
||||
|
@ -128,7 +127,6 @@ impl PipelineCompiler {
|
|||
&mut self,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
shader_pipeline_assignments: &mut PipelineAssignments,
|
||||
render_resource_context: &dyn RenderResourceContext,
|
||||
pipeline_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
pipelines: &[Handle<PipelineDescriptor>],
|
||||
|
@ -154,7 +152,6 @@ impl PipelineCompiler {
|
|||
let compiled_pipeline = self.compile_pipeline(
|
||||
vertex_buffer_descriptors,
|
||||
shader_storage,
|
||||
render_resource_context,
|
||||
pipeline_descriptor,
|
||||
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 shader_storage = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
let vertex_buffer_descriptors = resources.get::<VertexBufferDescriptors>().unwrap();
|
||||
let render_resources = resources.get::<RenderResources>().unwrap();
|
||||
let mut pipeline_descriptor_storage = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
|
@ -248,7 +244,6 @@ pub fn update_shader_assignments(world: &mut World, resources: &Resources) {
|
|||
pipeline_compiler.update_shader_assignments(
|
||||
&vertex_buffer_descriptors,
|
||||
&mut shader_pipeline_assignments,
|
||||
&*render_resources.context,
|
||||
&mut pipeline_descriptor_storage,
|
||||
&mut shader_storage,
|
||||
&renderable.pipelines,
|
||||
|
|
|
@ -4,7 +4,7 @@ use bevy_window::WindowResized;
|
|||
use crate::{
|
||||
camera::{ActiveCamera2d, Camera},
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
|
||||
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments, RenderResourceAssignment},
|
||||
renderer::{RenderContext, RenderResources},
|
||||
};
|
||||
|
||||
|
@ -52,12 +52,20 @@ impl SystemNode for Camera2dNode {
|
|||
query| {
|
||||
let render_resources = &render_resource_context.context;
|
||||
if camera_buffer.is_none() {
|
||||
let size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||
let buffer = render_resources.create_buffer(BufferInfo {
|
||||
size: std::mem::size_of::<[[f32; 4]; 4]>(),
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
..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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use crate::{
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
|
||||
render_resource::{
|
||||
resource_name, BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
|
||||
},
|
||||
renderer::{RenderContext, RenderResources},
|
||||
ActiveCamera, Camera,
|
||||
};
|
||||
|
@ -52,12 +54,20 @@ impl SystemNode for CameraNode {
|
|||
query| {
|
||||
let render_resources = &render_resource_context.context;
|
||||
if camera_buffer.is_none() {
|
||||
let size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||
let buffer = render_resources.create_buffer(BufferInfo {
|
||||
size: std::mem::size_of::<[[f32; 4]; 4]>(),
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
..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);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ use crate::{
|
|||
pipeline::VertexBufferDescriptors,
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{
|
||||
BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
|
||||
RenderResourceAssignmentsId, ResourceInfo,
|
||||
BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignment,
|
||||
RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo,
|
||||
},
|
||||
renderer::{RenderContext, RenderResourceContext, RenderResources},
|
||||
shader::{AsUniforms, FieldBindType},
|
||||
|
@ -224,42 +224,40 @@ where
|
|||
let (_name, uniform_buffer_status) = self.uniform_arrays[i].as_mut().unwrap();
|
||||
let (target_buffer, target_offset) = if dynamic_uniforms {
|
||||
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
|
||||
.get_or_assign_index(render_resource_assignments.id);
|
||||
render_resource_assignments.set_indexed(
|
||||
&field_info.uniform_name,
|
||||
buffer,
|
||||
(index * array_info.item_size) as u32,
|
||||
);
|
||||
offset = index * uniform_buffer_status.aligned_size;
|
||||
} else {
|
||||
panic!("Expected a dynamic uniform buffer");
|
||||
}
|
||||
});
|
||||
(buffer, offset)
|
||||
let index = uniform_buffer_status
|
||||
.get_or_assign_index(render_resource_assignments.id);
|
||||
render_resource_assignments.set(
|
||||
&field_info.uniform_name,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource: buffer,
|
||||
dynamic_index: Some(
|
||||
(index * uniform_buffer_status.aligned_size) as u32,
|
||||
),
|
||||
range: 0..size as u64,
|
||||
},
|
||||
);
|
||||
(buffer, index * uniform_buffer_status.aligned_size)
|
||||
} else {
|
||||
let resource = match render_resource_assignments
|
||||
.get(field_info.uniform_name)
|
||||
{
|
||||
Some(render_resource) => render_resource,
|
||||
None => {
|
||||
let resource = render_resources.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
..Default::default()
|
||||
});
|
||||
render_resource_assignments.set(&field_info.uniform_name, resource);
|
||||
resource
|
||||
}
|
||||
};
|
||||
let resource =
|
||||
match render_resource_assignments.get(field_info.uniform_name) {
|
||||
Some(assignment) => assignment.get_resource(),
|
||||
None => {
|
||||
let resource = render_resources.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
..Default::default()
|
||||
});
|
||||
render_resource_assignments.set(
|
||||
&field_info.uniform_name,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource,
|
||||
range: 0..size as u64,
|
||||
dynamic_index: None,
|
||||
},
|
||||
);
|
||||
resource
|
||||
}
|
||||
};
|
||||
|
||||
(resource, 0)
|
||||
};
|
||||
|
@ -791,8 +789,14 @@ fn setup_uniform_texture_resources<T>(
|
|||
}
|
||||
};
|
||||
|
||||
render_resource_assignments.set(field_info.texture_name, texture_resource);
|
||||
render_resource_assignments.set(field_info.sampler_name, sampler_resource);
|
||||
render_resource_assignments.set(
|
||||
field_info.texture_name,
|
||||
RenderResourceAssignment::Texture(texture_resource),
|
||||
);
|
||||
render_resource_assignments.set(
|
||||
field_info.sampler_name,
|
||||
RenderResourceAssignment::Sampler(sampler_resource),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -2,46 +2,63 @@ use super::RenderResource;
|
|||
use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization};
|
||||
use std::{
|
||||
collections::{hash_map::DefaultHasher, HashMap, HashSet},
|
||||
hash::{Hash, Hasher},
|
||||
hash::{Hash, Hasher}, ops::Range,
|
||||
};
|
||||
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
|
||||
#[derive(Eq, PartialEq, Debug, Default)]
|
||||
pub struct RenderResourceAssignments {
|
||||
pub id: RenderResourceAssignmentsId,
|
||||
render_resources: HashMap<String, (RenderResource, Option<u32>)>,
|
||||
render_resources: HashMap<String, RenderResourceAssignment>,
|
||||
vertex_buffers: HashMap<String, (RenderResource, Option<RenderResource>)>,
|
||||
bind_group_resource_sets:
|
||||
HashMap<BindGroupDescriptorId, (RenderResourceSetId, Option<Vec<u32>>)>,
|
||||
HashMap<BindGroupDescriptorId, RenderResourceSet>,
|
||||
dirty_bind_groups: HashSet<BindGroupDescriptorId>,
|
||||
pub pipeline_specialization: PipelineSpecialization,
|
||||
}
|
||||
|
||||
impl RenderResourceAssignments {
|
||||
pub fn get(&self, name: &str) -> Option<RenderResource> {
|
||||
self.render_resources.get(name).map(|(r, _i)| *r)
|
||||
pub fn get(&self, name: &str) -> Option<&RenderResourceAssignment> {
|
||||
self.render_resources.get(name)
|
||||
}
|
||||
|
||||
pub fn get_indexed(&self, name: &str) -> Option<(RenderResource, Option<u32>)> {
|
||||
self.render_resources.get(name).cloned()
|
||||
}
|
||||
|
||||
pub fn set(&mut self, name: &str, resource: RenderResource) {
|
||||
self.try_set_dirty(name, resource);
|
||||
pub fn set(&mut self, name: &str, assignment: RenderResourceAssignment) {
|
||||
self.try_set_dirty(name, &assignment);
|
||||
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) {
|
||||
self.try_set_dirty(name, resource);
|
||||
self.render_resources
|
||||
.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 {
|
||||
fn try_set_dirty(&mut self, name: &str, assignment: &RenderResourceAssignment) {
|
||||
if let Some(current_assignment) = self.render_resources.get(name) {
|
||||
if current_assignment != assignment {
|
||||
// TODO: this is pretty crude. can we do better?
|
||||
for bind_group_id in self.bind_group_resource_sets.keys() {
|
||||
self.dirty_bind_groups.insert(*bind_group_id);
|
||||
|
@ -76,53 +93,55 @@ impl RenderResourceAssignments {
|
|||
.contains_key(&bind_group_descriptor.id)
|
||||
|| self.dirty_bind_groups.contains(&bind_group_descriptor.id)
|
||||
{
|
||||
let result = self.generate_render_resource_set_id(bind_group_descriptor);
|
||||
if let Some((set_id, indices)) = result {
|
||||
let resource_set = self.generate_render_resource_set(bind_group_descriptor);
|
||||
if let Some(resource_set) = resource_set {
|
||||
let id = resource_set.id;
|
||||
self.bind_group_resource_sets
|
||||
.insert(bind_group_descriptor.id, (set_id, indices));
|
||||
Some(set_id)
|
||||
.insert(bind_group_descriptor.id, resource_set);
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
self.bind_group_resource_sets
|
||||
.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,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
) -> Option<&(RenderResourceSetId, Option<Vec<u32>>)> {
|
||||
) -> Option<&RenderResourceSet> {
|
||||
self.bind_group_resource_sets.get(&bind_group_descriptor_id)
|
||||
}
|
||||
|
||||
fn generate_render_resource_set_id(
|
||||
fn generate_render_resource_set(
|
||||
&self,
|
||||
bind_group_descriptor: &BindGroupDescriptor,
|
||||
) -> Option<(RenderResourceSetId, Option<Vec<u32>>)> {
|
||||
) -> Option<RenderResourceSet> {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let mut indices = Vec::new();
|
||||
for binding_descriptor in bind_group_descriptor.bindings.iter() {
|
||||
if let Some((render_resource, index)) = self.get_indexed(&binding_descriptor.name) {
|
||||
render_resource.hash(&mut hasher);
|
||||
if let Some(index) = index {
|
||||
indices.push(index);
|
||||
if let Some(assignment) = self.get(&binding_descriptor.name) {
|
||||
let resource = assignment.get_resource();
|
||||
resource.hash(&mut hasher);
|
||||
if let RenderResourceAssignment::Buffer { dynamic_index: Some(index), .. } = assignment {
|
||||
indices.push(*index);
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Some((
|
||||
RenderResourceSetId(hasher.finish()),
|
||||
if indices.is_empty() {
|
||||
Some(RenderResourceSet {
|
||||
id: RenderResourceSetId(hasher.finish()),
|
||||
dynamic_uniform_indices: if indices.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(indices)
|
||||
},
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,22 +195,22 @@ mod tests {
|
|||
],
|
||||
);
|
||||
|
||||
let resource1 = RenderResource::new();
|
||||
let resource2 = RenderResource::new();
|
||||
let resource3 = RenderResource::new();
|
||||
let resource4 = RenderResource::new();
|
||||
let resource1 = RenderResourceAssignment::Texture(RenderResource::new());
|
||||
let resource2 = RenderResourceAssignment::Texture(RenderResource::new());
|
||||
let resource3 = RenderResourceAssignment::Texture(RenderResource::new());
|
||||
let resource4 = RenderResourceAssignment::Texture(RenderResource::new());
|
||||
|
||||
let mut assignments = RenderResourceAssignments::default();
|
||||
assignments.set("a", resource1);
|
||||
assignments.set("b", resource2);
|
||||
assignments.set("a", resource1.clone());
|
||||
assignments.set("b", resource2.clone());
|
||||
|
||||
let mut different_assignments = RenderResourceAssignments::default();
|
||||
different_assignments.set("a", resource3);
|
||||
different_assignments.set("b", resource4);
|
||||
different_assignments.set("a", resource3.clone());
|
||||
different_assignments.set("b", resource4.clone());
|
||||
|
||||
let mut equal_assignments = RenderResourceAssignments::default();
|
||||
equal_assignments.set("a", resource1);
|
||||
equal_assignments.set("b", resource2);
|
||||
equal_assignments.set("a", resource1.clone());
|
||||
equal_assignments.set("b", resource2.clone());
|
||||
|
||||
let set_id = assignments.update_render_resource_set_id(&bind_group_descriptor);
|
||||
assert_ne!(set_id, None);
|
||||
|
@ -206,7 +225,7 @@ mod tests {
|
|||
assert_eq!(equal_set_id, set_id);
|
||||
|
||||
let mut unmatched_assignments = RenderResourceAssignments::default();
|
||||
unmatched_assignments.set("a", resource1);
|
||||
unmatched_assignments.set("a", resource1.clone());
|
||||
let unmatched_set_id =
|
||||
unmatched_assignments.update_render_resource_set_id(&bind_group_descriptor);
|
||||
assert_eq!(unmatched_set_id, None);
|
||||
|
|
|
@ -10,6 +10,7 @@ pub struct BufferArrayInfo {
|
|||
pub struct BufferInfo {
|
||||
pub size: usize,
|
||||
pub buffer_usage: BufferUsage,
|
||||
// TODO: remove array info and is_dynamic
|
||||
pub array_info: Option<BufferArrayInfo>,
|
||||
pub is_dynamic: bool,
|
||||
}
|
||||
|
|
|
@ -121,10 +121,10 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
|
|||
bind_group_descriptor: &BindGroupDescriptor,
|
||||
render_resource_assignments: &RenderResourceAssignments,
|
||||
) -> Option<RenderResourceSetId> {
|
||||
if let Some((render_resource_set_id, _indices)) =
|
||||
render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id)
|
||||
if let Some(resource_set) =
|
||||
render_resource_assignments.get_render_resource_set(bind_group_descriptor.id)
|
||||
{
|
||||
Some(*render_resource_set_id)
|
||||
Some(resource_set.id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use bevy_render::{
|
|||
PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
||||
},
|
||||
render_resource::{RenderResource, RenderResourceAssignments},
|
||||
render_resource::{RenderResource, RenderResourceAssignments, RenderResourceAssignment},
|
||||
renderer::{RenderContext, RenderResourceContext},
|
||||
texture::{Extent3d, TextureDescriptor},
|
||||
};
|
||||
|
@ -195,8 +195,8 @@ fn get_texture_view<'a>(
|
|||
) -> &'a wgpu::TextureView {
|
||||
match attachment {
|
||||
TextureAttachment::Name(name) => match global_render_resource_assignments.get(&name) {
|
||||
Some(resource) => refs.textures.get(&resource).unwrap(),
|
||||
None => {
|
||||
Some(RenderResourceAssignment::Texture(resource)) => refs.textures.get(&resource).unwrap(),
|
||||
_ => {
|
||||
panic!("Color attachment {} does not exist", name);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,7 +7,8 @@ use bevy_asset::{AssetStorage, Handle, HandleUntyped};
|
|||
use bevy_render::{
|
||||
pipeline::{BindGroupDescriptor, BindType, PipelineDescriptor},
|
||||
render_resource::{
|
||||
BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
|
||||
BufferInfo, RenderResource, RenderResourceAssignment, RenderResourceAssignments,
|
||||
RenderResourceSetId, ResourceInfo,
|
||||
},
|
||||
renderer::RenderResourceContext,
|
||||
shader::Shader,
|
||||
|
@ -287,11 +288,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
handle_info(info);
|
||||
}
|
||||
|
||||
fn create_shader_module_from_source(
|
||||
&self,
|
||||
shader_handle: Handle<Shader>,
|
||||
shader: &Shader,
|
||||
) {
|
||||
fn create_shader_module_from_source(&self, shader_handle: Handle<Shader>, shader: &Shader) {
|
||||
let mut shader_modules = self.resources.shader_modules.write().unwrap();
|
||||
let shader_module = self.device.create_shader_module(&shader.get_spirv(None));
|
||||
shader_modules.insert(shader_handle, shader_module);
|
||||
|
@ -484,21 +481,20 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
bind_group_descriptor: &BindGroupDescriptor,
|
||||
render_resource_assignments: &RenderResourceAssignments,
|
||||
) -> Option<RenderResourceSetId> {
|
||||
if let Some((render_resource_set_id, _indices)) =
|
||||
render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id)
|
||||
if let Some(render_resource_set) =
|
||||
render_resource_assignments.get_render_resource_set(bind_group_descriptor.id)
|
||||
{
|
||||
if !self
|
||||
.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!(
|
||||
"start creating bind group for RenderResourceSet {:?}",
|
||||
render_resource_set_id
|
||||
render_resource_set.id
|
||||
);
|
||||
let texture_views = self.resources.texture_views.read().unwrap();
|
||||
let samplers = self.resources.samplers.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 mut bind_groups = self.resources.bind_groups.write().unwrap();
|
||||
|
||||
|
@ -506,43 +502,27 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
.bindings
|
||||
.iter()
|
||||
.map(|binding| {
|
||||
if let Some(resource) = render_resource_assignments.get(&binding.name) {
|
||||
let info = resource_info
|
||||
.get(&resource)
|
||||
.expect("referenced resource does not exist");
|
||||
if let Some(assignment) = render_resource_assignments.get(&binding.name) {
|
||||
log::trace!(
|
||||
"found binding {} ({}) resource: {:?} {:?}",
|
||||
"found binding {} ({}) assignment: {:?}",
|
||||
binding.index,
|
||||
binding.name,
|
||||
resource,
|
||||
resource_info
|
||||
assignment,
|
||||
);
|
||||
let wgpu_resource = match &binding.bind_type {
|
||||
BindType::SampledTexture { .. } => {
|
||||
if let ResourceInfo::Texture = info {
|
||||
let texture = texture_views.get(&resource).unwrap();
|
||||
wgpu::BindingResource::TextureView(texture)
|
||||
} else {
|
||||
panic!("expected a Texture resource");
|
||||
}
|
||||
let wgpu_resource = match assignment {
|
||||
RenderResourceAssignment::Texture(resource) => {
|
||||
let texture = texture_views.get(&resource).unwrap();
|
||||
wgpu::BindingResource::TextureView(texture)
|
||||
}
|
||||
BindType::Sampler { .. } => {
|
||||
if let ResourceInfo::Sampler = info {
|
||||
let sampler = samplers.get(&resource).unwrap();
|
||||
wgpu::BindingResource::Sampler(sampler)
|
||||
} else {
|
||||
panic!("expected a Sampler resource");
|
||||
}
|
||||
RenderResourceAssignment::Sampler(resource) => {
|
||||
let sampler = samplers.get(&resource).unwrap();
|
||||
wgpu::BindingResource::Sampler(sampler)
|
||||
}
|
||||
BindType::Uniform { .. } => {
|
||||
if let ResourceInfo::Buffer(buffer_info) = info {
|
||||
let buffer = buffers.get(&resource).unwrap();
|
||||
wgpu::BindingResource::Buffer {
|
||||
buffer,
|
||||
range: 0..buffer_info.size as u64,
|
||||
}
|
||||
} else {
|
||||
panic!("expected a Buffer resource");
|
||||
RenderResourceAssignment::Buffer { resource, range , .. } => {
|
||||
let buffer = buffers.get(&resource).unwrap();
|
||||
wgpu::BindingResource::Buffer {
|
||||
buffer,
|
||||
range: range.clone(),
|
||||
}
|
||||
}
|
||||
_ => panic!("unsupported bind type"),
|
||||
|
@ -574,12 +554,12 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
.or_insert_with(|| WgpuBindGroupInfo::default());
|
||||
bind_group_info
|
||||
.bind_groups
|
||||
.insert(*render_resource_set_id, wgpu_bind_group);
|
||||
.insert(render_resource_set.id, wgpu_bind_group);
|
||||
log::trace!(
|
||||
"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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,17 +89,17 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
|
|||
}
|
||||
|
||||
for bind_group in pipeline_layout.bind_groups.iter() {
|
||||
if let Some((render_resource_set_id, dynamic_uniform_indices)) =
|
||||
render_resource_assignments.get_render_resource_set_id(bind_group.id)
|
||||
if let Some(resource_set) =
|
||||
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(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] = &[];
|
||||
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()
|
||||
} else {
|
||||
EMPTY
|
||||
|
@ -110,7 +110,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
|
|||
if let Some(bound_render_resource_set) =
|
||||
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
|
||||
{
|
||||
continue;
|
||||
|
@ -119,7 +119,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
|
|||
|
||||
if dynamic_uniform_indices.len() == 0 {
|
||||
self.bound_bind_groups
|
||||
.insert(bind_group.index, *render_resource_set_id);
|
||||
.insert(bind_group.index, resource_set.id);
|
||||
} else {
|
||||
self.bound_bind_groups.remove(&bind_group.index);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
|
|||
"set bind group {} {:?}: {:?}",
|
||||
bind_group.index,
|
||||
dynamic_uniform_indices,
|
||||
render_resource_set_id
|
||||
resource_set.id
|
||||
);
|
||||
self.render_pass.set_bind_group(
|
||||
bind_group.index,
|
||||
|
|
Loading…
Reference in a new issue