Reuse sampler when creating cached bind groups (#10610)

# Objective

- Some passes recreate a sampler when creating a bind group to be
cached, even if the sampler is always the same.

## Solution

- Store the sampler in the corresponding pipeline resource.
This commit is contained in:
Kanabenki 2024-01-26 14:34:29 +01:00 committed by GitHub
parent bfb8e9978a
commit 86e91f4368
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 37 additions and 41 deletions

View File

@ -5,7 +5,6 @@ use crate::{
}; };
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, Handle}; use bevy_asset::{load_internal_asset, Handle};
use bevy_derive::Deref;
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{ use bevy_render::{
@ -22,6 +21,7 @@ use bevy_render::{
view::{ExtractedView, ViewTarget}, view::{ExtractedView, ViewTarget},
Render, RenderApp, RenderSet, Render, RenderApp, RenderSet,
}; };
use bevy_utils::default;
mod node; mod node;
@ -123,27 +123,37 @@ impl Plugin for FxaaPlugin {
} }
} }
#[derive(Resource, Deref)] #[derive(Resource)]
pub struct FxaaPipeline { pub struct FxaaPipeline {
texture_bind_group: BindGroupLayout, texture_bind_group: BindGroupLayout,
sampler: Sampler,
} }
impl FromWorld for FxaaPipeline { impl FromWorld for FxaaPipeline {
fn from_world(render_world: &mut World) -> Self { fn from_world(render_world: &mut World) -> Self {
let texture_bind_group = render_world let render_device = render_world.resource::<RenderDevice>();
.resource::<RenderDevice>() let texture_bind_group = render_device.create_bind_group_layout(
.create_bind_group_layout( "fxaa_texture_bind_group_layout",
"fxaa_texture_bind_group_layout", &BindGroupLayoutEntries::sequential(
&BindGroupLayoutEntries::sequential( ShaderStages::FRAGMENT,
ShaderStages::FRAGMENT, (
( texture_2d(TextureSampleType::Float { filterable: true }),
texture_2d(TextureSampleType::Float { filterable: true }), sampler(SamplerBindingType::Filtering),
sampler(SamplerBindingType::Filtering),
),
), ),
); ),
);
FxaaPipeline { texture_bind_group } let sampler = render_device.create_sampler(&SamplerDescriptor {
mipmap_filter: FilterMode::Linear,
mag_filter: FilterMode::Linear,
min_filter: FilterMode::Linear,
..default()
});
FxaaPipeline {
texture_bind_group,
sampler,
}
} }
} }

View File

