diff --git a/crates/bevy_core_pipeline/src/bloom/mod.rs b/crates/bevy_core_pipeline/src/bloom/mod.rs index 9f8d0aec2946f..c1299794df570 100644 --- a/crates/bevy_core_pipeline/src/bloom/mod.rs +++ b/crates/bevy_core_pipeline/src/bloom/mod.rs @@ -170,30 +170,16 @@ impl ViewNode for BloomNode { // First downsample pass { - let downsampling_first_bind_group = - render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: Some("bloom_downsampling_first_bind_group"), - layout: &downsampling_pipeline_res.bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - // Read from main texture directly - resource: BindingResource::TextureView( - view_target.main_texture_view(), - ), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(&bind_groups.sampler), - }, - BindGroupEntry { - binding: 2, - resource: uniforms.clone(), - }, - ], - }); + let downsampling_first_bind_group = render_context.render_device().create_bind_group( + "bloom_downsampling_first_bind_group", + &downsampling_pipeline_res.bind_group_layout, + &BindGroupEntries::sequential(( + // Read from main texture directly + view_target.main_texture_view(), + &bind_groups.sampler, + uniforms.clone(), + )), + ); let view = &bloom_texture.view(0); let mut downsampling_first_pass = @@ -416,46 +402,28 @@ fn prepare_bloom_bind_groups( let mut downsampling_bind_groups = Vec::with_capacity(bind_group_count); for mip in 1..bloom_texture.mip_count { - downsampling_bind_groups.push(render_device.create_bind_group(&BindGroupDescriptor { - label: Some("bloom_downsampling_bind_group"), - layout: &downsampling_pipeline.bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(&bloom_texture.view(mip - 1)), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(sampler), - }, - BindGroupEntry { - binding: 2, - resource: uniforms.binding().unwrap(), - }, - ], - })); + downsampling_bind_groups.push(render_device.create_bind_group( + "bloom_downsampling_bind_group", + &downsampling_pipeline.bind_group_layout, + &BindGroupEntries::sequential(( + &bloom_texture.view(mip - 1), + sampler, + uniforms.binding().unwrap(), + )), + )); } let mut upsampling_bind_groups = Vec::with_capacity(bind_group_count); for mip in (0..bloom_texture.mip_count).rev() { - upsampling_bind_groups.push(render_device.create_bind_group(&BindGroupDescriptor { - label: Some("bloom_upsampling_bind_group"), - layout: &upsampling_pipeline.bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(&bloom_texture.view(mip)), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(sampler), - }, - BindGroupEntry { - binding: 2, - resource: uniforms.binding().unwrap(), - }, - ], - })); + upsampling_bind_groups.push(render_device.create_bind_group( + "bloom_upsampling_bind_group", + &upsampling_pipeline.bind_group_layout, + &BindGroupEntries::sequential(( + &bloom_texture.view(mip), + sampler, + uniforms.binding().unwrap(), + )), + )); } commands.entity(entity).insert(BloomBindGroups { diff --git a/crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/node.rs b/crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/node.rs index 0dd3f086ee27c..5bb8b87ebc58b 100644 --- a/crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/node.rs +++ b/crates/bevy_core_pipeline/src/contrast_adaptive_sharpening/node.rs @@ -7,8 +7,8 @@ use bevy_render::{ extract_component::{ComponentUniforms, DynamicUniformIndex}, render_graph::{Node, NodeRunError, RenderGraphContext}, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferId, Operations, - PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, TextureViewId, + BindGroup, BindGroupEntries, BufferId, Operations, PipelineCache, + RenderPassColorAttachment, RenderPassDescriptor, TextureViewId, }, renderer::RenderContext, view::{ExtractedView, ViewTarget}, @@ -77,29 +77,15 @@ impl Node for CASNode { bind_group } cached_bind_group => { - let bind_group = - render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: Some("cas_bind_group"), - layout: &sharpening_pipeline.texture_bind_group, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(view_target.source), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler( - &sharpening_pipeline.sampler, - ), - }, - BindGroupEntry { - binding: 2, - resource: uniforms, - }, - ], - }); + let bind_group = render_context.render_device().create_bind_group( + "cas_bind_group", + &sharpening_pipeline.texture_bind_group, + &BindGroupEntries::sequential(( + view_target.source, + &sharpening_pipeline.sampler, + uniforms, + )), + ); let (_, _, bind_group) = cached_bind_group.insert((uniforms_id, source.id(), bind_group)); diff --git a/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs b/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs index 5609896045ec8..c60306286900a 100644 --- a/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs +++ b/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs @@ -18,10 +18,7 @@ use bevy_render::{ use bevy_ecs::query::QueryItem; use bevy_render::{ render_graph::{NodeRunError, RenderGraphContext, ViewNode}, - render_resource::{ - BindGroupDescriptor, BindGroupEntry, BindingResource, Operations, PipelineCache, - RenderPassDescriptor, - }, + render_resource::{Operations, PipelineCache, RenderPassDescriptor}, renderer::RenderContext, }; @@ -94,18 +91,11 @@ impl ViewNode for CopyDeferredLightingIdNode { return Ok(()); }; - let bind_group = render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: Some("copy_deferred_lighting_id_bind_group"), - layout: ©_deferred_lighting_id_pipeline.layout, - entries: &[BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView( - &deferred_lighting_pass_id_texture.default_view, - ), - }], - }); + let bind_group = render_context.render_device().create_bind_group( + "copy_deferred_lighting_id_bind_group", + ©_deferred_lighting_id_pipeline.layout, + &BindGroupEntries::single(&deferred_lighting_pass_id_texture.default_view), + ); let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("copy_deferred_lighting_id_pass"), diff --git a/crates/bevy_core_pipeline/src/fxaa/node.rs b/crates/bevy_core_pipeline/src/fxaa/node.rs index 2daaf0584d981..7eaf4dce268ad 100644 --- a/crates/bevy_core_pipeline/src/fxaa/node.rs +++ b/crates/bevy_core_pipeline/src/fxaa/node.rs @@ -6,9 +6,8 @@ use bevy_ecs::query::QueryItem; use bevy_render::{ render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, FilterMode, Operations, - PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor, - TextureViewId, + BindGroup, BindGroupEntries, FilterMode, Operations, PipelineCache, + RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor, TextureViewId, }, renderer::RenderContext, view::ViewTarget, @@ -61,23 +60,11 @@ impl ViewNode for FxaaNode { ..default() }); - let bind_group = - render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: None, - layout: &fxaa_pipeline.texture_bind_group, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(source), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(&sampler), - }, - ], - }); + let bind_group = render_context.render_device().create_bind_group( + None, + &fxaa_pipeline.texture_bind_group, + &BindGroupEntries::sequential((source, &sampler)), + ); let (_, bind_group) = cached_bind_group.insert((source.id(), bind_group)); bind_group diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index 0646d4ce67ffb..d80bc0fce7bc9 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -8,6 +8,7 @@ use bevy_ecs::prelude::*; use bevy_render::{ camera::ExtractedCamera, render_graph::{Node, NodeRunError, RenderGraphApp, RenderGraphContext}, + render_resource::BindGroupEntries, renderer::RenderContext, view::{Msaa, ViewTarget}, Render, RenderSet, @@ -90,23 +91,11 @@ impl Node for MsaaWritebackNode { depth_stencil_attachment: None, }; - let bind_group = - render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: None, - layout: &blit_pipeline.texture_bind_group, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(post_process.source), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(&blit_pipeline.sampler), - }, - ], - }); + let bind_group = render_context.render_device().create_bind_group( + None, + &blit_pipeline.texture_bind_group, + &BindGroupEntries::sequential((post_process.source, &blit_pipeline.sampler)), + ); let mut render_pass = render_context .command_encoder() diff --git a/crates/bevy_core_pipeline/src/skybox/mod.rs b/crates/bevy_core_pipeline/src/skybox/mod.rs index efc133651930e..11caa03afd8aa 100644 --- a/crates/bevy_core_pipeline/src/skybox/mod.rs +++ b/crates/bevy_core_pipeline/src/skybox/mod.rs @@ -10,13 +10,13 @@ use bevy_render::{ extract_component::{ExtractComponent, ExtractComponentPlugin}, render_asset::RenderAssets, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, - BindGroupLayoutEntry, BindingResource, BindingType, BufferBindingType, - CachedRenderPipelineId, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, - DepthStencilState, FragmentState, MultisampleState, PipelineCache, PrimitiveState, - RenderPipelineDescriptor, SamplerBindingType, Shader, ShaderStages, ShaderType, - SpecializedRenderPipeline, SpecializedRenderPipelines, StencilFaceState, StencilState, - TextureFormat, TextureSampleType, TextureViewDimension, VertexState, + BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor, + BindGroupLayoutEntry, BindingType, BufferBindingType, CachedRenderPipelineId, + ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, DepthStencilState, + FragmentState, MultisampleState, PipelineCache, PrimitiveState, RenderPipelineDescriptor, + SamplerBindingType, Shader, ShaderStages, ShaderType, SpecializedRenderPipeline, + SpecializedRenderPipelines, StencilFaceState, StencilState, TextureFormat, + TextureSampleType, TextureViewDimension, VertexState, }, renderer::RenderDevice, texture::{BevyDefault, Image}, @@ -224,24 +224,15 @@ fn prepare_skybox_bind_groups( if let (Some(skybox), Some(view_uniforms)) = (images.get(&skybox.0), view_uniforms.uniforms.binding()) { - let bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: Some("skybox_bind_group"), - layout: &pipeline.bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(&skybox.texture_view), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(&skybox.sampler), - }, - BindGroupEntry { - binding: 2, - resource: view_uniforms, - }, - ], - }); + let bind_group = render_device.create_bind_group( + "skybox_bind_group", + &pipeline.bind_group_layout, + &BindGroupEntries::sequential(( + &skybox.texture_view, + &skybox.sampler, + view_uniforms, + )), + ); commands.entity(entity).insert(SkyboxBindGroup(bind_group)); } diff --git a/crates/bevy_core_pipeline/src/taa/mod.rs b/crates/bevy_core_pipeline/src/taa/mod.rs index e61dccc5d4bf5..28926a1b8ed0d 100644 --- a/crates/bevy_core_pipeline/src/taa/mod.rs +++ b/crates/bevy_core_pipeline/src/taa/mod.rs @@ -21,13 +21,13 @@ use bevy_render::{ prelude::{Camera, Projection}, render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner}, render_resource::{ - BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, - BindGroupLayoutEntry, BindingResource, BindingType, CachedRenderPipelineId, - ColorTargetState, ColorWrites, Extent3d, FilterMode, FragmentState, MultisampleState, - Operations, PipelineCache, PrimitiveState, RenderPassColorAttachment, RenderPassDescriptor, - RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, Shader, - ShaderStages, SpecializedRenderPipeline, SpecializedRenderPipelines, TextureDescriptor, - TextureDimension, TextureFormat, TextureSampleType, TextureUsages, TextureViewDimension, + BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, + BindingType, CachedRenderPipelineId, ColorTargetState, ColorWrites, Extent3d, FilterMode, + FragmentState, MultisampleState, Operations, PipelineCache, PrimitiveState, + RenderPassColorAttachment, RenderPassDescriptor, RenderPipelineDescriptor, Sampler, + SamplerBindingType, SamplerDescriptor, Shader, ShaderStages, SpecializedRenderPipeline, + SpecializedRenderPipelines, TextureDescriptor, TextureDimension, TextureFormat, + TextureSampleType, TextureUsages, TextureViewDimension, }, renderer::{RenderContext, RenderDevice}, texture::{BevyDefault, CachedTexture, TextureCache}, @@ -197,45 +197,18 @@ impl ViewNode for TAANode { }; let view_target = view_target.post_process_write(); - let taa_bind_group = - render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: Some("taa_bind_group"), - layout: &pipelines.taa_bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(view_target.source), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::TextureView( - &taa_history_textures.read.default_view, - ), - }, - BindGroupEntry { - binding: 2, - resource: BindingResource::TextureView( - &prepass_motion_vectors_texture.default_view, - ), - }, - BindGroupEntry { - binding: 3, - resource: BindingResource::TextureView( - &prepass_depth_texture.default_view, - ), - }, - BindGroupEntry { - binding: 4, - resource: BindingResource::Sampler(&pipelines.nearest_sampler), - }, - BindGroupEntry { - binding: 5, - resource: BindingResource::Sampler(&pipelines.linear_sampler), - }, - ], - }); + let taa_bind_group = render_context.render_device().create_bind_group( + "taa_bind_group", + &pipelines.taa_bind_group_layout, + &BindGroupEntries::sequential(( + view_target.source, + &taa_history_textures.read.default_view, + &prepass_motion_vectors_texture.default_view, + &prepass_depth_texture.default_view, + &pipelines.nearest_sampler, + &pipelines.linear_sampler, + )), + ); { let mut taa_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { diff --git a/crates/bevy_core_pipeline/src/tonemapping/mod.rs b/crates/bevy_core_pipeline/src/tonemapping/mod.rs index 2af1d48b6eed0..6aada19c458e5 100644 --- a/crates/bevy_core_pipeline/src/tonemapping/mod.rs +++ b/crates/bevy_core_pipeline/src/tonemapping/mod.rs @@ -306,8 +306,7 @@ pub fn get_lut_bindings<'a>( images: &'a RenderAssets, tonemapping_luts: &'a TonemappingLuts, tonemapping: &Tonemapping, - bindings: [u32; 2], -) -> [BindGroupEntry<'a>; 2] { +) -> (&'a TextureView, &'a Sampler) { let image = match tonemapping { // AgX lut texture used when tonemapping doesn't need a texture since it's very small (32x32x32) Tonemapping::None @@ -320,16 +319,7 @@ pub fn get_lut_bindings<'a>( Tonemapping::BlenderFilmic => &tonemapping_luts.blender_filmic, }; let lut_image = images.get(image).unwrap(); - [ - BindGroupEntry { - binding: bindings[0], - resource: BindingResource::TextureView(&lut_image.texture_view), - }, - BindGroupEntry { - binding: bindings[1], - resource: BindingResource::Sampler(&lut_image.sampler), - }, - ] + (&lut_image.texture_view, &lut_image.sampler) } pub fn get_lut_bind_group_layout_entries(bindings: [u32; 2]) -> [BindGroupLayoutEntry; 2] { diff --git a/crates/bevy_core_pipeline/src/tonemapping/node.rs b/crates/bevy_core_pipeline/src/tonemapping/node.rs index e3da4aa03e417..1d1c95d970850 100644 --- a/crates/bevy_core_pipeline/src/tonemapping/node.rs +++ b/crates/bevy_core_pipeline/src/tonemapping/node.rs @@ -7,9 +7,8 @@ use bevy_render::{ render_asset::RenderAssets, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferId, LoadOp, - Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, - SamplerDescriptor, TextureViewId, + BindGroup, BindGroupEntries, BufferId, LoadOp, Operations, PipelineCache, + RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor, TextureViewId, }, renderer::RenderContext, texture::Image, @@ -88,36 +87,19 @@ impl ViewNode for TonemappingNode { let tonemapping_luts = world.resource::(); - let mut entries = vec![ - BindGroupEntry { - binding: 0, - resource: view_uniforms.binding().unwrap(), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::TextureView(source), - }, - BindGroupEntry { - binding: 2, - resource: BindingResource::Sampler(&sampler), - }, - ]; - - entries.extend(get_lut_bindings( - gpu_images, - tonemapping_luts, - tonemapping, - [3, 4], - )); - - let bind_group = - render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: None, - layout: &tonemapping_pipeline.texture_bind_group, - entries: &entries, - }); + let lut_bindings = get_lut_bindings(gpu_images, tonemapping_luts, tonemapping); + + let bind_group = render_context.render_device().create_bind_group( + None, + &tonemapping_pipeline.texture_bind_group, + &BindGroupEntries::sequential(( + view_uniforms, + source, + &sampler, + lut_bindings.0, + lut_bindings.1, + )), + ); let (_, _, bind_group) = cached_bind_group.insert((view_uniforms_id, source.id(), bind_group)); diff --git a/crates/bevy_core_pipeline/src/upscaling/node.rs b/crates/bevy_core_pipeline/src/upscaling/node.rs index 76ff1d195c998..536b2b9437515 100644 --- a/crates/bevy_core_pipeline/src/upscaling/node.rs +++ b/crates/bevy_core_pipeline/src/upscaling/node.rs @@ -4,9 +4,8 @@ use bevy_render::{ camera::{CameraOutputMode, ExtractedCamera}, render_graph::{NodeRunError, RenderGraphContext, ViewNode}, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, LoadOp, Operations, - PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor, - TextureViewId, + BindGroup, BindGroupEntries, LoadOp, Operations, PipelineCache, RenderPassColorAttachment, + RenderPassDescriptor, SamplerDescriptor, TextureViewId, }, renderer::RenderContext, view::ViewTarget, @@ -57,23 +56,11 @@ impl ViewNode for UpscalingNode { .render_device() .create_sampler(&SamplerDescriptor::default()); - let bind_group = - render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: None, - layout: &blit_pipeline.texture_bind_group, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(upscaled_texture), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(&sampler), - }, - ], - }); + let bind_group = render_context.render_device().create_bind_group( + None, + &blit_pipeline.texture_bind_group, + &BindGroupEntries::sequential((upscaled_texture, &sampler)), + ); let (_, bind_group) = cached_bind_group.insert((upscaled_texture.id(), bind_group)); bind_group diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index 2efaa9c914607..446605b43e4f8 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -52,7 +52,7 @@ use bevy_render::{ render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets}, render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass}, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, + BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, Buffer, BufferBindingType, BufferInitDescriptor, BufferUsages, Shader, ShaderStages, ShaderType, VertexAttribute, VertexBufferLayout, VertexFormat, VertexStepMode, @@ -422,14 +422,11 @@ fn prepare_line_gizmo_bind_group( ) { if let Some(binding) = line_gizmo_uniforms.uniforms().binding() { commands.insert_resource(LineGizmoUniformBindgroup { - bindgroup: render_device.create_bind_group(&BindGroupDescriptor { - entries: &[BindGroupEntry { - binding: 0, - resource: binding, - }], - label: Some("LineGizmoUniform bindgroup"), - layout: &line_gizmo_uniform_layout.layout, - }), + bindgroup: render_device.create_bind_group( + "LineGizmoUniform bindgroup", + &line_gizmo_uniform_layout.layout, + &BindGroupEntries::single(binding), + ), }); } } diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index b8b61d15573da..f679f638d42ac 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -191,16 +191,11 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { return Ok(()); }; - let bind_group_1 = render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: Some("deferred_lighting_layout_group_1"), - layout: &deferred_lighting_layout.bind_group_layout_1, - entries: &[BindGroupEntry { - binding: 0, - resource: deferred_lighting_pass_id_binding.clone(), - }], - }); + let bind_group_1 = render_context.render_device().create_bind_group( + "deferred_lighting_layout_group_1", + &deferred_lighting_layout.bind_group_layout_1, + &BindGroupEntries::single(deferred_lighting_pass_id_binding), + ); let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { label: Some("deferred_lighting_pass"), diff --git a/crates/bevy_pbr/src/environment_map/mod.rs b/crates/bevy_pbr/src/environment_map/mod.rs index f46f0309f0cac..8cc74a212a396 100644 --- a/crates/bevy_pbr/src/environment_map/mod.rs +++ b/crates/bevy_pbr/src/environment_map/mod.rs @@ -7,8 +7,8 @@ use bevy_render::{ extract_component::{ExtractComponent, ExtractComponentPlugin}, render_asset::RenderAssets, render_resource::{ - BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, SamplerBindingType, - Shader, ShaderStages, TextureSampleType, TextureViewDimension, + BindGroupLayoutEntry, BindingType, Sampler, SamplerBindingType, Shader, ShaderStages, + TextureSampleType, TextureView, TextureViewDimension, }, texture::{FallbackImageCubemap, Image}, }; @@ -65,8 +65,7 @@ pub fn get_bindings<'a>( environment_map_light: Option<&EnvironmentMapLight>, images: &'a RenderAssets, fallback_image_cubemap: &'a FallbackImageCubemap, - bindings: [u32; 3], -) -> [BindGroupEntry<'a>; 3] { +) -> (&'a TextureView, &'a TextureView, &'a Sampler) { let (diffuse_map, specular_map) = match ( environment_map_light.and_then(|env_map| images.get(&env_map.diffuse_map)), environment_map_light.and_then(|env_map| images.get(&env_map.specular_map)), @@ -80,20 +79,7 @@ pub fn get_bindings<'a>( ), }; - [ - BindGroupEntry { - binding: bindings[0], - resource: BindingResource::TextureView(diffuse_map), - }, - BindGroupEntry { - binding: bindings[1], - resource: BindingResource::TextureView(specular_map), - }, - BindGroupEntry { - binding: bindings[2], - resource: BindingResource::Sampler(&fallback_image_cubemap.sampler), - }, - ] + (diffuse_map, specular_map, &fallback_image_cubemap.sampler) } pub fn get_bind_group_layout_entries(bindings: [u32; 3]) -> [BindGroupLayoutEntry; 3] { diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 6c5b4559d045c..54155ce385a0e 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -35,7 +35,7 @@ use bevy_render::{ RenderPhase, SetItemPipeline, TrackedRenderPass, }, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, + BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BufferBindingType, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, DepthStencilState, DynamicUniformBuffer, FragmentState, FrontFace, MultisampleState, PipelineCache, PolygonMode, PrimitiveState, PushConstantRange, @@ -713,42 +713,22 @@ pub fn prepare_prepass_view_bind_group( view_uniforms.uniforms.binding(), globals_buffer.buffer.binding(), ) { - prepass_view_bind_group.no_motion_vectors = - Some(render_device.create_bind_group(&BindGroupDescriptor { - entries: &[ - BindGroupEntry { - binding: 0, - resource: view_binding.clone(), - }, - BindGroupEntry { - binding: 1, - resource: globals_binding.clone(), - }, - ], - label: Some("prepass_view_no_motion_vectors_bind_group"), - layout: &prepass_pipeline.view_layout_no_motion_vectors, - })); + prepass_view_bind_group.no_motion_vectors = Some(render_device.create_bind_group( + "prepass_view_no_motion_vectors_bind_group", + &prepass_pipeline.view_layout_no_motion_vectors, + &BindGroupEntries::sequential((view_binding.clone(), globals_binding.clone())), + )); if let Some(previous_view_proj_binding) = previous_view_proj_uniforms.uniforms.binding() { - prepass_view_bind_group.motion_vectors = - Some(render_device.create_bind_group(&BindGroupDescriptor { - entries: &[ - BindGroupEntry { - binding: 0, - resource: view_binding, - }, - BindGroupEntry { - binding: 1, - resource: globals_binding, - }, - BindGroupEntry { - binding: 2, - resource: previous_view_proj_binding, - }, - ], - label: Some("prepass_view_motion_vectors_bind_group"), - layout: &prepass_pipeline.view_layout_motion_vectors, - })); + prepass_view_bind_group.motion_vectors = Some(render_device.create_bind_group( + "prepass_view_motion_vectors_bind_group", + &prepass_pipeline.view_layout_motion_vectors, + &BindGroupEntries::sequential(( + view_binding, + globals_binding, + previous_view_proj_binding, + )), + )); } } } diff --git a/crates/bevy_pbr/src/prepass/prepass_bindings.rs b/crates/bevy_pbr/src/prepass/prepass_bindings.rs index acbf80ceabde1..b72ddd1e318cd 100644 --- a/crates/bevy_pbr/src/prepass/prepass_bindings.rs +++ b/crates/bevy_pbr/src/prepass/prepass_bindings.rs @@ -1,7 +1,7 @@ use bevy_core_pipeline::prepass::ViewPrepassTextures; use bevy_render::render_resource::{ - BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, ShaderStages, - TextureAspect, TextureSampleType, TextureView, TextureViewDescriptor, TextureViewDimension, + BindGroupLayoutEntry, BindingType, ShaderStages, TextureAspect, TextureSampleType, TextureView, + TextureViewDescriptor, TextureViewDimension, }; use bevy_utils::default; use smallvec::SmallVec; @@ -83,51 +83,7 @@ pub fn get_bind_group_layout_entries( result } -// Needed so the texture views can live long enough. -pub struct PrepassBindingsSet { - depth_view: Option, - normal_view: Option, - motion_vectors_view: Option, - deferred_view: Option, -} - -impl PrepassBindingsSet { - pub fn get_entries(&self, bindings: [u32; 4]) -> SmallVec<[BindGroupEntry; 4]> { - let mut result = SmallVec::<[BindGroupEntry; 4]>::new(); - - if let Some(ref depth_view) = self.depth_view { - result.push(BindGroupEntry { - binding: bindings[0], - resource: BindingResource::TextureView(depth_view), - }); - } - - if let Some(ref normal_view) = self.normal_view { - result.push(BindGroupEntry { - binding: bindings[1], - resource: BindingResource::TextureView(normal_view), - }); - } - - if let Some(ref motion_vectors_view) = self.motion_vectors_view { - result.push(BindGroupEntry { - binding: bindings[2], - resource: BindingResource::TextureView(motion_vectors_view), - }); - } - - if let Some(ref deferred_view) = self.deferred_view { - result.push(BindGroupEntry { - binding: bindings[3], - resource: BindingResource::TextureView(deferred_view), - }); - } - - result - } -} - -pub fn get_bindings(prepass_textures: Option<&ViewPrepassTextures>) -> PrepassBindingsSet { +pub fn get_bindings(prepass_textures: Option<&ViewPrepassTextures>) -> [Option; 4] { let depth_desc = TextureViewDescriptor { label: Some("prepass_depth"), aspect: TextureAspect::DepthOnly, @@ -149,10 +105,5 @@ pub fn get_bindings(prepass_textures: Option<&ViewPrepassTextures>) -> PrepassBi .and_then(|x| x.deferred.as_ref()) .map(|texture| texture.default_view.clone()); - PrepassBindingsSet { - depth_view, - normal_view, - motion_vectors_view, - deferred_view, - } + [depth_view, normal_view, motion_vectors_view, deferred_view] } diff --git a/crates/bevy_pbr/src/render/mesh_bindings.rs b/crates/bevy_pbr/src/render/mesh_bindings.rs index dcc01e1aa4c8b..bf45fd12b8c83 100644 --- a/crates/bevy_pbr/src/render/mesh_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_bindings.rs @@ -4,8 +4,7 @@ use bevy_math::Mat4; use bevy_render::{ mesh::morph::MAX_MORPH_WEIGHTS, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupLayout, BindGroupLayoutDescriptor, - BindingResource, Buffer, TextureView, + BindGroup, BindGroupLayout, BindGroupLayoutDescriptor, BindingResource, Buffer, TextureView, }, renderer::RenderDevice, }; @@ -179,11 +178,11 @@ impl MeshLayouts { // ---------- BindGroup methods ---------- pub fn model_only(&self, render_device: &RenderDevice, model: &BindingResource) -> BindGroup { - render_device.create_bind_group(&BindGroupDescriptor { - entries: &[entry::model(0, model.clone())], - layout: &self.model_only, - label: Some("model_only_mesh_bind_group"), - }) + render_device.create_bind_group( + "model_only_mesh_bind_group", + &self.model_only, + &[entry::model(0, model.clone())], + ) } pub fn skinned( &self, @@ -191,11 +190,11 @@ impl MeshLayouts { model: &BindingResource, skin: &Buffer, ) -> BindGroup { - render_device.create_bind_group(&BindGroupDescriptor { - entries: &[entry::model(0, model.clone()), entry::skinning(1, skin)], - layout: &self.skinned, - label: Some("skinned_mesh_bind_group"), - }) + render_device.create_bind_group( + "skinned_mesh_bind_group", + &self.skinned, + &[entry::model(0, model.clone()), entry::skinning(1, skin)], + ) } pub fn morphed( &self, @@ -204,15 +203,15 @@ impl MeshLayouts { weights: &Buffer, targets: &TextureView, ) -> BindGroup { - render_device.create_bind_group(&BindGroupDescriptor { - entries: &[ + render_device.create_bind_group( + "morphed_mesh_bind_group", + &self.morphed, + &[ entry::model(0, model.clone()), entry::weights(2, weights), entry::targets(3, targets), ], - layout: &self.morphed, - label: Some("morphed_mesh_bind_group"), - }) + ) } pub fn morphed_skinned( &self, @@ -222,15 +221,15 @@ impl MeshLayouts { weights: &Buffer, targets: &TextureView, ) -> BindGroup { - render_device.create_bind_group(&BindGroupDescriptor { - entries: &[ + render_device.create_bind_group( + "morphed_skinned_mesh_bind_group", + &self.morphed_skinned, + &[ entry::model(0, model.clone()), entry::skinning(1, skin), entry::weights(2, weights), entry::targets(3, targets), ], - layout: &self.morphed_skinned, - label: Some("morphed_skinned_mesh_bind_group"), - }) + ) } } diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.rs b/crates/bevy_pbr/src/render/mesh_view_bindings.rs index 8ed474769525f..ba66561c6d785 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.rs @@ -15,9 +15,9 @@ use bevy_render::{ globals::{GlobalsBuffer, GlobalsUniform}, render_asset::RenderAssets, render_resource::{ - BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, - BindGroupLayoutEntry, BindingResource, BindingType, BufferBindingType, SamplerBindingType, - ShaderStages, ShaderType, TextureFormat, TextureSampleType, TextureViewDimension, + BindGroup, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, + BufferBindingType, DynamicBindGroupEntries, SamplerBindingType, ShaderStages, ShaderType, + TextureFormat, TextureSampleType, TextureViewDimension, }, renderer::RenderDevice, texture::{BevyDefault, FallbackImageCubemap, FallbackImageMsaa, Image}, @@ -383,8 +383,8 @@ pub fn prepare_mesh_view_bind_groups( ) { for ( entity, - view_shadow_bindings, - view_cluster_bindings, + shadow_bindings, + cluster_bindings, ssao_textures, prepass_textures, environment_map, @@ -395,108 +395,58 @@ pub fn prepare_mesh_view_bind_groups( .image_for_samplecount(1, TextureFormat::bevy_default()) .texture_view .clone(); + let ssao_view = ssao_textures + .map(|t| &t.screen_space_ambient_occlusion_texture.default_view) + .unwrap_or(&fallback_ssao); let layout = &mesh_pipeline.get_view_layout( MeshPipelineViewLayoutKey::from(*msaa) | MeshPipelineViewLayoutKey::from(prepass_textures), ); - let mut entries = vec![ - BindGroupEntry { - binding: 0, - resource: view_binding.clone(), - }, - BindGroupEntry { - binding: 1, - resource: light_binding.clone(), - }, - BindGroupEntry { - binding: 2, - resource: BindingResource::TextureView( - &view_shadow_bindings.point_light_depth_texture_view, - ), - }, - BindGroupEntry { - binding: 3, - resource: BindingResource::Sampler(&shadow_samplers.point_light_sampler), - }, - BindGroupEntry { - binding: 4, - resource: BindingResource::TextureView( - &view_shadow_bindings.directional_light_depth_texture_view, - ), - }, - BindGroupEntry { - binding: 5, - resource: BindingResource::Sampler(&shadow_samplers.directional_light_sampler), - }, - BindGroupEntry { - binding: 6, - resource: point_light_binding.clone(), - }, - BindGroupEntry { - binding: 7, - resource: view_cluster_bindings.light_index_lists_binding().unwrap(), - }, - BindGroupEntry { - binding: 8, - resource: view_cluster_bindings.offsets_and_counts_binding().unwrap(), - }, - BindGroupEntry { - binding: 9, - resource: globals.clone(), - }, - BindGroupEntry { - binding: 10, - resource: fog_binding.clone(), - }, - BindGroupEntry { - binding: 11, - resource: BindingResource::TextureView( - ssao_textures - .map(|t| &t.screen_space_ambient_occlusion_texture.default_view) - .unwrap_or(&fallback_ssao), - ), - }, - ]; - - let env_map = environment_map::get_bindings( - environment_map, - &images, - &fallback_cubemap, - [12, 13, 14], - ); - entries.extend_from_slice(&env_map); - - let tonemapping_luts = - get_lut_bindings(&images, &tonemapping_luts, tonemapping, [15, 16]); - entries.extend_from_slice(&tonemapping_luts); - - let label = Some("mesh_view_bind_group"); + let mut entries = DynamicBindGroupEntries::new_with_indices(( + (0, view_binding.clone()), + (1, light_binding.clone()), + (2, &shadow_bindings.point_light_depth_texture_view), + (3, &shadow_samplers.point_light_sampler), + (4, &shadow_bindings.directional_light_depth_texture_view), + (5, &shadow_samplers.directional_light_sampler), + (6, point_light_binding.clone()), + (7, cluster_bindings.light_index_lists_binding().unwrap()), + (8, cluster_bindings.offsets_and_counts_binding().unwrap()), + (9, globals.clone()), + (10, fog_binding.clone()), + (11, ssao_view), + )); + + let env_map_bindings = + environment_map::get_bindings(environment_map, &images, &fallback_cubemap); + entries = entries.extend_with_indices(( + (12, env_map_bindings.0), + (13, env_map_bindings.1), + (14, env_map_bindings.2), + )); + + let lut_bindings = get_lut_bindings(&images, &tonemapping_luts, tonemapping); + entries = entries.extend_with_indices(((15, lut_bindings.0), (16, lut_bindings.1))); // When using WebGL, we can't have a depth texture with multisampling - let prepass_bindings = if cfg!(any(not(feature = "webgl"), not(target_arch = "wasm32"))) - || (cfg!(all(feature = "webgl", target_arch = "wasm32")) && msaa.samples() == 1) + let prepass_bindings; + if cfg!(any(not(feature = "webgl"), not(target_arch = "wasm32"))) || msaa.samples() == 1 { - Some(prepass::get_bindings(prepass_textures)) - } else { - None - }; - - // This if statement is here to make the borrow checker happy. - // Ideally we could just have `entries.extend_from_slice(&prepass_bindings.get_entries([17, 18, 19, 20]));` - // in the existing if statement above, but that either doesn't allow `prepass_bindings` to live long enough, - // as its used when creating the bind group at the end of the function, or causes a `cannot move out of` error. - if let Some(prepass_bindings) = &prepass_bindings { - entries.extend_from_slice(&prepass_bindings.get_entries([17, 18, 19, 20])); + prepass_bindings = prepass::get_bindings(prepass_textures); + for (binding, index) in prepass_bindings + .iter() + .map(Option::as_ref) + .zip([17, 18, 19, 20]) + .flat_map(|(b, i)| b.map(|b| (b, i))) + { + entries = entries.extend_with_indices(((index, binding),)); + } } commands.entity(entity).insert(MeshViewBindGroup { - value: render_device.create_bind_group(&BindGroupDescriptor { - entries: &entries, - label, - layout, - }), + value: render_device.create_bind_group("mesh_view_bind_group", layout, &entries), }); } } diff --git a/crates/bevy_pbr/src/ssao/mod.rs b/crates/bevy_pbr/src/ssao/mod.rs index eaabea3772654..59fb57cfac3c6 100644 --- a/crates/bevy_pbr/src/ssao/mod.rs +++ b/crates/bevy_pbr/src/ssao/mod.rs @@ -21,12 +21,11 @@ use bevy_render::{ prelude::Camera, render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner}, render_resource::{ - AddressMode, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, - BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, - BufferBindingType, CachedComputePipelineId, ComputePassDescriptor, - ComputePipelineDescriptor, Extent3d, FilterMode, PipelineCache, Sampler, - SamplerBindingType, SamplerDescriptor, Shader, ShaderDefVal, ShaderStages, ShaderType, - SpecializedComputePipeline, SpecializedComputePipelines, StorageTextureAccess, + AddressMode, BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor, + BindGroupLayoutEntry, BindingType, BufferBindingType, CachedComputePipelineId, + ComputePassDescriptor, ComputePipelineDescriptor, Extent3d, FilterMode, PipelineCache, + Sampler, SamplerBindingType, SamplerDescriptor, Shader, ShaderDefVal, ShaderStages, + ShaderType, SpecializedComputePipeline, SpecializedComputePipelines, StorageTextureAccess, TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages, TextureView, TextureViewDescriptor, TextureViewDimension, }, @@ -776,171 +775,63 @@ fn prepare_ssao_bind_groups( }; for (entity, ssao_textures, prepass_textures) in &views { - let common_bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: Some("ssao_common_bind_group"), - layout: &pipelines.common_bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::Sampler(&pipelines.point_clamp_sampler), - }, - BindGroupEntry { - binding: 1, - resource: view_uniforms.clone(), - }, - ], - }); + let common_bind_group = render_device.create_bind_group( + "ssao_common_bind_group", + &pipelines.common_bind_group_layout, + &BindGroupEntries::sequential((&pipelines.point_clamp_sampler, view_uniforms.clone())), + ); - let preprocess_depth_mip_view_descriptor = TextureViewDescriptor { - format: Some(TextureFormat::R16Float), - dimension: Some(TextureViewDimension::D2), - mip_level_count: Some(1), - ..default() + let create_depth_view = |mip_level| { + ssao_textures + .preprocessed_depth_texture + .texture + .create_view(&TextureViewDescriptor { + label: Some("ssao_preprocessed_depth_texture_mip_view"), + base_mip_level: mip_level, + format: Some(TextureFormat::R16Float), + dimension: Some(TextureViewDimension::D2), + mip_level_count: Some(1), + ..default() + }) }; - let preprocess_depth_bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: Some("ssao_preprocess_depth_bind_group"), - layout: &pipelines.preprocess_depth_bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView( - &prepass_textures.depth.as_ref().unwrap().default_view, - ), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::TextureView( - &ssao_textures - .preprocessed_depth_texture - .texture - .create_view(&TextureViewDescriptor { - label: Some("ssao_preprocessed_depth_texture_mip_view_0"), - base_mip_level: 0, - ..preprocess_depth_mip_view_descriptor - }), - ), - }, - BindGroupEntry { - binding: 2, - resource: BindingResource::TextureView( - &ssao_textures - .preprocessed_depth_texture - .texture - .create_view(&TextureViewDescriptor { - label: Some("ssao_preprocessed_depth_texture_mip_view_1"), - base_mip_level: 1, - ..preprocess_depth_mip_view_descriptor - }), - ), - }, - BindGroupEntry { - binding: 3, - resource: BindingResource::TextureView( - &ssao_textures - .preprocessed_depth_texture - .texture - .create_view(&TextureViewDescriptor { - label: Some("ssao_preprocessed_depth_texture_mip_view_2"), - base_mip_level: 2, - ..preprocess_depth_mip_view_descriptor - }), - ), - }, - BindGroupEntry { - binding: 4, - resource: BindingResource::TextureView( - &ssao_textures - .preprocessed_depth_texture - .texture - .create_view(&TextureViewDescriptor { - label: Some("ssao_preprocessed_depth_texture_mip_view_3"), - base_mip_level: 3, - ..preprocess_depth_mip_view_descriptor - }), - ), - }, - BindGroupEntry { - binding: 5, - resource: BindingResource::TextureView( - &ssao_textures - .preprocessed_depth_texture - .texture - .create_view(&TextureViewDescriptor { - label: Some("ssao_preprocessed_depth_texture_mip_view_4"), - base_mip_level: 4, - ..preprocess_depth_mip_view_descriptor - }), - ), - }, - ], - }); + let preprocess_depth_bind_group = render_device.create_bind_group( + "ssao_preprocess_depth_bind_group", + &pipelines.preprocess_depth_bind_group_layout, + &BindGroupEntries::sequential(( + &prepass_textures.depth.as_ref().unwrap().default_view, + &create_depth_view(0), + &create_depth_view(1), + &create_depth_view(2), + &create_depth_view(3), + &create_depth_view(4), + )), + ); - let gtao_bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: Some("ssao_gtao_bind_group"), - layout: &pipelines.gtao_bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView( - &ssao_textures.preprocessed_depth_texture.default_view, - ), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::TextureView( - &prepass_textures.normal.as_ref().unwrap().default_view, - ), - }, - BindGroupEntry { - binding: 2, - resource: BindingResource::TextureView(&pipelines.hilbert_index_lut), - }, - BindGroupEntry { - binding: 3, - resource: BindingResource::TextureView( - &ssao_textures.ssao_noisy_texture.default_view, - ), - }, - BindGroupEntry { - binding: 4, - resource: BindingResource::TextureView( - &ssao_textures.depth_differences_texture.default_view, - ), - }, - BindGroupEntry { - binding: 5, - resource: globals_uniforms.clone(), - }, - ], - }); + let gtao_bind_group = render_device.create_bind_group( + "ssao_gtao_bind_group", + &pipelines.gtao_bind_group_layout, + &BindGroupEntries::sequential(( + &ssao_textures.preprocessed_depth_texture.default_view, + &prepass_textures.normal.as_ref().unwrap().default_view, + &pipelines.hilbert_index_lut, + &ssao_textures.ssao_noisy_texture.default_view, + &ssao_textures.depth_differences_texture.default_view, + globals_uniforms.clone(), + )), + ); - let spatial_denoise_bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: Some("ssao_spatial_denoise_bind_group"), - layout: &pipelines.spatial_denoise_bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView( - &ssao_textures.ssao_noisy_texture.default_view, - ), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::TextureView( - &ssao_textures.depth_differences_texture.default_view, - ), - }, - BindGroupEntry { - binding: 2, - resource: BindingResource::TextureView( - &ssao_textures - .screen_space_ambient_occlusion_texture - .default_view, - ), - }, - ], - }); + let spatial_denoise_bind_group = render_device.create_bind_group( + "ssao_spatial_denoise_bind_group", + &pipelines.spatial_denoise_bind_group_layout, + &BindGroupEntries::sequential(( + &ssao_textures.ssao_noisy_texture.default_view, + &ssao_textures.depth_differences_texture.default_view, + &ssao_textures + .screen_space_ambient_occlusion_texture + .default_view, + )), + ); commands.entity(entity).insert(SsaoBindGroups { common_bind_group, diff --git a/crates/bevy_render/src/render_resource/bind_group.rs b/crates/bevy_render/src/render_resource/bind_group.rs index c4de9cb1b6089..8ee876b9c5208 100644 --- a/crates/bevy_render/src/render_resource/bind_group.rs +++ b/crates/bevy_render/src/render_resource/bind_group.rs @@ -9,10 +9,7 @@ use crate::{ pub use bevy_render_macros::AsBindGroup; use encase::ShaderType; use std::ops::Deref; -use wgpu::{ - BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, - BindingResource, -}; +use wgpu::{BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource}; define_atomic_id!(BindGroupId); render_resource_wrapper!(ErasedBindGroup, wgpu::BindGroup); @@ -289,11 +286,7 @@ pub trait AsBindGroup { }) .collect::>(); - let bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: Self::label(), - layout, - entries: &entries, - }); + let bind_group = render_device.create_bind_group(Self::label(), layout, &entries); Ok(PreparedBindGroup { bindings, diff --git a/crates/bevy_render/src/render_resource/bind_group_entries.rs b/crates/bevy_render/src/render_resource/bind_group_entries.rs new file mode 100644 index 0000000000000..09336eeb0a093 --- /dev/null +++ b/crates/bevy_render/src/render_resource/bind_group_entries.rs @@ -0,0 +1,282 @@ +use bevy_utils::all_tuples_with_size; +use wgpu::{BindGroupEntry, BindingResource}; + +use super::{Sampler, TextureView}; + +/// Helper for constructing bindgroups. +/// +/// Allows constructing the descriptor's entries as: +/// ```ignore +/// render_device.create_bind_group( +/// "my_bind_group", +/// &my_layout, +/// &BindGroupEntries::with_indices(( +/// (2, &my_sampler), +/// (3, my_uniform), +/// )), +/// ); +/// ``` +/// +/// instead of +/// +/// ```ignore +/// render_device.create_bind_group( +/// "my_bind_group", +/// &my_layout, +/// &[ +/// BindGroupEntry { +/// binding: 2, +/// resource: BindingResource::Sampler(&my_sampler), +/// }, +/// BindGroupEntry { +/// binding: 3, +/// resource: my_uniform, +/// }, +/// ], +/// ); +/// ``` +/// +/// or +/// +/// ```ignore +/// render_device.create_bind_group( +/// "my_bind_group", +/// &my_layout, +/// &BindGroupEntries::sequential(( +/// &my_sampler, +/// my_uniform, +/// )), +/// ); +/// ``` +/// +/// instead of +/// +/// ```ignore +/// render_device.create_bind_group( +/// "my_bind_group", +/// &my_layout, +/// &[ +/// BindGroupEntry { +/// binding: 0, +/// resource: BindingResource::Sampler(&my_sampler), +/// }, +/// BindGroupEntry { +/// binding: 1, +/// resource: my_uniform, +/// }, +/// ], +/// ); +/// ``` +/// +/// or +/// +/// ```ignore +/// render_device.create_bind_group( +/// "my_bind_group", +/// &my_layout, +/// &BindGroupEntries::single(my_uniform), +/// ); +/// ``` +/// +/// instead of +/// +/// ```ignore +/// render_device.create_bind_group( +/// "my_bind_group", +/// &my_layout, +/// &[ +/// BindGroupEntry { +/// binding: 0, +/// resource: my_uniform, +/// }, +/// ], +/// ); +/// ``` + +pub struct BindGroupEntries<'b, const N: usize = 1> { + entries: [BindGroupEntry<'b>; N], +} + +impl<'b, const N: usize> BindGroupEntries<'b, N> { + #[inline] + pub fn sequential(resources: impl IntoBindingArray<'b, N>) -> Self { + let mut i = 0; + Self { + entries: resources.into_array().map(|resource| { + let binding = i; + i += 1; + BindGroupEntry { binding, resource } + }), + } + } + + #[inline] + pub fn with_indices(indexed_resources: impl IntoIndexedBindingArray<'b, N>) -> Self { + Self { + entries: indexed_resources + .into_array() + .map(|(binding, resource)| BindGroupEntry { binding, resource }), + } + } +} + +impl<'b> BindGroupEntries<'b, 1> { + pub fn single(resource: impl IntoBinding<'b>) -> [BindGroupEntry<'b>; 1] { + [BindGroupEntry { + binding: 0, + resource: resource.into_binding(), + }] + } +} + +impl<'b, const N: usize> std::ops::Deref for BindGroupEntries<'b, N> { + type Target = [BindGroupEntry<'b>]; + + fn deref(&self) -> &[BindGroupEntry<'b>] { + &self.entries + } +} + +pub trait IntoBinding<'a> { + fn into_binding(self) -> BindingResource<'a>; +} + +impl<'a> IntoBinding<'a> for &'a TextureView { + #[inline] + fn into_binding(self) -> BindingResource<'a> { + BindingResource::TextureView(self) + } +} + +impl<'a> IntoBinding<'a> for &'a [&'a wgpu::TextureView] { + #[inline] + fn into_binding(self) -> BindingResource<'a> { + BindingResource::TextureViewArray(self) + } +} + +impl<'a> IntoBinding<'a> for &'a Sampler { + #[inline] + fn into_binding(self) -> BindingResource<'a> { + BindingResource::Sampler(self) + } +} + +impl<'a> IntoBinding<'a> for BindingResource<'a> { + #[inline] + fn into_binding(self) -> BindingResource<'a> { + self + } +} + +impl<'a> IntoBinding<'a> for wgpu::BufferBinding<'a> { + #[inline] + fn into_binding(self) -> BindingResource<'a> { + BindingResource::Buffer(self) + } +} + +pub trait IntoBindingArray<'b, const N: usize> { + fn into_array(self) -> [BindingResource<'b>; N]; +} + +macro_rules! impl_to_binding_slice { + ($N: expr, $(($T: ident, $I: ident)),*) => { + impl<'b, $($T: IntoBinding<'b>),*> IntoBindingArray<'b, $N> for ($($T,)*) { + #[inline] + fn into_array(self) -> [BindingResource<'b>; $N] { + let ($($I,)*) = self; + [$($I.into_binding(), )*] + } + } + } +} + +all_tuples_with_size!(impl_to_binding_slice, 1, 32, T, s); + +pub trait IntoIndexedBindingArray<'b, const N: usize> { + fn into_array(self) -> [(u32, BindingResource<'b>); N]; +} + +macro_rules! impl_to_indexed_binding_slice { + ($N: expr, $(($T: ident, $S: ident, $I: ident)),*) => { + impl<'b, $($T: IntoBinding<'b>),*> IntoIndexedBindingArray<'b, $N> for ($((u32, $T),)*) { + #[inline] + fn into_array(self) -> [(u32, BindingResource<'b>); $N] { + let ($(($S, $I),)*) = self; + [$(($S, $I.into_binding())), *] + } + } + } +} + +all_tuples_with_size!(impl_to_indexed_binding_slice, 1, 32, T, n, s); + +pub struct DynamicBindGroupEntries<'b> { + entries: Vec>, +} + +impl<'b> DynamicBindGroupEntries<'b> { + pub fn sequential(entries: impl IntoBindingArray<'b, N>) -> Self { + Self { + entries: entries + .into_array() + .into_iter() + .enumerate() + .map(|(ix, resource)| BindGroupEntry { + binding: ix as u32, + resource, + }) + .collect(), + } + } + + pub fn extend_sequential( + mut self, + entries: impl IntoBindingArray<'b, N>, + ) -> Self { + let start = self.entries.last().unwrap().binding + 1; + self.entries.extend( + entries + .into_array() + .into_iter() + .enumerate() + .map(|(ix, resource)| BindGroupEntry { + binding: start + ix as u32, + resource, + }), + ); + self + } + + pub fn new_with_indices(entries: impl IntoIndexedBindingArray<'b, N>) -> Self { + Self { + entries: entries + .into_array() + .into_iter() + .map(|(binding, resource)| BindGroupEntry { binding, resource }) + .collect(), + } + } + + pub fn extend_with_indices( + mut self, + entries: impl IntoIndexedBindingArray<'b, N>, + ) -> Self { + self.entries.extend( + entries + .into_array() + .into_iter() + .map(|(binding, resource)| BindGroupEntry { binding, resource }), + ); + self + } +} + +impl<'b> std::ops::Deref for DynamicBindGroupEntries<'b> { + type Target = [BindGroupEntry<'b>]; + + fn deref(&self) -> &[BindGroupEntry<'b>] { + &self.entries + } +} diff --git a/crates/bevy_render/src/render_resource/mod.rs b/crates/bevy_render/src/render_resource/mod.rs index f16f5f1269929..b7d245b0bdbc9 100644 --- a/crates/bevy_render/src/render_resource/mod.rs +++ b/crates/bevy_render/src/render_resource/mod.rs @@ -1,5 +1,6 @@ mod batched_uniform_buffer; mod bind_group; +mod bind_group_entries; mod bind_group_layout; mod buffer; mod buffer_vec; @@ -14,6 +15,7 @@ mod texture; mod uniform_buffer; pub use bind_group::*; +pub use bind_group_entries::*; pub use bind_group_layout::*; pub use buffer::*; pub use buffer_vec::*; diff --git a/crates/bevy_render/src/render_resource/uniform_buffer.rs b/crates/bevy_render/src/render_resource/uniform_buffer.rs index 3ecd692ba2880..95196568ff20a 100644 --- a/crates/bevy_render/src/render_resource/uniform_buffer.rs +++ b/crates/bevy_render/src/render_resource/uniform_buffer.rs @@ -13,6 +13,8 @@ use wgpu::{ util::BufferInitDescriptor, BindingResource, BufferBinding, BufferDescriptor, BufferUsages, }; +use super::IntoBinding; + /// Stores data to be transferred to the GPU and made accessible to shaders as a uniform buffer. /// /// Uniform buffers are available to shaders on a read-only basis. Uniform buffers are commonly used to make available to shaders @@ -139,6 +141,16 @@ impl UniformBuffer { } } +impl<'a, T: ShaderType + WriteInto> IntoBinding<'a> for &'a UniformBuffer { + #[inline] + fn into_binding(self) -> BindingResource<'a> { + self.buffer() + .expect("Failed to get buffer") + .as_entire_buffer_binding() + .into_binding() + } +} + /// Stores data to be transferred to the GPU and made accessible to shaders as a dynamic uniform buffer. /// /// Dynamic uniform buffers are available to shaders on a read-only basis. Dynamic uniform buffers are commonly used to make @@ -367,3 +379,10 @@ impl<'a> BufferMut for QueueWriteBufferViewWrapper<'a> { self.buffer_view.write(offset, val); } } + +impl<'a, T: ShaderType + WriteInto> IntoBinding<'a> for &'a DynamicUniformBuffer { + #[inline] + fn into_binding(self) -> BindingResource<'a> { + self.binding().unwrap() + } +} diff --git a/crates/bevy_render/src/renderer/render_device.rs b/crates/bevy_render/src/renderer/render_device.rs index 8a177e94774cb..6a126df8aa41e 100644 --- a/crates/bevy_render/src/renderer/render_device.rs +++ b/crates/bevy_render/src/renderer/render_device.rs @@ -3,7 +3,9 @@ use crate::render_resource::{ RenderPipeline, Sampler, Texture, }; use bevy_ecs::system::Resource; -use wgpu::{util::DeviceExt, BufferAsyncError, BufferBindingType}; +use wgpu::{ + util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BufferAsyncError, BufferBindingType, +}; use super::RenderQueue; @@ -82,8 +84,17 @@ impl RenderDevice { /// Creates a new [`BindGroup`](wgpu::BindGroup). #[inline] - pub fn create_bind_group(&self, desc: &wgpu::BindGroupDescriptor) -> BindGroup { - let wgpu_bind_group = self.device.create_bind_group(desc); + pub fn create_bind_group<'a>( + &self, + label: impl Into>, + layout: &'a BindGroupLayout, + entries: &'a [BindGroupEntry<'a>], + ) -> BindGroup { + let wgpu_bind_group = self.device.create_bind_group(&BindGroupDescriptor { + label: label.into(), + layout, + entries, + }); BindGroup::from(wgpu_bind_group) } diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 37729f3a253ed..31ac4fca2cee3 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -1,5 +1,7 @@ use crate::{ - render_resource::{PipelineCache, SpecializedRenderPipelines, SurfaceTexture, TextureView}, + render_resource::{ + BindGroupEntries, PipelineCache, SpecializedRenderPipelines, SurfaceTexture, TextureView, + }, renderer::{RenderAdapter, RenderDevice, RenderInstance}, texture::TextureFormatPixelInfo, Extract, ExtractSchedule, Render, RenderApp, RenderSet, @@ -413,14 +415,11 @@ pub fn prepare_windows( usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST, mapped_at_creation: false, }); - let bind_group = render_device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("screenshot-to-screen-bind-group"), - layout: &screenshot_pipeline.bind_group_layout, - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&texture_view), - }], - }); + let bind_group = render_device.create_bind_group( + "screenshot-to-screen-bind-group", + &screenshot_pipeline.bind_group_layout, + &BindGroupEntries::single(&texture_view), + ); let pipeline_id = pipelines.specialize( &pipeline_cache, &screenshot_pipeline, diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index 5f62000bc441e..df5e4f0594011 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -596,14 +596,11 @@ pub fn prepare_mesh2d_bind_group( ) { if let Some(binding) = mesh2d_uniforms.binding() { commands.insert_resource(Mesh2dBindGroup { - value: render_device.create_bind_group(&BindGroupDescriptor { - entries: &[BindGroupEntry { - binding: 0, - resource: binding, - }], - label: Some("mesh2d_bind_group"), - layout: &mesh2d_pipeline.mesh_layout, - }), + value: render_device.create_bind_group( + "mesh2d_bind_group", + &mesh2d_pipeline.mesh_layout, + &BindGroupEntries::single(binding), + ), }); } } @@ -626,20 +623,11 @@ pub fn prepare_mesh2d_view_bind_groups( globals_buffer.buffer.binding(), ) { for entity in &views { - let view_bind_group = render_device.create_bind_group(&BindGroupDescriptor { - entries: &[ - BindGroupEntry { - binding: 0, - resource: view_binding.clone(), - }, - BindGroupEntry { - binding: 1, - resource: globals.clone(), - }, - ], - label: Some("mesh2d_view_bind_group"), - layout: &mesh2d_pipeline.view_layout, - }); + let view_bind_group = render_device.create_bind_group( + "mesh2d_view_bind_group", + &mesh2d_pipeline.view_layout, + &BindGroupEntries::sequential((view_binding.clone(), globals.clone())), + ); commands.entity(entity).insert(Mesh2dViewBindGroup { value: view_bind_group, diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index c70d33286ccf8..bebdbad231393 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -21,7 +21,7 @@ use bevy_render::{ DrawFunctions, PhaseItem, RenderCommand, RenderCommandResult, RenderPhase, SetItemPipeline, TrackedRenderPass, }, - render_resource::*, + render_resource::{BindGroupEntries, *}, renderer::{RenderDevice, RenderQueue}, texture::{ BevyDefault, DefaultImageSampler, GpuImage, Image, ImageSampler, TextureFormatPixelInfo, @@ -623,14 +623,11 @@ pub fn prepare_sprites( // Clear the sprite instances sprite_meta.sprite_instance_buffer.clear(); - sprite_meta.view_bind_group = Some(render_device.create_bind_group(&BindGroupDescriptor { - entries: &[BindGroupEntry { - binding: 0, - resource: view_binding, - }], - label: Some("sprite_view_bind_group"), - layout: &sprite_pipeline.view_layout, - })); + sprite_meta.view_bind_group = Some(render_device.create_bind_group( + "sprite_view_bind_group", + &sprite_pipeline.view_layout, + &BindGroupEntries::single(view_binding), + )); // Index buffer indices let mut index = 0; @@ -667,22 +664,14 @@ pub fn prepare_sprites( .values .entry(batch_image_handle) .or_insert_with(|| { - render_device.create_bind_group(&BindGroupDescriptor { - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView( - &gpu_image.texture_view, - ), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(&gpu_image.sampler), - }, - ], - label: Some("sprite_material_bind_group"), - layout: &sprite_pipeline.material_layout, - }) + render_device.create_bind_group( + "sprite_material_bind_group", + &sprite_pipeline.material_layout, + &BindGroupEntries::sequential(( + &gpu_image.texture_view, + &gpu_image.sampler, + )), + ) }); } diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index c852122e6ac76..a7a52c628319e 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -5,7 +5,7 @@ use bevy_core_pipeline::{core_2d::Camera2d, core_3d::Camera3d}; use bevy_hierarchy::Parent; use bevy_render::render_phase::PhaseItem; use bevy_render::view::ViewVisibility; -use bevy_render::{ExtractSchedule, Render}; +use bevy_render::{render_resource::BindGroupEntries, ExtractSchedule, Render}; use bevy_window::{PrimaryWindow, Window}; pub use pipeline::*; pub use render_pass::*; @@ -812,14 +812,11 @@ pub fn prepare_uinodes( let mut batches: Vec<(Entity, UiBatch)> = Vec::with_capacity(*previous_len); ui_meta.vertices.clear(); - ui_meta.view_bind_group = Some(render_device.create_bind_group(&BindGroupDescriptor { - entries: &[BindGroupEntry { - binding: 0, - resource: view_binding, - }], - label: Some("ui_view_bind_group"), - layout: &ui_pipeline.view_layout, - })); + ui_meta.view_bind_group = Some(render_device.create_bind_group( + "ui_view_bind_group", + &ui_pipeline.view_layout, + &BindGroupEntries::single(view_binding), + )); // Vertex buffer index let mut index = 0; @@ -851,24 +848,14 @@ pub fn prepare_uinodes( .values .entry(batch_image_handle) .or_insert_with(|| { - render_device.create_bind_group(&BindGroupDescriptor { - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView( - &gpu_image.texture_view, - ), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler( - &gpu_image.sampler, - ), - }, - ], - label: Some("ui_material_bind_group"), - layout: &ui_pipeline.image_layout, - }) + render_device.create_bind_group( + "ui_material_bind_group", + &ui_pipeline.image_layout, + &BindGroupEntries::sequential(( + &gpu_image.texture_view, + &gpu_image.sampler, + )), + ) }); existing_batch = batches.last_mut(); diff --git a/crates/bevy_utils/macros/src/lib.rs b/crates/bevy_utils/macros/src/lib.rs index 26fb9839919bd..4189b432ac605 100644 --- a/crates/bevy_utils/macros/src/lib.rs +++ b/crates/bevy_utils/macros/src/lib.rs @@ -136,3 +136,38 @@ pub fn all_tuples(input: TokenStream) -> TokenStream { )* }) } + +#[proc_macro] +pub fn all_tuples_with_size(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as AllTuples); + let len = 1 + input.end - input.start; + let mut ident_tuples = Vec::with_capacity(len); + for i in 0..=len { + let idents = input + .idents + .iter() + .map(|ident| format_ident!("{}{}", ident, i)); + if input.idents.len() < 2 { + ident_tuples.push(quote! { + #(#idents)* + }); + } else { + ident_tuples.push(quote! { + (#(#idents),*) + }); + } + } + + let macro_ident = &input.macro_ident; + let invocations = (input.start..=input.end).map(|i| { + let ident_tuples = &ident_tuples[..i]; + quote! { + #macro_ident!(#i, #(#ident_tuples),*); + } + }); + TokenStream::from(quote! { + #( + #invocations + )* + }) +} diff --git a/examples/shader/compute_shader_game_of_life.rs b/examples/shader/compute_shader_game_of_life.rs index 10c368771474b..2f8a269e592b8 100644 --- a/examples/shader/compute_shader_game_of_life.rs +++ b/examples/shader/compute_shader_game_of_life.rs @@ -107,14 +107,11 @@ fn prepare_bind_group( render_device: Res, ) { let view = gpu_images.get(&game_of_life_image.0).unwrap(); - let bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: None, - layout: &pipeline.texture_bind_group_layout, - entries: &[BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(&view.texture_view), - }], - }); + let bind_group = render_device.create_bind_group( + None, + &pipeline.texture_bind_group_layout, + &BindGroupEntries::single(&view.texture_view), + ); commands.insert_resource(GameOfLifeImageBindGroup(bind_group)); } diff --git a/examples/shader/post_processing.rs b/examples/shader/post_processing.rs index 94d3096e6a7c4..66d26cffbc271 100644 --- a/examples/shader/post_processing.rs +++ b/examples/shader/post_processing.rs @@ -20,12 +20,12 @@ use bevy::{ NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner, }, render_resource::{ - BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, - BindGroupLayoutEntry, BindingResource, BindingType, CachedRenderPipelineId, - ColorTargetState, ColorWrites, FragmentState, MultisampleState, Operations, - PipelineCache, PrimitiveState, RenderPassColorAttachment, RenderPassDescriptor, - RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, ShaderStages, - ShaderType, TextureFormat, TextureSampleType, TextureViewDimension, + BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, + BindingType, CachedRenderPipelineId, ColorTargetState, ColorWrites, FragmentState, + MultisampleState, Operations, PipelineCache, PrimitiveState, RenderPassColorAttachment, + RenderPassDescriptor, RenderPipelineDescriptor, Sampler, SamplerBindingType, + SamplerDescriptor, ShaderStages, ShaderType, TextureFormat, TextureSampleType, + TextureViewDimension, }, renderer::{RenderContext, RenderDevice}, texture::BevyDefault, @@ -176,30 +176,19 @@ impl ViewNode for PostProcessNode { // The reason it doesn't work is because each post_process_write will alternate the source/destination. // The only way to have the correct source/destination for the bind_group // is to make sure you get it during the node execution. - let bind_group = render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: Some("post_process_bind_group"), - layout: &post_process_pipeline.layout, - // It's important for this to match the BindGroupLayout defined in the PostProcessPipeline - entries: &[ - BindGroupEntry { - binding: 0, - // Make sure to use the source view - resource: BindingResource::TextureView(post_process.source), - }, - BindGroupEntry { - binding: 1, - // Use the sampler created for the pipeline - resource: BindingResource::Sampler(&post_process_pipeline.sampler), - }, - BindGroupEntry { - binding: 2, - // Set the settings binding - resource: settings_binding.clone(), - }, - ], - }); + let bind_group = render_context.render_device().create_bind_group( + "post_process_bind_group", + &post_process_pipeline.layout, + // It's important for this to match the BindGroupLayout defined in the PostProcessPipeline + &BindGroupEntries::sequential(( + // Make sure to use the source view + post_process.source, + // Use the sampler created for the pipeline + &post_process_pipeline.sampler, + // Set the settings binding + settings_binding.clone(), + )), + ); // Begin the render pass let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { diff --git a/examples/shader/texture_binding_array.rs b/examples/shader/texture_binding_array.rs index bcce8ccac7a8e..82bcf34acc6ab 100644 --- a/examples/shader/texture_binding_array.rs +++ b/examples/shader/texture_binding_array.rs @@ -5,11 +5,8 @@ use bevy::{ prelude::*, reflect::TypePath, render::{ - render_asset::RenderAssets, - render_resource::{AsBindGroupError, PreparedBindGroup, *}, - renderer::RenderDevice, - texture::FallbackImage, - RenderApp, + render_asset::RenderAssets, render_resource::*, renderer::RenderDevice, + texture::FallbackImage, RenderApp, }, }; use std::{num::NonZeroU32, process::exit}; @@ -119,20 +116,11 @@ impl AsBindGroup for BindlessMaterial { textures[id] = &*image.texture_view; } - let bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: "bindless_material_bind_group".into(), + let bind_group = render_device.create_bind_group( + "bindless_material_bind_group", layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureViewArray(&textures[..]), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::Sampler(&fallback_image.sampler), - }, - ], - }); + &BindGroupEntries::sequential((&textures[..], &fallback_image.sampler)), + ); Ok(PreparedBindGroup { bindings: vec![],