Recreate tonemapping bind group if view uniforms buffer has changed (#7904)

# Objective

- Currently, https://github.com/vleue/bevy_bistro_playground crashes when enabling shadows, because this allocates a new buffer for the view uniforms, but the `TonemappingNode` uses a cached bind group that doesn't reference the new uniform buffer.

## Solution

- Check if the buffer id of the view uniforms buffer has changed and create a new bind group if it did.
This commit is contained in:
Edgar Geier 2023-03-05 15:10:25 +00:00
parent 04b42132a8
commit 05b1a6d0b5

View file

@ -8,9 +8,9 @@ use bevy_render::{
render_asset::RenderAssets,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
render_resource::{
BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, LoadOp, Operations,
PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor,
TextureViewId,
BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferId, LoadOp,
Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor,
SamplerDescriptor, TextureViewId,
},
renderer::RenderContext,
texture::Image,
@ -29,7 +29,7 @@ pub struct TonemappingNode {
),
With<ExtractedView>,
>,
cached_texture_bind_group: Mutex<Option<(TextureViewId, BindGroup)>>,
cached_bind_group: Mutex<Option<(BufferId, TextureViewId, BindGroup)>>,
last_tonemapping: Mutex<Option<Tonemapping>>,
}
@ -39,7 +39,7 @@ impl TonemappingNode {
pub fn new(world: &mut World) -> Self {
Self {
query: QueryState::new(world),
cached_texture_bind_group: Mutex::new(None),
cached_bind_group: Mutex::new(None),
last_tonemapping: Mutex::new(None),
}
}
@ -65,7 +65,8 @@ impl Node for TonemappingNode {
let tonemapping_pipeline = world.resource::<TonemappingPipeline>();
let gpu_images = world.get_resource::<RenderAssets<Image>>().unwrap();
let view_uniforms_resource = world.resource::<ViewUniforms>();
let view_uniforms = view_uniforms_resource.uniforms.binding().unwrap();
let view_uniforms = &view_uniforms_resource.uniforms;
let view_uniforms_id = view_uniforms.buffer().unwrap().id();
let (view_uniform_offset, target, view_tonemapping_pipeline, tonemapping) =
match self.query.get_manual(world, view_entity) {
@ -97,9 +98,15 @@ impl Node for TonemappingNode {
*last_tonemapping = Some(*tonemapping);
}
let mut cached_bind_group = self.cached_texture_bind_group.lock().unwrap();
let mut cached_bind_group = self.cached_bind_group.lock().unwrap();
let bind_group = match &mut *cached_bind_group {
Some((id, bind_group)) if source.id() == *id && !tonemapping_changed => bind_group,
Some((buffer_id, texture_id, bind_group))
if view_uniforms_id == *buffer_id
&& source.id() == *texture_id
&& !tonemapping_changed =>
{
bind_group
}
cached_bind_group => {
let sampler = render_context
.render_device()
@ -110,7 +117,7 @@ impl Node for TonemappingNode {
let mut entries = vec![
BindGroupEntry {
binding: 0,
resource: view_uniforms.clone(),
resource: view_uniforms.binding().unwrap(),
},
BindGroupEntry {
binding: 1,
@ -138,7 +145,8 @@ impl Node for TonemappingNode {
entries: &entries,
});
let (_, bind_group) = cached_bind_group.insert((source.id(), bind_group));
let (_, _, bind_group) =
cached_bind_group.insert((view_uniforms_id, source.id(), bind_group));
bind_group
}
};