Skip to content

Commit

Permalink
add dynamic binding generation
Browse files Browse the repository at this point in the history
  • Loading branch information
cart authored and mrk-its committed Nov 10, 2020
1 parent 6475d74 commit a4b5f7f
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 39 deletions.
4 changes: 1 addition & 3 deletions crates/bevy_render/src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,7 @@ impl<'a> DrawContext<'a> {
&mut self,
draw: &mut Draw,
pipeline_handle: &Handle<PipelineDescriptor>,
specialization: &mut PipelineSpecialization,
render_resource_bindings: &mut [&mut RenderResourceBindings],
specialization: &PipelineSpecialization,
) -> Result<(), DrawError> {
let specialized_pipeline = if let Some(specialized_pipeline) = self
.pipeline_compiler
Expand All @@ -173,7 +172,6 @@ impl<'a> DrawContext<'a> {
&mut self.shaders,
pipeline_handle,
specialization,
render_resource_bindings,
)
};

Expand Down
38 changes: 8 additions & 30 deletions crates/bevy_render/src/pipeline/pipeline_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
BindType, InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
VERTEX_FALLBACK_LAYOUT_NAME,
},
renderer::{RenderResourceBinding, RenderResourceBindings, RenderResourceContext},
renderer::RenderResourceContext,
shader::{Shader, ShaderSource},
};
use bevy_asset::{Assets, Handle};
Expand Down Expand Up @@ -136,8 +136,7 @@ impl PipelineCompiler {
pipelines: &mut Assets<PipelineDescriptor>,
shaders: &mut Assets<Shader>,
source_pipeline: &Handle<PipelineDescriptor>,
pipeline_specialization: &mut PipelineSpecialization,
render_resource_bindings: &mut [&mut RenderResourceBindings],
pipeline_specialization: &PipelineSpecialization,
) -> Handle<PipelineDescriptor> {
let source_descriptor = pipelines.get(source_pipeline).unwrap();
let mut specialized_descriptor = source_descriptor.clone();
Expand All @@ -164,14 +163,16 @@ impl PipelineCompiler {
true,
);

let dynamic_bindings = self.get_dynamic_bindings(render_resource_bindings);

if !dynamic_bindings.is_empty() {
if !pipeline_specialization.dynamic_bindings.is_empty() {
// set binding uniforms to dynamic if render resource bindings use dynamic
for bind_group in layout.bind_groups.iter_mut() {
let mut binding_changed = false;
for binding in bind_group.bindings.iter_mut() {
if dynamic_bindings.iter().any(|b| b == &binding.name) {
if pipeline_specialization
.dynamic_bindings
.iter()
.any(|b| b == &binding.name)
{
if let BindType::Uniform {
ref mut dynamic, ..
} = binding.bind_type
Expand All @@ -187,7 +188,6 @@ impl PipelineCompiler {
}
}
}
pipeline_specialization.dynamic_bindings = dynamic_bindings;
specialized_descriptor.layout = Some(layout);

// create a vertex layout that provides all attributes from either the specialized vertex buffers or a zero buffer
Expand Down Expand Up @@ -267,28 +267,6 @@ impl PipelineCompiler {
weak_specialized_pipeline_handle
}

fn get_dynamic_bindings(
&self,
render_resource_bindings: &mut [&mut RenderResourceBindings],
) -> Vec<String> {
render_resource_bindings
.iter()
.flat_map(|bindings| {
bindings
.bindings
.iter()
.filter(|(_, binding)| {
matches!(binding, RenderResourceBinding::Buffer {
dynamic_index: Some(_),
..
})
})
.map(|(name, _)| name)
})
.cloned()
.collect()
}

pub fn iter_compiled_pipelines(
&self,
pipeline_handle: Handle<PipelineDescriptor>,
Expand Down
21 changes: 17 additions & 4 deletions crates/bevy_render/src/pipeline/render_pipelines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ use bevy_property::Properties;
pub struct RenderPipeline {
pub pipeline: Handle<PipelineDescriptor>,
pub specialization: PipelineSpecialization,
/// used to track if PipelineSpecialization::dynamic_bindings is in sync with RenderResourceBindings
pub dynamic_bindings_generation: usize,
}

impl RenderPipeline {
pub fn new(pipeline: Handle<PipelineDescriptor>) -> Self {
RenderPipeline {
specialization: Default::default(),
pipeline,
..Default::default()
dynamic_bindings_generation: std::usize::MAX,
}
}

Expand All @@ -31,6 +34,7 @@ impl RenderPipeline {
RenderPipeline {
pipeline,
specialization,
dynamic_bindings_generation: std::usize::MAX,
}
}
}
Expand Down Expand Up @@ -100,7 +104,17 @@ pub fn draw_render_pipelines_system(
let render_pipelines = &mut *render_pipelines;
for pipeline in render_pipelines.pipelines.iter_mut() {
pipeline.specialization.sample_count = msaa.samples;
// TODO: move these to mesh.rs?
if pipeline.dynamic_bindings_generation
!= render_pipelines.bindings.dynamic_bindings_generation()
{
pipeline.specialization.dynamic_bindings = render_pipelines
.bindings
.iter_dynamic_bindings()
.map(|name| name.to_string())
.collect::<Vec<String>>();
pipeline.dynamic_bindings_generation =
render_pipelines.bindings.dynamic_bindings_generation();
}
}

for render_pipeline in render_pipelines.pipelines.iter_mut() {
Expand All @@ -112,8 +126,7 @@ pub fn draw_render_pipelines_system(
.set_pipeline(
&mut draw,
&render_pipeline.pipeline,
&mut render_pipeline.specialization,
render_resource_bindings,
&render_pipeline.specialization,
)
.unwrap();
draw_context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ impl RenderResourceBinding {
}
}

pub fn is_dynamic_buffer(&self) -> bool {
matches!(self, RenderResourceBinding::Buffer {
dynamic_index: Some(_),
..
})
}

pub fn get_sampler(&self) -> Option<SamplerId> {
if let RenderResourceBinding::Sampler(sampler) = self {
Some(*sampler)
Expand Down Expand Up @@ -112,6 +119,7 @@ pub struct RenderResourceBindings {
bind_groups: HashMap<BindGroupId, BindGroup>,
bind_group_descriptors: HashMap<BindGroupDescriptorId, Option<BindGroupId>>,
dirty_bind_groups: HashSet<BindGroupId>,
dynamic_bindings_generation: usize,
}

impl RenderResourceBindings {
Expand All @@ -124,9 +132,17 @@ impl RenderResourceBindings {
self.bindings.insert(name.to_string(), binding);
}

/// The current "generation" of dynamic bindings. This number increments every time a dynamic binding changes
pub fn dynamic_bindings_generation(&self) -> usize {
self.dynamic_bindings_generation
}

fn try_set_dirty(&mut self, name: &str, binding: &RenderResourceBinding) {
if let Some(current_binding) = self.bindings.get(name) {
if current_binding != binding {
if current_binding.is_dynamic_buffer() {
self.dynamic_bindings_generation += 1;
}
// TODO: this is crude. we shouldn't need to invalidate all bind groups
for id in self.bind_groups.keys() {
self.dirty_bind_groups.insert(*id);
Expand Down Expand Up @@ -236,6 +252,18 @@ impl RenderResourceBindings {

Some(bind_group_builder.finish())
}

pub fn iter_dynamic_bindings(&self) -> impl Iterator<Item = &str> {
self.bindings
.iter()
.filter(|(_, binding)| {
matches!(binding, RenderResourceBinding::Buffer {
dynamic_index: Some(_),
..
})
})
.map(|(name, _)| name.as_str())
}
}

#[derive(Debug, Default)]
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_text/src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,11 @@ impl<'a> Drawable for DrawableText<'a> {
context.set_pipeline(
draw,
&bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE,
&mut PipelineSpecialization {
&PipelineSpecialization {
sample_count: self.msaa.samples,
vertex_buffer_descriptor: self.font_quad_vertex_descriptor.clone(),
..Default::default()
},
&mut [self.render_resource_bindings],
)?;

let render_resource_context = &**context.render_resource_context;
Expand Down

0 comments on commit a4b5f7f

Please sign in to comment.