@ -6,13 +6,12 @@ use bevy_ecs::query::QueryItem;
use bevy_render::{ use bevy_render::{
render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_graph::{NodeRunError, RenderGraphContext, ViewNode},
render_resource::{ render_resource::{
BindGroup, BindGroupEntries, FilterMode, Operations, PipelineCache, BindGroup, BindGroupEntries, Operations, PipelineCache, RenderPassColorAttachment,
RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor, TextureViewId, RenderPassDescriptor, TextureViewId,
}, },
renderer::RenderContext, renderer::RenderContext,
view::ViewTarget, view::ViewTarget,
}; };
use bevy_utils::default;
#[derive(Default)] #[derive(Default)]
pub struct FxaaNode { pub struct FxaaNode {
@ -51,19 +50,10 @@ impl ViewNode for FxaaNode {
let bind_group = match &mut *cached_bind_group { let bind_group = match &mut *cached_bind_group {
Some((id, bind_group)) if source.id() == *id => bind_group, Some((id, bind_group)) if source.id() == *id => bind_group,
cached_bind_group => { cached_bind_group => {
let sampler = render_context
.render_device()
.create_sampler(&SamplerDescriptor {
mipmap_filter: FilterMode::Linear,
mag_filter: FilterMode::Linear,
min_filter: FilterMode::Linear,
..default()
});
let bind_group = render_context.render_device().create_bind_group( let bind_group = render_context.render_device().create_bind_group(
None, None,
&fxaa_pipeline.texture_bind_group, &fxaa_pipeline.texture_bind_group,
&BindGroupEntries::sequential((source, &sampler)), &BindGroupEntries::sequential((source, &fxaa_pipeline.sampler)),
); );
let (_, bind_group) = cached_bind_group.insert((source.id(), bind_group)); let (_, bind_group) = cached_bind_group.insert((source.id(), bind_group));

View File

@ -114,6 +114,7 @@ impl Plugin for TonemappingPlugin {
#[derive(Resource)] #[derive(Resource)]
pub struct TonemappingPipeline { pub struct TonemappingPipeline {
texture_bind_group: BindGroupLayout, texture_bind_group: BindGroupLayout,
sampler: Sampler,
} }
/// Optionally enables a tonemapping shader that attempts to map linear input stimulus into a perceptually uniform image for a given [`Camera`] entity. /// Optionally enables a tonemapping shader that attempts to map linear input stimulus into a perceptually uniform image for a given [`Camera`] entity.
@ -266,12 +267,15 @@ impl FromWorld for TonemappingPipeline {
entries = entries =
entries.extend_with_indices(((3, lut_layout_entries[0]), (4, lut_layout_entries[1]))); entries.extend_with_indices(((3, lut_layout_entries[0]), (4, lut_layout_entries[1])));
let tonemap_texture_bind_group = render_world let render_device = render_world.resource::<RenderDevice>();
.resource::<RenderDevice>() let tonemap_texture_bind_group = render_device
.create_bind_group_layout("tonemapping_hdr_texture_bind_group_layout", &entries); .create_bind_group_layout("tonemapping_hdr_texture_bind_group_layout", &entries);
let sampler = render_device.create_sampler(&SamplerDescriptor::default());
TonemappingPipeline { TonemappingPipeline {
texture_bind_group: tonemap_texture_bind_group, texture_bind_group: tonemap_texture_bind_group,
sampler,
} }
} }
} }

View File

@ -8,7 +8,7 @@ use bevy_render::{
render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_graph::{NodeRunError, RenderGraphContext, ViewNode},
render_resource::{ render_resource::{
BindGroup, BindGroupEntries, BufferId, LoadOp, Operations, PipelineCache, BindGroup, BindGroupEntries, BufferId, LoadOp, Operations, PipelineCache,
RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor, StoreOp, TextureViewId, RenderPassColorAttachment, RenderPassDescriptor, StoreOp, TextureViewId,
}, },
renderer::RenderContext, renderer::RenderContext,
texture::Image, texture::Image,
@ -80,10 +80,6 @@ impl ViewNode for TonemappingNode {
bind_group bind_group
} }
cached_bind_group => { cached_bind_group => {
let sampler = render_context
.render_device()
.create_sampler(&SamplerDescriptor::default());
let tonemapping_luts = world.resource::<TonemappingLuts>(); let tonemapping_luts = world.resource::<TonemappingLuts>();
let lut_bindings = get_lut_bindings(gpu_images, tonemapping_luts, tonemapping); let lut_bindings = get_lut_bindings(gpu_images, tonemapping_luts, tonemapping);
@ -94,7 +90,7 @@ impl ViewNode for TonemappingNode {
&BindGroupEntries::sequential(( &BindGroupEntries::sequential((
view_uniforms, view_uniforms,
source, source,
&sampler, &tonemapping_pipeline.sampler,
lut_bindings.0, lut_bindings.0,
lut_bindings.1, lut_bindings.1,
)), )),

View File

@ -5,7 +5,7 @@ use bevy_render::{
render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_graph::{NodeRunError, RenderGraphContext, ViewNode},
render_resource::{ render_resource::{
BindGroup, BindGroupEntries, LoadOp, Operations, PipelineCache, RenderPassColorAttachment, BindGroup, BindGroupEntries, LoadOp, Operations, PipelineCache, RenderPassColorAttachment,
RenderPassDescriptor, SamplerDescriptor, StoreOp, TextureViewId, RenderPassDescriptor, StoreOp, TextureViewId,
}, },
renderer::RenderContext, renderer::RenderContext,
view::ViewTarget, view::ViewTarget,
@ -52,14 +52,10 @@ impl ViewNode for UpscalingNode {
let bind_group = match &mut *cached_bind_group { let bind_group = match &mut *cached_bind_group {
Some((id, bind_group)) if upscaled_texture.id() == *id => bind_group, Some((id, bind_group)) if upscaled_texture.id() == *id => bind_group,
cached_bind_group => { cached_bind_group => {
let sampler = render_context
.render_device()
.create_sampler(&SamplerDescriptor::default());
let bind_group = render_context.render_device().create_bind_group( let bind_group = render_context.render_device().create_bind_group(
None, None,
&blit_pipeline.texture_bind_group, &blit_pipeline.texture_bind_group,
&BindGroupEntries::sequential((upscaled_texture, &sampler)), &BindGroupEntries::sequential((upscaled_texture, &blit_pipeline.sampler)),
); );
let (_, bind_group) = cached_bind_group.insert((upscaled_texture.id(), bind_group)); let (_, bind_group) = cached_bind_group.insert((upscaled_texture.id(), bind_group));