From 38779ed77c3cb021a1ec1ad3358b1453448c0516 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Tue, 13 May 2025 21:13:09 -0700 Subject: [PATCH 01/37] Wgpu 25 compile. --- crates/bevy_color/Cargo.toml | 2 +- crates/bevy_image/Cargo.toml | 2 +- crates/bevy_mesh/Cargo.toml | 2 +- crates/bevy_reflect/Cargo.toml | 2 +- crates/bevy_render/Cargo.toml | 8 +++---- crates/bevy_render/src/lib.rs | 4 ++++ .../bind_group_layout_entries.rs | 10 ++++++++- crates/bevy_render/src/render_resource/mod.rs | 2 +- .../src/render_resource/pipeline_cache.rs | 12 ++++++---- crates/bevy_render/src/renderer/mod.rs | 22 +++++++++++-------- .../bevy_render/src/renderer/render_device.rs | 17 ++++++++------ crates/bevy_render/src/settings.rs | 6 ++--- crates/bevy_winit/Cargo.toml | 2 +- 13 files changed, 56 insertions(+), 35 deletions(-) diff --git a/crates/bevy_color/Cargo.toml b/crates/bevy_color/Cargo.toml index ca7a7a74f5deb..98436ffc8f03b 100644 --- a/crates/bevy_color/Cargo.toml +++ b/crates/bevy_color/Cargo.toml @@ -20,7 +20,7 @@ serde = { version = "1.0", features = [ ], default-features = false, optional = true } thiserror = { version = "2", default-features = false } derive_more = { version = "1", default-features = false, features = ["from"] } -wgpu-types = { version = "24", default-features = false, optional = true } +wgpu-types = { version = "25", default-features = false, optional = true } encase = { version = "0.10", default-features = false, optional = true } [features] diff --git a/crates/bevy_image/Cargo.toml b/crates/bevy_image/Cargo.toml index 7f8128e3656bc..c3fa772563637 100644 --- a/crates/bevy_image/Cargo.toml +++ b/crates/bevy_image/Cargo.toml @@ -60,7 +60,7 @@ image = { version = "0.25.2", default-features = false } # misc bitflags = { version = "2.3", features = ["serde"] } bytemuck = { version = "1.5" } -wgpu-types = { version = "24", default-features = false } +wgpu-types = { version = "25", default-features = false } serde = { version = "1", features = ["derive"] } thiserror = { version = "2", default-features = false } futures-lite = "2.0.1" diff --git a/crates/bevy_mesh/Cargo.toml b/crates/bevy_mesh/Cargo.toml index a235fea5efc53..8894bd5c93b3a 100644 --- a/crates/bevy_mesh/Cargo.toml +++ b/crates/bevy_mesh/Cargo.toml @@ -27,7 +27,7 @@ bevy_platform = { path = "../bevy_platform", version = "0.16.0-dev", default-fea # other bitflags = { version = "2.3", features = ["serde"] } bytemuck = { version = "1.5" } -wgpu-types = { version = "24", default-features = false } +wgpu-types = { version = "25", default-features = false } serde = { version = "1", features = ["derive"] } hexasphere = "15.0" thiserror = { version = "2", default-features = false } diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index 8827fc695bc72..2b3bdae968273 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -109,7 +109,7 @@ uuid = { version = "1.13.1", default-features = false, optional = true, features "serde", ] } variadics_please = "1.1" -wgpu-types = { version = "24", features = [ +wgpu-types = { version = "25", features = [ "serde", ], optional = true, default-features = false } diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index d9775e9c8fea6..b2c05a7bf5a79 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -85,14 +85,14 @@ codespan-reporting = "0.11.0" # It is enabled for now to avoid having to do a significant overhaul of the renderer just for wasm. # When the 'atomics' feature is enabled `fragile-send-sync-non-atomic` does nothing # and Bevy instead wraps `wgpu` types to verify they are not used off their origin thread. -wgpu = { version = "24", default-features = false, features = [ +wgpu = { version = "25", default-features = false, features = [ "wgsl", "dx12", "metal", "naga-ir", "fragile-send-sync-non-atomic-wasm", ] } -naga = { version = "24", features = ["wgsl-in"] } +naga = { version = "25", features = ["wgsl-in"] } serde = { version = "1", features = ["derive"] } bytemuck = { version = "1.5", features = ["derive", "must_cast"] } downcast-rs = { version = "2", default-features = false, features = ["std"] } @@ -119,7 +119,7 @@ wesl = { version = "0.1.2", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # Omit the `glsl` feature in non-WebAssembly by default. -naga_oil = { version = "0.17.1", default-features = false, features = [ +naga_oil = { path = "../../../naga_oil", default-features = false, features = [ "test_shader", ] } @@ -127,7 +127,7 @@ naga_oil = { version = "0.17.1", default-features = false, features = [ proptest = "1" [target.'cfg(target_arch = "wasm32")'.dependencies] -naga_oil = "0.17.1" +naga_oil = { path = "../../../naga_oil" } js-sys = "0.3" web-sys = { version = "0.3.67", features = [ 'Blob', diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index a20315c0997bb..c7b134394bef5 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -352,10 +352,14 @@ impl Plugin for RenderPlugin { backend_options: wgpu::BackendOptions { gl: wgpu::GlBackendOptions { gles_minor_version: settings.gles3_minor_version, + fence_behavior: wgpu::GlFenceBehavior::Normal, }, dx12: wgpu::Dx12BackendOptions { shader_compiler: settings.dx12_shader_compiler.clone(), }, + noop: wgpu::NoopBackendOptions { + enable: false, + }, }, }); diff --git a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs index 41affa434959a..575c6a23fdab5 100644 --- a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs +++ b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs @@ -570,6 +570,14 @@ pub mod binding_types { } pub fn acceleration_structure() -> BindGroupLayoutEntryBuilder { - BindingType::AccelerationStructure.into_bind_group_layout_entry_builder() + BindingType::AccelerationStructure { + vertex_return: false, + }.into_bind_group_layout_entry_builder() + } + + pub fn acceleration_structure_vertex_return() -> BindGroupLayoutEntryBuilder { + BindingType::AccelerationStructure { + vertex_return: true, + }.into_bind_group_layout_entry_builder() } } diff --git a/crates/bevy_render/src/render_resource/mod.rs b/crates/bevy_render/src/render_resource/mod.rs index aecf27173d9bb..b40e6273294a1 100644 --- a/crates/bevy_render/src/render_resource/mod.rs +++ b/crates/bevy_render/src/render_resource/mod.rs @@ -49,7 +49,7 @@ pub use wgpu::{ ComputePassDescriptor, ComputePipelineDescriptor as RawComputePipelineDescriptor, CreateBlasDescriptor, CreateTlasDescriptor, DepthBiasState, DepthStencilState, DownlevelFlags, Extent3d, Face, Features as WgpuFeatures, FilterMode, FragmentState as RawFragmentState, - FrontFace, ImageSubresourceRange, IndexFormat, Limits as WgpuLimits, LoadOp, Maintain, MapMode, + FrontFace, ImageSubresourceRange, IndexFormat, Limits as WgpuLimits, LoadOp, MapMode, MultisampleState, Operations, Origin3d, PipelineCompilationOptions, PipelineLayout, PipelineLayoutDescriptor, PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange, RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 416a83cd65c09..e3e990f5d8f2d 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -873,7 +873,7 @@ impl PipelineCache { // TODO: Expose the rest of this somehow let compilation_options = PipelineCompilationOptions { - constants: &default(), + constants: &[], zero_initialize_workgroup_memory: descriptor.zero_initialize_workgroup_memory, }; @@ -955,7 +955,7 @@ impl PipelineCache { entry_point: Some(&descriptor.entry_point), // TODO: Expose the rest of this somehow compilation_options: PipelineCompilationOptions { - constants: &default(), + constants: &[], zero_initialize_workgroup_memory: descriptor .zero_initialize_workgroup_memory, }, @@ -1159,8 +1159,12 @@ fn get_capabilities(features: Features, downlevel: DownlevelFlags) -> Capabiliti features.contains(Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING), ); capabilities.set( - Capabilities::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, - features.contains(Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING), + Capabilities::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + features.contains(Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING), + ); + capabilities.set( + Capabilities::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING, + features.contains(Features::UNIFORM_BUFFER_BINDING_ARRAYS) ); // TODO: This needs a proper wgpu feature capabilities.set( diff --git a/crates/bevy_render/src/renderer/mod.rs b/crates/bevy_render/src/renderer/mod.rs index f2cfbcd9d0dac..fd6fe80aa2f67 100644 --- a/crates/bevy_render/src/renderer/mod.rs +++ b/crates/bevy_render/src/renderer/mod.rs @@ -21,10 +21,7 @@ use alloc::sync::Arc; use bevy_ecs::{prelude::*, system::SystemState}; use bevy_platform::time::Instant; use bevy_time::TimeSender; -use wgpu::{ - Adapter, AdapterInfo, CommandBuffer, CommandEncoder, DeviceType, Instance, Queue, - RequestAdapterOptions, -}; +use wgpu::{Adapter, AdapterInfo, CommandBuffer, CommandEncoder, DeviceType, Instance, Queue, RequestAdapterOptions, Trace}; /// Updates the [`RenderGraph`] with all of its nodes and then runs it to render the entire frame. pub fn render_system(world: &mut World, state: &mut SystemState>>) { @@ -177,21 +174,21 @@ pub async fn initialize_renderer( // discrete GPUs due to having to transfer data across the PCI-E bus and so it // should not be automatically enabled in this case. It is however beneficial for // integrated GPUs. - features -= wgpu::Features::MAPPABLE_PRIMARY_BUFFERS; + features.remove(wgpu::Features::MAPPABLE_PRIMARY_BUFFERS); } // RAY_QUERY and RAY_TRACING_ACCELERATION STRUCTURE will sometimes cause DeviceLost failures on platforms // that report them as supported: // - features -= wgpu::Features::EXPERIMENTAL_RAY_QUERY; - features -= wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE; + features.remove(wgpu::Features::EXPERIMENTAL_RAY_QUERY); + features.remove(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE); limits = adapter.limits(); } // Enforce the disabled features if let Some(disabled_features) = options.disabled_features { - features -= disabled_features; + features.remove(disabled_features); } // NOTE: |= is used here to ensure that any explicitly-enabled features are respected. features |= options.features; @@ -240,6 +237,12 @@ pub async fn initialize_renderer( max_uniform_buffers_per_shader_stage: limits .max_uniform_buffers_per_shader_stage .min(constrained_limits.max_uniform_buffers_per_shader_stage), + max_binding_array_elements_per_shader_stage: limits + .max_binding_array_elements_per_shader_stage + .min(constrained_limits.max_binding_array_elements_per_shader_stage), + max_binding_array_sampler_elements_per_shader_stage: limits + .max_binding_array_sampler_elements_per_shader_stage + .min(constrained_limits.max_binding_array_sampler_elements_per_shader_stage), max_uniform_buffer_binding_size: limits .max_uniform_buffer_binding_size .min(constrained_limits.max_uniform_buffer_binding_size), @@ -316,8 +319,9 @@ pub async fn initialize_renderer( required_features: features, required_limits: limits, memory_hints: options.memory_hints.clone(), + // See https://github.com/gfx-rs/wgpu/issues/5974 + trace: Trace::Off, }, - options.trace_path.as_deref(), ) .await .unwrap(); diff --git a/crates/bevy_render/src/renderer/render_device.rs b/crates/bevy_render/src/renderer/render_device.rs index 31f47e57404c1..b1a20d2acedce 100644 --- a/crates/bevy_render/src/renderer/render_device.rs +++ b/crates/bevy_render/src/renderer/render_device.rs @@ -7,7 +7,7 @@ use bevy_ecs::resource::Resource; use bevy_utils::WgpuWrapper; use wgpu::{ util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, - BindGroupLayoutEntry, BufferAsyncError, BufferBindingType, MaintainResult, + BindGroupLayoutEntry, BufferAsyncError, BufferBindingType, PollError, PollStatus, }; /// This GPU device is responsible for the creation of most rendering and compute resources. @@ -67,11 +67,14 @@ impl RenderDevice { // This call passes binary data to the backend as-is and can potentially result in a driver crash or bogus behavior. // No attempt is made to ensure that data is valid SPIR-V. unsafe { - self.device - .create_shader_module_spirv(&wgpu::ShaderModuleDescriptorSpirV { - label: desc.label, - source: source.clone(), - }) + self.device.create_shader_module_passthrough( + wgpu::ShaderModuleDescriptorPassthrough::SpirV( + wgpu::ShaderModuleDescriptorSpirV { + label: desc.label, + source: source.clone(), + }, + ), + ) } } // SAFETY: @@ -118,7 +121,7 @@ impl RenderDevice { /// /// no-op on the web, device is automatically polled. #[inline] - pub fn poll(&self, maintain: wgpu::Maintain) -> MaintainResult { + pub fn poll(&self, maintain: wgpu::PollType) -> Result { self.device.poll(maintain) } diff --git a/crates/bevy_render/src/settings.rs b/crates/bevy_render/src/settings.rs index ab50fc81b1a49..427b080a3410c 100644 --- a/crates/bevy_render/src/settings.rs +++ b/crates/bevy_render/src/settings.rs @@ -2,12 +2,12 @@ use crate::renderer::{ RenderAdapter, RenderAdapterInfo, RenderDevice, RenderInstance, RenderQueue, }; use alloc::borrow::Cow; -use std::path::PathBuf; pub use wgpu::{ Backends, Dx12Compiler, Features as WgpuFeatures, Gles3MinorVersion, InstanceFlags, Limits as WgpuLimits, MemoryHints, PowerPreference, }; +use wgpu::DxcShaderModel; /// Configures the priority used when automatically configuring the features/limits of `wgpu`. #[derive(Clone)] @@ -53,8 +53,6 @@ pub struct WgpuSettings { pub instance_flags: InstanceFlags, /// This hints to the WGPU device about the preferred memory allocation strategy. pub memory_hints: MemoryHints, - /// The path to pass to wgpu for API call tracing. This only has an effect if wgpu's tracing functionality is enabled. - pub trace_path: Option, } impl Default for WgpuSettings { @@ -114,6 +112,7 @@ impl Default for WgpuSettings { Dx12Compiler::DynamicDxc { dxc_path: String::from(dxc), dxil_path: String::from(dxil), + max_shader_model: DxcShaderModel::V6_7, } } else { Dx12Compiler::Fxc @@ -137,7 +136,6 @@ impl Default for WgpuSettings { gles3_minor_version, instance_flags, memory_hints: MemoryHints::default(), - trace_path: None, } } } diff --git a/crates/bevy_winit/Cargo.toml b/crates/bevy_winit/Cargo.toml index 43db87a1d2372..7bdb486d3d1a5 100644 --- a/crates/bevy_winit/Cargo.toml +++ b/crates/bevy_winit/Cargo.toml @@ -59,7 +59,7 @@ cfg-if = "1.0" raw-window-handle = "0.6" serde = { version = "1.0", features = ["derive"], optional = true } bytemuck = { version = "1.5", optional = true } -wgpu-types = { version = "24", optional = true } +wgpu-types = { version = "25", optional = true } accesskit = "0.19" tracing = { version = "0.1", default-features = false, features = ["std"] } From f5969d78befbcb97d1ee87b88b405daba6f696f6 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Mon, 9 Jun 2025 13:50:12 -0700 Subject: [PATCH 02/37] Split view 0 into 0,1 --- crates/bevy_gizmos/src/line_joints.wgsl | 2 +- crates/bevy_gizmos/src/lines.wgsl | 2 +- crates/bevy_gizmos/src/pipeline_3d.rs | 18 +- crates/bevy_pbr/src/deferred/mod.rs | 8 +- crates/bevy_pbr/src/lib.rs | 4 +- crates/bevy_pbr/src/material.rs | 14 +- crates/bevy_pbr/src/prepass/mod.rs | 60 +++- crates/bevy_pbr/src/render/mesh.rs | 9 +- crates/bevy_pbr/src/render/mesh_bindings.wgsl | 4 +- .../bevy_pbr/src/render/mesh_view_bindings.rs | 294 ++++++++++-------- .../src/render/mesh_view_bindings.wgsl | 82 ++--- crates/bevy_pbr/src/render/pbr_bindings.wgsl | 66 ++-- crates/bevy_pbr/src/ssr/mod.rs | 8 +- crates/bevy_pbr/src/volumetric_fog/render.rs | 8 +- crates/bevy_pbr/src/wireframe.rs | 4 +- crates/bevy_render/src/render_phase/draw.rs | 8 +- .../src/render_resource/bind_group.rs | 20 +- .../src/render_resource/bind_group_entries.rs | 6 + .../bind_group_layout_entries.rs | 9 + examples/shader/custom_render_phase.rs | 4 +- examples/shader/custom_shader_instancing.rs | 4 +- examples/shader/specialized_mesh_pipeline.rs | 19 +- examples/shader/texture_binding_array.rs | 4 +- 23 files changed, 370 insertions(+), 287 deletions(-) diff --git a/crates/bevy_gizmos/src/line_joints.wgsl b/crates/bevy_gizmos/src/line_joints.wgsl index cbbf152c02c59..3936578ee8379 100644 --- a/crates/bevy_gizmos/src/line_joints.wgsl +++ b/crates/bevy_gizmos/src/line_joints.wgsl @@ -14,7 +14,7 @@ struct LineGizmoUniform { #endif } -@group(1) @binding(0) var joints_gizmo: LineGizmoUniform; +@group(2) @binding(0) var joints_gizmo: LineGizmoUniform; struct VertexInput { @location(0) position_a: vec3, diff --git a/crates/bevy_gizmos/src/lines.wgsl b/crates/bevy_gizmos/src/lines.wgsl index 1181e3f59cdb8..d06ccfa20d3c1 100644 --- a/crates/bevy_gizmos/src/lines.wgsl +++ b/crates/bevy_gizmos/src/lines.wgsl @@ -17,7 +17,7 @@ struct LineGizmoUniform { #endif } -@group(1) @binding(0) var line_gizmo: LineGizmoUniform; +@group(2) @binding(0) var line_gizmo: LineGizmoUniform; struct VertexInput { @location(0) position_a: vec3, diff --git a/crates/bevy_gizmos/src/pipeline_3d.rs b/crates/bevy_gizmos/src/pipeline_3d.rs index 1cc70c67cb313..0b99248fd5a35 100644 --- a/crates/bevy_gizmos/src/pipeline_3d.rs +++ b/crates/bevy_gizmos/src/pipeline_3d.rs @@ -124,7 +124,8 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { .get_view_layout(key.view_key.into()) .clone(); - let layout = vec![view_layout, self.uniform_layout.clone()]; + let mut layout = view_layout.to_vec(); + layout.push(self.uniform_layout.clone()); let fragment_entry_point = match key.line_style { GizmoLineStyle::Solid => "fragment_solid", @@ -221,7 +222,8 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { .get_view_layout(key.view_key.into()) .clone(); - let layout = vec![view_layout, self.uniform_layout.clone()]; + let mut layout = view_layout.to_vec(); + layout.push(self.uniform_layout.clone()); if key.joints == GizmoLineJoint::None { error!("There is no entry point for line joints with GizmoLineJoints::None. Please consider aborting the drawing process before reaching this stage."); @@ -273,20 +275,20 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { type DrawLineGizmo3d = ( SetItemPipeline, - SetMeshViewBindGroup<0>, - SetLineGizmoBindGroup<1>, + SetMeshViewBindGroup<0, 1>, + SetLineGizmoBindGroup<2>, DrawLineGizmo, ); type DrawLineGizmo3dStrip = ( SetItemPipeline, - SetMeshViewBindGroup<0>, - SetLineGizmoBindGroup<1>, + SetMeshViewBindGroup<0, 1>, + SetLineGizmoBindGroup<2>, DrawLineGizmo, ); type DrawLineJointGizmo3d = ( SetItemPipeline, - SetMeshViewBindGroup<0>, - SetLineGizmoBindGroup<1>, + SetMeshViewBindGroup<0, 1>, + SetLineGizmoBindGroup<2>, DrawLineJointGizmo, ); diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index 65be474e65470..0451f35516657 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -346,12 +346,12 @@ impl SpecializedRenderPipeline for DeferredLightingLayout { #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into()); + let mut layout = self.mesh_pipeline.get_view_layout(key.into()).to_vec(); + layout.push(self.bind_group_layout_1.clone()); + RenderPipelineDescriptor { label: Some("deferred_lighting_pipeline".into()), - layout: vec![ - self.mesh_pipeline.get_view_layout(key.into()).clone(), - self.bind_group_layout_1.clone(), - ], + layout, vertex: VertexState { shader: self.deferred_lighting_shader.clone(), shader_defs: shader_defs.clone(), diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 945bc9c55bcd7..517ef0eb5cbe2 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -152,8 +152,8 @@ fn shader_ref(path: PathBuf) -> ShaderRef { const MESHLET_VISIBILITY_BUFFER_RESOLVE_SHADER_HANDLE: Handle = weak_handle!("69187376-3dea-4d0f-b3f5-185bde63d6a2"); -pub const TONEMAPPING_LUT_TEXTURE_BINDING_INDEX: u32 = 26; -pub const TONEMAPPING_LUT_SAMPLER_BINDING_INDEX: u32 = 27; +pub const TONEMAPPING_LUT_TEXTURE_BINDING_INDEX: u32 = 18; +pub const TONEMAPPING_LUT_SAMPLER_BINDING_INDEX: u32 = 19; /// Sets up the entire PBR infrastructure of bevy. pub struct PbrPlugin { diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index af11db1ba6d93..2b25b1b9be660 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -120,9 +120,9 @@ use tracing::error; /// In WGSL shaders, the material's binding would look like this: /// /// ```wgsl -/// @group(2) @binding(0) var color: vec4; -/// @group(2) @binding(1) var color_texture: texture_2d; -/// @group(2) @binding(2) var color_sampler: sampler; +/// @group(3) @binding(0) var color: vec4; +/// @group(3) @binding(1) var color_texture: texture_2d; +/// @group(3) @binding(2) var color_sampler: sampler; /// ``` pub trait Material: Asset + AsBindGroup + Clone + Sized { /// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader @@ -501,7 +501,7 @@ where descriptor.fragment.as_mut().unwrap().shader = fragment_shader.clone(); } - descriptor.layout.insert(2, self.material_layout.clone()); + descriptor.layout.insert(3, self.material_layout.clone()); M::specialize(self, &mut descriptor, layout, key)?; @@ -543,9 +543,9 @@ impl FromWorld for MaterialPipeline { type DrawMaterial = ( SetItemPipeline, - SetMeshViewBindGroup<0>, - SetMeshBindGroup<1>, - SetMaterialBindGroup, + SetMeshViewBindGroup<0, 1>, + SetMeshBindGroup<2>, + SetMaterialBindGroup, DrawMesh, ); diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 35182910a9cc8..e7523e45e3262 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -95,7 +95,6 @@ where Render, prepare_prepass_view_bind_group::.in_set(RenderSystems::PrepareBindGroups), ) - .init_resource::() .init_resource::>>() .allow_ambiguous_resource::>>(); } @@ -105,7 +104,9 @@ where return; }; - render_app.init_resource::>(); + render_app + .init_resource::>() + .init_resource::(); } } @@ -267,6 +268,7 @@ pub struct PrepassPipelineInternal { pub view_layout_motion_vectors: BindGroupLayout, pub view_layout_no_motion_vectors: BindGroupLayout, pub mesh_layouts: MeshLayouts, + pub empty_layout: BindGroupLayout, pub material_layout: BindGroupLayout, pub prepass_material_vertex_shader: Option>, pub prepass_material_fragment_shader: Option>, @@ -376,6 +378,7 @@ impl FromWorld for PrepassPipeline { skins_use_uniform_buffers: skin::skins_use_uniform_buffers(render_device), depth_clip_control_supported, binding_arrays_are_usable: binding_arrays_are_usable(render_device, render_adapter), + empty_layout: render_device.create_bind_group_layout("prepass_empty_layout", &[]), }; PrepassPipeline { internal, @@ -420,13 +423,14 @@ impl PrepassPipelineInternal { layout: &MeshVertexBufferLayoutRef, ) -> Result { let mut shader_defs = shader_defs; - let mut bind_group_layouts = vec![if mesh_key - .contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) - { - self.view_layout_motion_vectors.clone() - } else { - self.view_layout_no_motion_vectors.clone() - }]; + let mut bind_group_layouts = vec![ + if mesh_key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) { + self.view_layout_motion_vectors.clone() + } else { + self.view_layout_no_motion_vectors.clone() + }, + self.empty_layout.clone(), + ]; let mut vertex_attributes = Vec::new(); // Let the shader code know that it's running in a prepass pipeline. @@ -551,7 +555,7 @@ impl PrepassPipelineInternal { &mut vertex_attributes, self.skins_use_uniform_buffers, ); - bind_group_layouts.insert(1, bind_group); + bind_group_layouts.insert(2, bind_group); let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?; // Setup prepass fragment targets - normals in slot 0 (or None if not needed), motion vectors in slot 1 let mut targets = prepass_target_descriptors( @@ -713,10 +717,29 @@ pub fn prepare_previous_view_uniforms( } } -#[derive(Default, Resource)] +#[derive(Resource)] pub struct PrepassViewBindGroup { pub motion_vectors: Option, pub no_motion_vectors: Option, + pub empty_bind_group: BindGroup, +} + +impl FromWorld for PrepassViewBindGroup { + fn from_world(world: &mut World) -> Self { + let pipeline = world.resource::>(); + + let render_device = world.resource::(); + let empty_bind_group = render_device.create_bind_group( + "prepass_view_empty_bind_group", + &pipeline.internal.empty_layout, + &[], + ); + PrepassViewBindGroup { + motion_vectors: None, + no_motion_vectors: None, + empty_bind_group, + } + } } pub fn prepare_prepass_view_bind_group( @@ -1231,8 +1254,8 @@ pub fn queue_prepass_material_meshes( } } -pub struct SetPrepassViewBindGroup; -impl RenderCommand

for SetPrepassViewBindGroup { +pub struct SetPrepassViewBindGroup; +impl RenderCommand

for SetPrepassViewBindGroup { type Param = SRes; type ViewQuery = ( Read, @@ -1274,6 +1297,11 @@ impl RenderCommand

for SetPrepassViewBindGroup< ); } } + pass.set_bind_group( + J, + &prepass_view_bind_group.empty_bind_group, + &[], + ); RenderCommandResult::Success } @@ -1281,8 +1309,8 @@ impl RenderCommand

for SetPrepassViewBindGroup< pub type DrawPrepass = ( SetItemPipeline, - SetPrepassViewBindGroup<0>, - SetMeshBindGroup<1>, - SetMaterialBindGroup, + SetPrepassViewBindGroup<0, 1>, + SetMeshBindGroup<2>, + SetMaterialBindGroup, DrawMesh, ); diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 8c408233e1842..41374b113d5f6 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1864,7 +1864,7 @@ impl MeshPipeline { } } - pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &BindGroupLayout { + pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &[BindGroupLayout; 2] { self.view_layouts.get_view_layout(layout_key) } } @@ -2320,7 +2320,7 @@ impl SpecializedMeshPipeline for MeshPipeline { shader_defs.push("PBR_SPECULAR_TEXTURES_SUPPORTED".into()); } - let mut bind_group_layout = vec![self.get_view_layout(key.into()).clone()]; + let mut bind_group_layout = self.get_view_layout(key.into()).to_vec(); if key.msaa_samples() > 1 { shader_defs.push("MULTISAMPLED".into()); @@ -2847,8 +2847,8 @@ fn prepare_mesh_bind_groups_for_phase( groups } -pub struct SetMeshViewBindGroup; -impl RenderCommand

for SetMeshViewBindGroup { +pub struct SetMeshViewBindGroup; +impl RenderCommand

for SetMeshViewBindGroup { type Param = (); type ViewQuery = ( Read, @@ -2891,6 +2891,7 @@ impl RenderCommand

for SetMeshViewBindGroup offsets.push(layers_count_offset.offset); } pass.set_bind_group(I, &mesh_view_bind_group.value, &offsets); + pass.set_bind_group(J, &mesh_view_bind_group.value_binding_array, &[]); RenderCommandResult::Success } diff --git a/crates/bevy_pbr/src/render/mesh_bindings.wgsl b/crates/bevy_pbr/src/render/mesh_bindings.wgsl index 62b967c56f1b9..6e78dc4337a8b 100644 --- a/crates/bevy_pbr/src/render/mesh_bindings.wgsl +++ b/crates/bevy_pbr/src/render/mesh_bindings.wgsl @@ -4,8 +4,8 @@ #ifndef MESHLET_MESH_MATERIAL_PASS #ifdef PER_OBJECT_BUFFER_BATCH_SIZE -@group(1) @binding(0) var mesh: array; +@group(2) @binding(0) var mesh: array; #else -@group(1) @binding(0) var mesh: array; +@group(2) @binding(0) var mesh: array; #endif // PER_OBJECT_BUFFER_BATCH_SIZE #endif // MESHLET_MESH_MATERIAL_PASS diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.rs b/crates/bevy_pbr/src/render/mesh_view_bindings.rs index 8e231886bae1e..dcb6751d36bb7 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.rs @@ -59,7 +59,7 @@ use {crate::MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES, bevy_utils::once, traci #[derive(Clone)] pub struct MeshPipelineViewLayout { - pub bind_group_layout: BindGroupLayout, + pub bind_group_layout: [BindGroupLayout; 2], #[cfg(debug_assertions)] pub texture_count: usize, @@ -201,7 +201,11 @@ fn layout_entries( layout_key: MeshPipelineViewLayoutKey, render_device: &RenderDevice, render_adapter: &RenderAdapter, -) -> Vec { +) -> [Vec; 2] { + // EnvironmentMapLight + let environment_map_entries = + environment_map::get_bind_group_layout_entries(render_device, render_adapter); + let mut entries = DynamicBindGroupLayoutEntries::new_with_indices( ShaderStages::FRAGMENT, ( @@ -313,45 +317,15 @@ fn layout_entries( 16, texture_2d(TextureSampleType::Float { filterable: false }), ), + (17, environment_map_entries[3]), ), ); - // EnvironmentMapLight - let environment_map_entries = - environment_map::get_bind_group_layout_entries(render_device, render_adapter); - entries = entries.extend_with_indices(( - (17, environment_map_entries[0]), - (18, environment_map_entries[1]), - (19, environment_map_entries[2]), - (20, environment_map_entries[3]), - )); - - // Irradiance volumes - if IRRADIANCE_VOLUMES_ARE_USABLE { - let irradiance_volume_entries = - irradiance_volume::get_bind_group_layout_entries(render_device, render_adapter); - entries = entries.extend_with_indices(( - (21, irradiance_volume_entries[0]), - (22, irradiance_volume_entries[1]), - )); - } - - // Clustered decals - if let Some(clustered_decal_entries) = - decal::clustered::get_bind_group_layout_entries(render_device, render_adapter) - { - entries = entries.extend_with_indices(( - (23, clustered_decal_entries[0]), - (24, clustered_decal_entries[1]), - (25, clustered_decal_entries[2]), - )); - } - // Tonemapping let tonemapping_lut_entries = get_lut_bind_group_layout_entries(); entries = entries.extend_with_indices(( - (26, tonemapping_lut_entries[0]), - (27, tonemapping_lut_entries[1]), + (18, tonemapping_lut_entries[0]), + (19, tonemapping_lut_entries[1]), )); // Prepass @@ -361,7 +335,7 @@ fn layout_entries( { for (entry, binding) in prepass::get_bind_group_layout_entries(layout_key) .iter() - .zip([28, 29, 30, 31]) + .zip([20, 21, 22, 23]) { if let Some(entry) = entry { entries = entries.extend_with_indices(((binding as u32, *entry),)); @@ -372,33 +346,61 @@ fn layout_entries( // View Transmission Texture entries = entries.extend_with_indices(( ( - 32, + 24, texture_2d(TextureSampleType::Float { filterable: true }), ), - (33, sampler(SamplerBindingType::Filtering)), + (25, sampler(SamplerBindingType::Filtering)), )); - // OIT - if layout_key.contains(MeshPipelineViewLayoutKey::OIT_ENABLED) { - // Check if we can use OIT. This is a hack to avoid errors on webgl -- - // the OIT plugin will warn the user that OIT is not supported on their - // platform, so we don't need to do it here. - if is_oit_supported(render_adapter, render_device, false) { - entries = entries.extend_with_indices(( - // oit_layers - (34, storage_buffer_sized(false, None)), - // oit_layer_ids, - (35, storage_buffer_sized(false, None)), - // oit_layer_count - ( - 36, - uniform_buffer::(true), - ), - )); - } + // // OIT + // if layout_key.contains(MeshPipelineViewLayoutKey::OIT_ENABLED) { + // // Check if we can use OIT. This is a hack to avoid errors on webgl -- + // // the OIT plugin will warn the user that OIT is not supported on their + // // platform, so we don't need to do it here. + // if is_oit_supported(render_adapter, render_device, false) { + // entries = entries.extend_with_indices(( + // // oit_layers + // (26, storage_buffer_sized(false, None)), + // // oit_layer_ids, + // (27, storage_buffer_sized(false, None)), + // // oit_layer_count + // ( + // 28, + // uniform_buffer::(true), + // ), + // )); + // } + // } + + let mut binding_array_entries = DynamicBindGroupLayoutEntries::new(ShaderStages::FRAGMENT); + binding_array_entries = binding_array_entries.extend_with_indices(( + (0, environment_map_entries[0]), + (1, environment_map_entries[1]), + (2, environment_map_entries[2]), + )); + + // Irradiance volumes + if IRRADIANCE_VOLUMES_ARE_USABLE { + let irradiance_volume_entries = + irradiance_volume::get_bind_group_layout_entries(render_device, render_adapter); + binding_array_entries = binding_array_entries.extend_with_indices(( + (3, irradiance_volume_entries[0]), + (4, irradiance_volume_entries[1]), + )); } - entries.to_vec() + // Clustered decals + if let Some(clustered_decal_entries) = + decal::clustered::get_bind_group_layout_entries(render_device, render_adapter) + { + binding_array_entries = binding_array_entries.extend_with_indices(( + (5, clustered_decal_entries[0]), + (6, clustered_decal_entries[1]), + (7, clustered_decal_entries[2]), + )); + } + + [entries.to_vec(), binding_array_entries.to_vec()] } /// Stores the view layouts for every combination of pipeline keys. @@ -435,12 +437,20 @@ impl FromWorld for MeshPipelineViewLayouts { #[cfg(debug_assertions)] let texture_count: usize = entries .iter() - .filter(|entry| matches!(entry.ty, BindingType::Texture { .. })) + .flat_map(|e| { + e.iter() + .filter(|entry| matches!(entry.ty, BindingType::Texture { .. })) + }) .count(); MeshPipelineViewLayout { - bind_group_layout: render_device - .create_bind_group_layout(key.label().as_str(), &entries), + bind_group_layout: [ + render_device.create_bind_group_layout(key.label().as_str(), &entries[0]), + render_device.create_bind_group_layout( + format!("{}_binding_array", key.label()).as_str(), + &entries[1], + ), + ], #[cfg(debug_assertions)] texture_count, } @@ -449,7 +459,7 @@ impl FromWorld for MeshPipelineViewLayouts { } impl MeshPipelineViewLayouts { - pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &BindGroupLayout { + pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &[BindGroupLayout; 2] { let index = layout_key.bits() as usize; let layout = &self[index]; @@ -484,12 +494,20 @@ pub fn generate_view_layouts( #[cfg(debug_assertions)] let texture_count: usize = entries .iter() - .filter(|entry| matches!(entry.ty, BindingType::Texture { .. })) + .flat_map(|e| { + e.into_iter() + .filter(|entry| matches!(entry.ty, BindingType::Texture { .. })) + }) .count(); MeshPipelineViewLayout { - bind_group_layout: render_device - .create_bind_group_layout(key.label().as_str(), &entries), + bind_group_layout: [ + render_device.create_bind_group_layout(key.label().as_str(), &entries[0]), + render_device.create_bind_group_layout( + format!("{}_binding_array", key.label()).as_str(), + &entries[1], + ), + ], #[cfg(debug_assertions)] texture_count, } @@ -499,6 +517,7 @@ pub fn generate_view_layouts( #[derive(Component)] pub struct MeshViewBindGroup { pub value: BindGroup, + pub value_binding_array: BindGroup, } pub fn prepare_mesh_view_bind_groups( @@ -585,7 +604,7 @@ pub fn prepare_mesh_view_bind_groups( layout_key |= MeshPipelineViewLayoutKey::OIT_ENABLED; } - let layout = &mesh_pipeline.get_view_layout(layout_key); + let layout = mesh_pipeline.get_view_layout(layout_key); let mut entries = DynamicBindGroupEntries::new_with_indices(( (0, view_binding.clone()), @@ -614,6 +633,58 @@ pub fn prepare_mesh_view_bind_groups( (16, ssao_view), )); + entries = entries.extend_with_indices(((17, environment_map_binding.clone()),)); + + let lut_bindings = + get_lut_bindings(&images, &tonemapping_luts, tonemapping, &fallback_image); + entries = entries.extend_with_indices(((18, lut_bindings.0), (19, 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"))) || msaa.samples() == 1 + { + prepass_bindings = prepass::get_bindings(prepass_textures); + for (binding, index) in prepass_bindings + .iter() + .map(Option::as_ref) + .zip([20, 21, 22, 23]) + .flat_map(|(b, i)| b.map(|b| (b, i))) + { + entries = entries.extend_with_indices(((index, binding),)); + } + }; + + let transmission_view = transmission_texture + .map(|transmission| &transmission.view) + .unwrap_or(&fallback_image_zero.texture_view); + + let transmission_sampler = transmission_texture + .map(|transmission| &transmission.sampler) + .unwrap_or(&fallback_image_zero.sampler); + + entries = + entries.extend_with_indices(((24, transmission_view), (25, transmission_sampler))); + + // if has_oit { + // if let ( + // Some(oit_layers_binding), + // Some(oit_layer_ids_binding), + // Some(oit_settings_binding), + // ) = ( + // oit_buffers.layers.binding(), + // oit_buffers.layer_ids.binding(), + // oit_buffers.settings.binding(), + // ) { + // entries = entries.extend_with_indices(( + // (26, oit_layers_binding.clone()), + // (27, oit_layer_ids_binding.clone()), + // (28, oit_settings_binding.clone()), + // )); + // } + // } + + let mut entries_binding_array = DynamicBindGroupEntries::new(); + let environment_map_bind_group_entries = RenderViewEnvironmentMapBindGroupEntries::get( render_view_environment_maps, &images, @@ -621,18 +692,16 @@ pub fn prepare_mesh_view_bind_groups( &render_device, &render_adapter, ); - match environment_map_bind_group_entries { RenderViewEnvironmentMapBindGroupEntries::Single { diffuse_texture_view, specular_texture_view, sampler, } => { - entries = entries.extend_with_indices(( - (17, diffuse_texture_view), - (18, specular_texture_view), - (19, sampler), - (20, environment_map_binding.clone()), + entries_binding_array = entries_binding_array.extend_with_indices(( + (0, diffuse_texture_view), + (1, specular_texture_view), + (2, sampler), )); } RenderViewEnvironmentMapBindGroupEntries::Multiple { @@ -640,11 +709,10 @@ pub fn prepare_mesh_view_bind_groups( ref specular_texture_views, sampler, } => { - entries = entries.extend_with_indices(( - (17, diffuse_texture_views.as_slice()), - (18, specular_texture_views.as_slice()), - (19, sampler), - (20, environment_map_binding.clone()), + entries_binding_array = entries_binding_array.extend_with_indices(( + (0, diffuse_texture_views.as_slice()), + (1, specular_texture_views.as_slice()), + (2, sampler), )); } } @@ -666,14 +734,15 @@ pub fn prepare_mesh_view_bind_groups( texture_view, sampler, }) => { - entries = entries.extend_with_indices(((21, texture_view), (22, sampler))); + entries_binding_array = entries_binding_array + .extend_with_indices(((3, texture_view), (4, sampler))); } Some(RenderViewIrradianceVolumeBindGroupEntries::Multiple { ref texture_views, sampler, }) => { - entries = entries - .extend_with_indices(((21, texture_views.as_slice()), (22, sampler))); + entries_binding_array = entries_binding_array + .extend_with_indices(((3, texture_views.as_slice()), (4, sampler))); } None => {} } @@ -689,76 +758,37 @@ pub fn prepare_mesh_view_bind_groups( // Add the decal bind group entries. if let Some(ref render_view_decal_bind_group_entries) = decal_bind_group_entries { - entries = entries.extend_with_indices(( + entries_binding_array = entries_binding_array.extend_with_indices(( // `clustered_decals` ( - 23, + 5, render_view_decal_bind_group_entries .decals .as_entire_binding(), ), // `clustered_decal_textures` ( - 24, + 6, render_view_decal_bind_group_entries .texture_views .as_slice(), ), // `clustered_decal_sampler` - (25, render_view_decal_bind_group_entries.sampler), + (7, render_view_decal_bind_group_entries.sampler), )); } - let lut_bindings = - get_lut_bindings(&images, &tonemapping_luts, tonemapping, &fallback_image); - entries = entries.extend_with_indices(((26, lut_bindings.0), (27, 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"))) || msaa.samples() == 1 - { - prepass_bindings = prepass::get_bindings(prepass_textures); - for (binding, index) in prepass_bindings - .iter() - .map(Option::as_ref) - .zip([28, 29, 30, 31]) - .flat_map(|(b, i)| b.map(|b| (b, i))) - { - entries = entries.extend_with_indices(((index, binding),)); - } - }; - - let transmission_view = transmission_texture - .map(|transmission| &transmission.view) - .unwrap_or(&fallback_image_zero.texture_view); - - let transmission_sampler = transmission_texture - .map(|transmission| &transmission.sampler) - .unwrap_or(&fallback_image_zero.sampler); - - entries = - entries.extend_with_indices(((32, transmission_view), (33, transmission_sampler))); - - if has_oit { - if let ( - Some(oit_layers_binding), - Some(oit_layer_ids_binding), - Some(oit_settings_binding), - ) = ( - oit_buffers.layers.binding(), - oit_buffers.layer_ids.binding(), - oit_buffers.settings.binding(), - ) { - entries = entries.extend_with_indices(( - (34, oit_layers_binding.clone()), - (35, oit_layer_ids_binding.clone()), - (36, oit_settings_binding.clone()), - )); - } - } - commands.entity(entity).insert(MeshViewBindGroup { - value: render_device.create_bind_group("mesh_view_bind_group", layout, &entries), + value: render_device.create_bind_group( + "mesh_view_bind_group", + &layout[0], + &entries, + ), + value_binding_array: render_device.create_bind_group( + "mesh_view_bind_group_binding_array", + &layout[1], + &entries_binding_array, + ), }); } } diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl b/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl index 2fb34d84669c9..e14ce849b3056 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl @@ -50,70 +50,70 @@ const VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE: u32 = 64u; @group(0) @binding(15) var ssr_settings: types::ScreenSpaceReflectionsSettings; @group(0) @binding(16) var screen_space_ambient_occlusion_texture: texture_2d; - -#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY -@group(0) @binding(17) var diffuse_environment_maps: binding_array, 8u>; -@group(0) @binding(18) var specular_environment_maps: binding_array, 8u>; -#else -@group(0) @binding(17) var diffuse_environment_map: texture_cube; -@group(0) @binding(18) var specular_environment_map: texture_cube; -#endif -@group(0) @binding(19) var environment_map_sampler: sampler; -@group(0) @binding(20) var environment_map_uniform: types::EnvironmentMapUniform; - -#ifdef IRRADIANCE_VOLUMES_ARE_USABLE -#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY -@group(0) @binding(21) var irradiance_volumes: binding_array, 8u>; -#else -@group(0) @binding(21) var irradiance_volume: texture_3d; -#endif -@group(0) @binding(22) var irradiance_volume_sampler: sampler; -#endif - -#ifdef CLUSTERED_DECALS_ARE_USABLE -@group(0) @binding(23) var clustered_decals: types::ClusteredDecals; -@group(0) @binding(24) var clustered_decal_textures: binding_array, 8u>; -@group(0) @binding(25) var clustered_decal_sampler: sampler; -#endif // CLUSTERED_DECALS_ARE_USABLE +@group(0) @binding(17) var environment_map_uniform: types::EnvironmentMapUniform; // NB: If you change these, make sure to update `tonemapping_shared.wgsl` too. -@group(0) @binding(26) var dt_lut_texture: texture_3d; -@group(0) @binding(27) var dt_lut_sampler: sampler; +@group(0) @binding(18) var dt_lut_texture: texture_3d; +@group(0) @binding(19) var dt_lut_sampler: sampler; #ifdef MULTISAMPLED #ifdef DEPTH_PREPASS -@group(0) @binding(28) var depth_prepass_texture: texture_depth_multisampled_2d; +@group(0) @binding(20) var depth_prepass_texture: texture_depth_multisampled_2d; #endif // DEPTH_PREPASS #ifdef NORMAL_PREPASS -@group(0) @binding(29) var normal_prepass_texture: texture_multisampled_2d; +@group(0) @binding(21) var normal_prepass_texture: texture_multisampled_2d; #endif // NORMAL_PREPASS #ifdef MOTION_VECTOR_PREPASS -@group(0) @binding(30) var motion_vector_prepass_texture: texture_multisampled_2d; +@group(0) @binding(22) var motion_vector_prepass_texture: texture_multisampled_2d; #endif // MOTION_VECTOR_PREPASS #else // MULTISAMPLED #ifdef DEPTH_PREPASS -@group(0) @binding(28) var depth_prepass_texture: texture_depth_2d; +@group(0) @binding(20) var depth_prepass_texture: texture_depth_2d; #endif // DEPTH_PREPASS #ifdef NORMAL_PREPASS -@group(0) @binding(29) var normal_prepass_texture: texture_2d; +@group(0) @binding(21) var normal_prepass_texture: texture_2d; #endif // NORMAL_PREPASS #ifdef MOTION_VECTOR_PREPASS -@group(0) @binding(30) var motion_vector_prepass_texture: texture_2d; +@group(0) @binding(22) var motion_vector_prepass_texture: texture_2d; #endif // MOTION_VECTOR_PREPASS #endif // MULTISAMPLED #ifdef DEFERRED_PREPASS -@group(0) @binding(31) var deferred_prepass_texture: texture_2d; +@group(0) @binding(23) var deferred_prepass_texture: texture_2d; #endif // DEFERRED_PREPASS -@group(0) @binding(32) var view_transmission_texture: texture_2d; -@group(0) @binding(33) var view_transmission_sampler: sampler; +@group(0) @binding(24) var view_transmission_texture: texture_2d; +@group(0) @binding(25) var view_transmission_sampler: sampler; -#ifdef OIT_ENABLED -@group(0) @binding(34) var oit_layers: array>; -@group(0) @binding(35) var oit_layer_ids: array>; -@group(0) @binding(36) var oit_settings: types::OrderIndependentTransparencySettings; -#endif // OIT_ENABLED +//#ifdef OIT_ENABLED +//@group(0) @binding(26) var oit_layers: array>; +//@group(0) @binding(27) var oit_layer_ids: array>; +//@group(0) @binding(28) var oit_settings: types::OrderIndependentTransparencySettings; +//#endif // OIT_ENABLED + +#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY +@group(1) @binding(0) var diffuse_environment_maps: binding_array, 8u>; +@group(1) @binding(1) var specular_environment_maps: binding_array, 8u>; +#else +@group(1) @binding(0) var diffuse_environment_map: texture_cube; +@group(1) @binding(1) var specular_environment_map: texture_cube; +#endif +@group(1) @binding(2) var environment_map_sampler: sampler; + +#ifdef IRRADIANCE_VOLUMES_ARE_USABLE +#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY +@group(1) @binding(3) var irradiance_volumes: binding_array, 8u>; +#else +@group(1) @binding(3) var irradiance_volume: texture_3d; +#endif +@group(1) @binding(4) var irradiance_volume_sampler: sampler; +#endif + +#ifdef CLUSTERED_DECALS_ARE_USABLE +@group(1) @binding(5) var clustered_decals: types::ClusteredDecals; +@group(1) @binding(6) var clustered_decal_textures: binding_array, 8u>; +@group(1) @binding(7) var clustered_decal_sampler: sampler; +#endif // CLUSTERED_DECALS_ARE_USABLE diff --git a/crates/bevy_pbr/src/render/pbr_bindings.wgsl b/crates/bevy_pbr/src/render/pbr_bindings.wgsl index fac7b97265fdb..373d0bdd54436 100644 --- a/crates/bevy_pbr/src/render/pbr_bindings.wgsl +++ b/crates/bevy_pbr/src/render/pbr_bindings.wgsl @@ -37,53 +37,53 @@ struct StandardMaterialBindings { specular_tint_sampler: u32, // 30 } -@group(2) @binding(0) var material_indices: array; -@group(2) @binding(10) var material_array: array; +@group(3) @binding(0) var material_indices: array; +@group(3) @binding(10) var material_array: array; #else // BINDLESS -@group(2) @binding(0) var material: StandardMaterial; -@group(2) @binding(1) var base_color_texture: texture_2d; -@group(2) @binding(2) var base_color_sampler: sampler; -@group(2) @binding(3) var emissive_texture: texture_2d; -@group(2) @binding(4) var emissive_sampler: sampler; -@group(2) @binding(5) var metallic_roughness_texture: texture_2d; -@group(2) @binding(6) var metallic_roughness_sampler: sampler; -@group(2) @binding(7) var occlusion_texture: texture_2d; -@group(2) @binding(8) var occlusion_sampler: sampler; -@group(2) @binding(9) var normal_map_texture: texture_2d; -@group(2) @binding(10) var normal_map_sampler: sampler; -@group(2) @binding(11) var depth_map_texture: texture_2d; -@group(2) @binding(12) var depth_map_sampler: sampler; +@group(3) @binding(0) var material: StandardMaterial; +@group(3) @binding(1) var base_color_texture: texture_2d; +@group(3) @binding(2) var base_color_sampler: sampler; +@group(3) @binding(3) var emissive_texture: texture_2d; +@group(3) @binding(4) var emissive_sampler: sampler; +@group(3) @binding(5) var metallic_roughness_texture: texture_2d; +@group(3) @binding(6) var metallic_roughness_sampler: sampler; +@group(3) @binding(7) var occlusion_texture: texture_2d; +@group(3) @binding(8) var occlusion_sampler: sampler; +@group(3) @binding(9) var normal_map_texture: texture_2d; +@group(3) @binding(10) var normal_map_sampler: sampler; +@group(3) @binding(11) var depth_map_texture: texture_2d; +@group(3) @binding(12) var depth_map_sampler: sampler; #ifdef PBR_ANISOTROPY_TEXTURE_SUPPORTED -@group(2) @binding(13) var anisotropy_texture: texture_2d; -@group(2) @binding(14) var anisotropy_sampler: sampler; +@group(3) @binding(13) var anisotropy_texture: texture_2d; +@group(3) @binding(14) var anisotropy_sampler: sampler; #endif // PBR_ANISOTROPY_TEXTURE_SUPPORTED #ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED -@group(2) @binding(15) var specular_transmission_texture: texture_2d; -@group(2) @binding(16) var specular_transmission_sampler: sampler; -@group(2) @binding(17) var thickness_texture: texture_2d; -@group(2) @binding(18) var thickness_sampler: sampler; -@group(2) @binding(19) var diffuse_transmission_texture: texture_2d; -@group(2) @binding(20) var diffuse_transmission_sampler: sampler; +@group(3) @binding(15) var specular_transmission_texture: texture_2d; +@group(3) @binding(16) var specular_transmission_sampler: sampler; +@group(3) @binding(17) var thickness_texture: texture_2d; +@group(3) @binding(18) var thickness_sampler: sampler; +@group(3) @binding(19) var diffuse_transmission_texture: texture_2d; +@group(3) @binding(20) var diffuse_transmission_sampler: sampler; #endif // PBR_TRANSMISSION_TEXTURES_SUPPORTED #ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED -@group(2) @binding(21) var clearcoat_texture: texture_2d; -@group(2) @binding(22) var clearcoat_sampler: sampler; -@group(2) @binding(23) var clearcoat_roughness_texture: texture_2d; -@group(2) @binding(24) var clearcoat_roughness_sampler: sampler; -@group(2) @binding(25) var clearcoat_normal_texture: texture_2d; -@group(2) @binding(26) var clearcoat_normal_sampler: sampler; +@group(3) @binding(21) var clearcoat_texture: texture_2d; +@group(3) @binding(22) var clearcoat_sampler: sampler; +@group(3) @binding(23) var clearcoat_roughness_texture: texture_2d; +@group(3) @binding(24) var clearcoat_roughness_sampler: sampler; +@group(3) @binding(25) var clearcoat_normal_texture: texture_2d; +@group(3) @binding(26) var clearcoat_normal_sampler: sampler; #endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED #ifdef PBR_SPECULAR_TEXTURES_SUPPORTED -@group(2) @binding(27) var specular_texture: texture_2d; -@group(2) @binding(28) var specular_sampler: sampler; -@group(2) @binding(29) var specular_tint_texture: texture_2d; -@group(2) @binding(30) var specular_tint_sampler: sampler; +@group(3) @binding(27) var specular_texture: texture_2d; +@group(3) @binding(28) var specular_sampler: sampler; +@group(3) @binding(29) var specular_tint_texture: texture_2d; +@group(3) @binding(30) var specular_tint_sampler: sampler; #endif // PBR_SPECULAR_TEXTURES_SUPPORTED #endif // BINDLESS diff --git a/crates/bevy_pbr/src/ssr/mod.rs b/crates/bevy_pbr/src/ssr/mod.rs index 9f7dbb2f769e2..9e5ad5a20ca70 100644 --- a/crates/bevy_pbr/src/ssr/mod.rs +++ b/crates/bevy_pbr/src/ssr/mod.rs @@ -515,9 +515,11 @@ impl SpecializedRenderPipeline for ScreenSpaceReflectionsPipeline { type Key = ScreenSpaceReflectionsPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let mesh_view_layout = self + let mut layout = self .mesh_view_layouts - .get_view_layout(key.mesh_pipeline_view_key); + .get_view_layout(key.mesh_pipeline_view_key) + .to_vec(); + layout.push(self.bind_group_layout.clone()); let mut shader_defs = vec![ "DEPTH_PREPASS".into(), @@ -535,7 +537,7 @@ impl SpecializedRenderPipeline for ScreenSpaceReflectionsPipeline { RenderPipelineDescriptor { label: Some("SSR pipeline".into()), - layout: vec![mesh_view_layout.clone(), self.bind_group_layout.clone()], + layout, vertex: fullscreen_vertex_shader::fullscreen_shader_vertex_state(), fragment: Some(FragmentState { shader: self.shader.clone(), diff --git a/crates/bevy_pbr/src/volumetric_fog/render.rs b/crates/bevy_pbr/src/volumetric_fog/render.rs index 45f694e546f31..6f9b70abb060f 100644 --- a/crates/bevy_pbr/src/volumetric_fog/render.rs +++ b/crates/bevy_pbr/src/volumetric_fog/render.rs @@ -559,9 +559,15 @@ impl SpecializedRenderPipeline for VolumetricFogPipeline { shader_defs.push("DENSITY_TEXTURE".into()); } + let mut layout = self + .mesh_view_layouts + .get_view_layout(key.mesh_pipeline_view_key) + .to_vec(); + layout.push(volumetric_view_bind_group_layout.clone()); + RenderPipelineDescriptor { label: Some("volumetric lighting pipeline".into()), - layout: vec![mesh_view_layout.clone(), volumetric_view_bind_group_layout], + layout, push_constant_ranges: vec![], vertex: VertexState { shader: self.shader.clone(), diff --git a/crates/bevy_pbr/src/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index cc64ad2e4f09c..1f22688b77547 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -317,8 +317,8 @@ impl RenderCommand

for SetWireframe3dPushConstants { pub type DrawWireframe3d = ( SetItemPipeline, - SetMeshViewBindGroup<0>, - SetMeshBindGroup<1>, + SetMeshViewBindGroup<0, 1>, + SetMeshBindGroup<2>, SetWireframe3dPushConstants, DrawMesh, ); diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index 374dc6b33081c..c2d43c32b7167 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -167,15 +167,15 @@ impl DrawFunctions

{ /// /// ``` /// # use bevy_render::render_phase::SetItemPipeline; -/// # struct SetMeshViewBindGroup; +/// # struct SetMeshViewBindGroup; /// # struct SetMeshBindGroup; /// # struct SetMaterialBindGroup(std::marker::PhantomData); /// # struct DrawMesh; /// pub type DrawMaterial = ( /// SetItemPipeline, -/// SetMeshViewBindGroup<0>, -/// SetMeshBindGroup<1>, -/// SetMaterialBindGroup, +/// SetMeshViewBindGroup<0, 1>, +/// SetMeshBindGroup<2>, +/// SetMaterialBindGroup, /// DrawMesh, /// ); /// ``` diff --git a/crates/bevy_render/src/render_resource/bind_group.rs b/crates/bevy_render/src/render_resource/bind_group.rs index cff88bd355a62..17de8455dac5d 100644 --- a/crates/bevy_render/src/render_resource/bind_group.rs +++ b/crates/bevy_render/src/render_resource/bind_group.rs @@ -133,12 +133,12 @@ impl Deref for BindGroup { /// In WGSL shaders, the binding would look like this: /// /// ```wgsl -/// @group(2) @binding(0) var color: vec4; -/// @group(2) @binding(1) var color_texture: texture_2d; -/// @group(2) @binding(2) var color_sampler: sampler; -/// @group(2) @binding(3) var storage_buffer: array; -/// @group(2) @binding(4) var raw_buffer: array; -/// @group(2) @binding(5) var storage_texture: texture_storage_2d; +/// @group(3) @binding(0) var color: vec4; +/// @group(3) @binding(1) var color_texture: texture_2d; +/// @group(3) @binding(2) var color_sampler: sampler; +/// @group(3) @binding(3) var storage_buffer: array; +/// @group(3) @binding(4) var raw_buffer: array; +/// @group(3) @binding(5) var storage_texture: texture_storage_2d; /// ``` /// Note that the "group" index is determined by the usage context. It is not defined in [`AsBindGroup`]. For example, in Bevy material bind groups /// are generally bound to group 2. @@ -261,7 +261,7 @@ impl Deref for BindGroup { /// roughness: f32, /// }; /// -/// @group(2) @binding(0) var material: CoolMaterial; +/// @group(3) @binding(0) var material: CoolMaterial; /// ``` /// /// Some less common scenarios will require "struct-level" attributes. These are the currently supported struct-level attributes: @@ -312,7 +312,7 @@ impl Deref for BindGroup { /// declaration: /// /// ```wgsl -/// @group(2) @binding(10) var material_array: binding_array; +/// @group(3) @binding(10) var material_array: binding_array; /// ``` /// /// On the other hand, if you write this declaration: @@ -325,7 +325,7 @@ impl Deref for BindGroup { /// Then Bevy produces a binding that matches this WGSL declaration instead: /// /// ```wgsl -/// @group(2) @binding(10) var material_array: array; +/// @group(3) @binding(10) var material_array: array; /// ``` /// /// * Just as with the structure-level `uniform` attribute, Bevy converts the @@ -338,7 +338,7 @@ impl Deref for BindGroup { /// this in WGSL in non-bindless mode: /// /// ```wgsl -/// @group(2) @binding(0) var material: StandardMaterial; +/// @group(3) @binding(0) var material: StandardMaterial; /// ``` /// /// * For efficiency reasons, `data` is generally preferred over `uniform` diff --git a/crates/bevy_render/src/render_resource/bind_group_entries.rs b/crates/bevy_render/src/render_resource/bind_group_entries.rs index cc8eb188de461..847bb46f498af 100644 --- a/crates/bevy_render/src/render_resource/bind_group_entries.rs +++ b/crates/bevy_render/src/render_resource/bind_group_entries.rs @@ -287,6 +287,12 @@ impl<'b> DynamicBindGroupEntries<'b> { } } + pub fn new() -> Self { + Self { + entries: Vec::new(), + } + } + pub fn extend_with_indices( mut self, entries: impl IntoIndexedBindingArray<'b, N>, diff --git a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs index 575c6a23fdab5..24d6ba5176484 100644 --- a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs +++ b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs @@ -334,6 +334,15 @@ impl DynamicBindGroupLayoutEntries { } } + pub fn new( + default_visibility: ShaderStages, + ) -> Self { + Self { + default_visibility, + entries: Vec::new(), + } + } + pub fn extend_with_indices( mut self, entries: impl IntoIndexedBindGroupLayoutEntryBuilderArray, diff --git a/examples/shader/custom_render_phase.rs b/examples/shader/custom_render_phase.rs index 6499ca6bd26af..7200bcce7f669 100644 --- a/examples/shader/custom_render_phase.rs +++ b/examples/shader/custom_render_phase.rs @@ -242,9 +242,9 @@ impl SpecializedMeshPipeline for StencilPipeline { type DrawMesh3dStencil = ( SetItemPipeline, // This will set the view bindings in group 0 - SetMeshViewBindGroup<0>, + SetMeshViewBindGroup<0, 1>, // This will set the mesh bindings in group 1 - SetMeshBindGroup<1>, + SetMeshBindGroup<2>, // This will draw the mesh DrawMesh, ); diff --git a/examples/shader/custom_shader_instancing.rs b/examples/shader/custom_shader_instancing.rs index d81c6e53b6632..edea5794496a4 100644 --- a/examples/shader/custom_shader_instancing.rs +++ b/examples/shader/custom_shader_instancing.rs @@ -247,8 +247,8 @@ impl SpecializedMeshPipeline for CustomPipeline { type DrawCustom = ( SetItemPipeline, - SetMeshViewBindGroup<0>, - SetMeshBindGroup<1>, + SetMeshViewBindGroup<0, 1>, + SetMeshBindGroup<2>, DrawMeshInstanced, ); diff --git a/examples/shader/specialized_mesh_pipeline.rs b/examples/shader/specialized_mesh_pipeline.rs index a2cfd11b34b37..1c28de50d5ddb 100644 --- a/examples/shader/specialized_mesh_pipeline.rs +++ b/examples/shader/specialized_mesh_pipeline.rs @@ -152,9 +152,9 @@ type DrawSpecializedPipelineCommands = ( // Set the pipeline SetItemPipeline, // Set the view uniform at bind group 0 - SetMeshViewBindGroup<0>, + SetMeshViewBindGroup<0, 1>, // Set the mesh uniform at bind group 1 - SetMeshBindGroup<1>, + SetMeshBindGroup<2>, // Draw the mesh DrawMesh, ); @@ -209,16 +209,15 @@ impl SpecializedMeshPipeline for CustomMeshPipeline { // This will automatically generate the correct `VertexBufferLayout` based on the vertex attributes let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?; + let mut layout = self.mesh_pipeline + .get_view_layout(MeshPipelineViewLayoutKey::from(mesh_key)) + .clone() + .to_vec(); + layout.push(self.mesh_pipeline.mesh_layouts.model_only.clone()); + Ok(RenderPipelineDescriptor { label: Some("Specialized Mesh Pipeline".into()), - layout: vec![ - // Bind group 0 is the view uniform - self.mesh_pipeline - .get_view_layout(MeshPipelineViewLayoutKey::from(mesh_key)) - .clone(), - // Bind group 1 is the mesh uniform - self.mesh_pipeline.mesh_layouts.model_only.clone(), - ], + layout, push_constant_ranges: vec![], vertex: VertexState { shader: self.shader_handle.clone(), diff --git a/examples/shader/texture_binding_array.rs b/examples/shader/texture_binding_array.rs index bf5dc3da9debe..e4939edf6ae86 100644 --- a/examples/shader/texture_binding_array.rs +++ b/examples/shader/texture_binding_array.rs @@ -163,7 +163,7 @@ impl AsBindGroup for BindlessMaterial { ( // Screen texture // - // @group(2) @binding(0) var textures: binding_array>; + // @group(3) @binding(0) var textures: binding_array>; ( 0, texture_2d(TextureSampleType::Float { filterable: true }) @@ -171,7 +171,7 @@ impl AsBindGroup for BindlessMaterial { ), // Sampler // - // @group(2) @binding(1) var nearest_sampler: sampler; + // @group(3) @binding(1) var nearest_sampler: sampler; // // Note: as with textures, multiple samplers can also be bound // onto one binding slot: From 891184e8ff160d9bdf8988aa0b29df34461fc90e Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Mon, 9 Jun 2025 15:45:43 -0700 Subject: [PATCH 03/37] Fmt. --- crates/bevy_pbr/src/prepass/mod.rs | 10 ++- .../bevy_pbr/src/render/mesh_view_bindings.rs | 72 +++++++++---------- .../src/render/mesh_view_bindings.wgsl | 10 +-- crates/bevy_render/src/lib.rs | 4 +- .../bind_group_layout_entries.rs | 10 +-- .../src/render_resource/pipeline_cache.rs | 2 +- crates/bevy_render/src/renderer/mod.rs | 23 +++--- crates/bevy_render/src/settings.rs | 2 +- examples/shader/specialized_mesh_pipeline.rs | 3 +- 9 files changed, 67 insertions(+), 69 deletions(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index e7523e45e3262..8d48f4986f28c 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -1255,7 +1255,9 @@ pub fn queue_prepass_material_meshes( } pub struct SetPrepassViewBindGroup; -impl RenderCommand

for SetPrepassViewBindGroup { +impl RenderCommand

+ for SetPrepassViewBindGroup +{ type Param = SRes; type ViewQuery = ( Read, @@ -1297,11 +1299,7 @@ impl RenderCommand

for SetPrepa ); } } - pass.set_bind_group( - J, - &prepass_view_bind_group.empty_bind_group, - &[], - ); + pass.set_bind_group(J, &prepass_view_bind_group.empty_bind_group, &[]); RenderCommandResult::Success } diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.rs b/crates/bevy_pbr/src/render/mesh_view_bindings.rs index dcb6751d36bb7..86521d742c1fd 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.rs @@ -352,25 +352,25 @@ fn layout_entries( (25, sampler(SamplerBindingType::Filtering)), )); - // // OIT - // if layout_key.contains(MeshPipelineViewLayoutKey::OIT_ENABLED) { - // // Check if we can use OIT. This is a hack to avoid errors on webgl -- - // // the OIT plugin will warn the user that OIT is not supported on their - // // platform, so we don't need to do it here. - // if is_oit_supported(render_adapter, render_device, false) { - // entries = entries.extend_with_indices(( - // // oit_layers - // (26, storage_buffer_sized(false, None)), - // // oit_layer_ids, - // (27, storage_buffer_sized(false, None)), - // // oit_layer_count - // ( - // 28, - // uniform_buffer::(true), - // ), - // )); - // } - // } + // OIT + if layout_key.contains(MeshPipelineViewLayoutKey::OIT_ENABLED) { + // Check if we can use OIT. This is a hack to avoid errors on webgl -- + // the OIT plugin will warn the user that OIT is not supported on their + // platform, so we don't need to do it here. + if is_oit_supported(render_adapter, render_device, false) { + entries = entries.extend_with_indices(( + // oit_layers + (26, storage_buffer_sized(false, None)), + // oit_layer_ids, + (27, storage_buffer_sized(false, None)), + // oit_layer_count + ( + 28, + uniform_buffer::(true), + ), + )); + } + } let mut binding_array_entries = DynamicBindGroupLayoutEntries::new(ShaderStages::FRAGMENT); binding_array_entries = binding_array_entries.extend_with_indices(( @@ -665,23 +665,23 @@ pub fn prepare_mesh_view_bind_groups( entries = entries.extend_with_indices(((24, transmission_view), (25, transmission_sampler))); - // if has_oit { - // if let ( - // Some(oit_layers_binding), - // Some(oit_layer_ids_binding), - // Some(oit_settings_binding), - // ) = ( - // oit_buffers.layers.binding(), - // oit_buffers.layer_ids.binding(), - // oit_buffers.settings.binding(), - // ) { - // entries = entries.extend_with_indices(( - // (26, oit_layers_binding.clone()), - // (27, oit_layer_ids_binding.clone()), - // (28, oit_settings_binding.clone()), - // )); - // } - // } + if has_oit { + if let ( + Some(oit_layers_binding), + Some(oit_layer_ids_binding), + Some(oit_settings_binding), + ) = ( + oit_buffers.layers.binding(), + oit_buffers.layer_ids.binding(), + oit_buffers.settings.binding(), + ) { + entries = entries.extend_with_indices(( + (26, oit_layers_binding.clone()), + (27, oit_layer_ids_binding.clone()), + (28, oit_settings_binding.clone()), + )); + } + } let mut entries_binding_array = DynamicBindGroupEntries::new(); diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl b/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl index e14ce849b3056..0f650e6e54dbb 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl @@ -88,11 +88,11 @@ const VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE: u32 = 64u; @group(0) @binding(24) var view_transmission_texture: texture_2d; @group(0) @binding(25) var view_transmission_sampler: sampler; -//#ifdef OIT_ENABLED -//@group(0) @binding(26) var oit_layers: array>; -//@group(0) @binding(27) var oit_layer_ids: array>; -//@group(0) @binding(28) var oit_settings: types::OrderIndependentTransparencySettings; -//#endif // OIT_ENABLED +#ifdef OIT_ENABLED +@group(0) @binding(26) var oit_layers: array>; +@group(0) @binding(27) var oit_layer_ids: array>; +@group(0) @binding(28) var oit_settings: types::OrderIndependentTransparencySettings; +#endif // OIT_ENABLED #ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY @group(1) @binding(0) var diffuse_environment_maps: binding_array, 8u>; diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index c7b134394bef5..aa1e2da676082 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -357,9 +357,7 @@ impl Plugin for RenderPlugin { dx12: wgpu::Dx12BackendOptions { shader_compiler: settings.dx12_shader_compiler.clone(), }, - noop: wgpu::NoopBackendOptions { - enable: false, - }, + noop: wgpu::NoopBackendOptions { enable: false }, }, }); diff --git a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs index 24d6ba5176484..17630b7dae2d7 100644 --- a/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs +++ b/crates/bevy_render/src/render_resource/bind_group_layout_entries.rs @@ -334,9 +334,7 @@ impl DynamicBindGroupLayoutEntries { } } - pub fn new( - default_visibility: ShaderStages, - ) -> Self { + pub fn new(default_visibility: ShaderStages) -> Self { Self { default_visibility, entries: Vec::new(), @@ -581,12 +579,14 @@ pub mod binding_types { pub fn acceleration_structure() -> BindGroupLayoutEntryBuilder { BindingType::AccelerationStructure { vertex_return: false, - }.into_bind_group_layout_entry_builder() + } + .into_bind_group_layout_entry_builder() } pub fn acceleration_structure_vertex_return() -> BindGroupLayoutEntryBuilder { BindingType::AccelerationStructure { vertex_return: true, - }.into_bind_group_layout_entry_builder() + } + .into_bind_group_layout_entry_builder() } } diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index e3e990f5d8f2d..4c1f3f6e57571 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -1164,7 +1164,7 @@ fn get_capabilities(features: Features, downlevel: DownlevelFlags) -> Capabiliti ); capabilities.set( Capabilities::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING, - features.contains(Features::UNIFORM_BUFFER_BINDING_ARRAYS) + features.contains(Features::UNIFORM_BUFFER_BINDING_ARRAYS), ); // TODO: This needs a proper wgpu feature capabilities.set( diff --git a/crates/bevy_render/src/renderer/mod.rs b/crates/bevy_render/src/renderer/mod.rs index fd6fe80aa2f67..084e7cb0608b5 100644 --- a/crates/bevy_render/src/renderer/mod.rs +++ b/crates/bevy_render/src/renderer/mod.rs @@ -21,7 +21,10 @@ use alloc::sync::Arc; use bevy_ecs::{prelude::*, system::SystemState}; use bevy_platform::time::Instant; use bevy_time::TimeSender; -use wgpu::{Adapter, AdapterInfo, CommandBuffer, CommandEncoder, DeviceType, Instance, Queue, RequestAdapterOptions, Trace}; +use wgpu::{ + Adapter, AdapterInfo, CommandBuffer, CommandEncoder, DeviceType, Instance, Queue, + RequestAdapterOptions, Trace, +}; /// Updates the [`RenderGraph`] with all of its nodes and then runs it to render the entire frame. pub fn render_system(world: &mut World, state: &mut SystemState>>) { @@ -313,16 +316,14 @@ pub async fn initialize_renderer( } let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - label: options.device_label.as_ref().map(AsRef::as_ref), - required_features: features, - required_limits: limits, - memory_hints: options.memory_hints.clone(), - // See https://github.com/gfx-rs/wgpu/issues/5974 - trace: Trace::Off, - }, - ) + .request_device(&wgpu::DeviceDescriptor { + label: options.device_label.as_ref().map(AsRef::as_ref), + required_features: features, + required_limits: limits, + memory_hints: options.memory_hints.clone(), + // See https://github.com/gfx-rs/wgpu/issues/5974 + trace: Trace::Off, + }) .await .unwrap(); let queue = Arc::new(WgpuWrapper::new(queue)); diff --git a/crates/bevy_render/src/settings.rs b/crates/bevy_render/src/settings.rs index 427b080a3410c..715bbb35f845b 100644 --- a/crates/bevy_render/src/settings.rs +++ b/crates/bevy_render/src/settings.rs @@ -3,11 +3,11 @@ use crate::renderer::{ }; use alloc::borrow::Cow; +use wgpu::DxcShaderModel; pub use wgpu::{ Backends, Dx12Compiler, Features as WgpuFeatures, Gles3MinorVersion, InstanceFlags, Limits as WgpuLimits, MemoryHints, PowerPreference, }; -use wgpu::DxcShaderModel; /// Configures the priority used when automatically configuring the features/limits of `wgpu`. #[derive(Clone)] diff --git a/examples/shader/specialized_mesh_pipeline.rs b/examples/shader/specialized_mesh_pipeline.rs index 1c28de50d5ddb..8be91f918162d 100644 --- a/examples/shader/specialized_mesh_pipeline.rs +++ b/examples/shader/specialized_mesh_pipeline.rs @@ -209,7 +209,8 @@ impl SpecializedMeshPipeline for CustomMeshPipeline { // This will automatically generate the correct `VertexBufferLayout` based on the vertex attributes let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?; - let mut layout = self.mesh_pipeline + let mut layout = self + .mesh_pipeline .get_view_layout(MeshPipelineViewLayoutKey::from(mesh_key)) .clone() .to_vec(); From ddf8b8e276c0b7b2b9bfbc580c770d2ef00237b8 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Sat, 14 Jun 2025 17:32:37 -0700 Subject: [PATCH 04/37] . --- assets/shaders/array_texture.wgsl | 4 +-- assets/shaders/automatic_instancing.wgsl | 4 +-- assets/shaders/bindless_material.wgsl | 10 +++---- assets/shaders/cubemap_unlit.wgsl | 6 ++-- assets/shaders/custom_material.wesl | 2 +- assets/shaders/custom_material.wgsl | 6 ++-- .../custom_material_screenspace_texture.wgsl | 4 +-- assets/shaders/custom_vertex_attribute.wgsl | 2 +- assets/shaders/extended_material.wgsl | 2 +- .../shaders/extended_material_bindless.wgsl | 10 +++---- assets/shaders/fallback_image_test.wgsl | 24 +++++++-------- ...irradiance_volume_voxel_visualization.wgsl | 2 +- assets/shaders/line_material.wgsl | 2 +- assets/shaders/shader_defs.wgsl | 2 +- assets/shaders/show_prepass.wgsl | 2 +- assets/shaders/storage_buffer.wgsl | 2 +- assets/shaders/texture_binding_array.wgsl | 4 +-- assets/shaders/water_material.wgsl | 6 ++-- crates/bevy_pbr/src/ssr/mod.rs | 29 +++++++++---------- crates/bevy_pbr/src/ssr/ssr.wgsl | 4 +-- crates/bevy_render/src/lib.rs | 20 ++++++++++++- 21 files changed, 81 insertions(+), 66 deletions(-) diff --git a/assets/shaders/array_texture.wgsl b/assets/shaders/array_texture.wgsl index d49d492a06396..293f3316654e4 100644 --- a/assets/shaders/array_texture.wgsl +++ b/assets/shaders/array_texture.wgsl @@ -7,8 +7,8 @@ } #import bevy_core_pipeline::tonemapping::tone_mapping -@group(2) @binding(0) var my_array_texture: texture_2d_array; -@group(2) @binding(1) var my_array_texture_sampler: sampler; +@group(3) @binding(0) var my_array_texture: texture_2d_array; +@group(3) @binding(1) var my_array_texture_sampler: sampler; @fragment fn fragment( diff --git a/assets/shaders/automatic_instancing.wgsl b/assets/shaders/automatic_instancing.wgsl index 35276246b094e..ca2195df0d4de 100644 --- a/assets/shaders/automatic_instancing.wgsl +++ b/assets/shaders/automatic_instancing.wgsl @@ -3,8 +3,8 @@ view_transformations::position_world_to_clip } -@group(2) @binding(0) var texture: texture_2d; -@group(2) @binding(1) var texture_sampler: sampler; +@group(3) @binding(0) var texture: texture_2d; +@group(3) @binding(1) var texture_sampler: sampler; struct Vertex { @builtin(instance_index) instance_index: u32, diff --git a/assets/shaders/bindless_material.wgsl b/assets/shaders/bindless_material.wgsl index 3de313b81afa9..f7fa795d94c1c 100644 --- a/assets/shaders/bindless_material.wgsl +++ b/assets/shaders/bindless_material.wgsl @@ -15,12 +15,12 @@ struct MaterialBindings { } #ifdef BINDLESS -@group(2) @binding(0) var materials: array; -@group(2) @binding(10) var material_color: binding_array; +@group(3) @binding(0) var materials: array; +@group(3) @binding(10) var material_color: binding_array; #else // BINDLESS -@group(2) @binding(0) var material_color: Color; -@group(2) @binding(1) var material_color_texture: texture_2d; -@group(2) @binding(2) var material_color_sampler: sampler; +@group(3) @binding(0) var material_color: Color; +@group(3) @binding(1) var material_color_texture: texture_2d; +@group(3) @binding(2) var material_color_sampler: sampler; #endif // BINDLESS @fragment diff --git a/assets/shaders/cubemap_unlit.wgsl b/assets/shaders/cubemap_unlit.wgsl index 14e45a045bfdb..81e153e408dfb 100644 --- a/assets/shaders/cubemap_unlit.wgsl +++ b/assets/shaders/cubemap_unlit.wgsl @@ -1,12 +1,12 @@ #import bevy_pbr::forward_io::VertexOutput #ifdef CUBEMAP_ARRAY -@group(2) @binding(0) var base_color_texture: texture_cube_array; +@group(3) @binding(0) var base_color_texture: texture_cube_array; #else -@group(2) @binding(0) var base_color_texture: texture_cube; +@group(3) @binding(0) var base_color_texture: texture_cube; #endif -@group(2) @binding(1) var base_color_sampler: sampler; +@group(3) @binding(1) var base_color_sampler: sampler; @fragment fn fragment( diff --git a/assets/shaders/custom_material.wesl b/assets/shaders/custom_material.wesl index 5113e1cbe0b39..ca946687845ab 100644 --- a/assets/shaders/custom_material.wesl +++ b/assets/shaders/custom_material.wesl @@ -10,7 +10,7 @@ struct CustomMaterial { time: vec4, } -@group(2) @binding(0) var material: CustomMaterial; +@group(3) @binding(0) var material: CustomMaterial; @fragment fn fragment( diff --git a/assets/shaders/custom_material.wgsl b/assets/shaders/custom_material.wgsl index 1b65627d45b32..7548d2223c8af 100644 --- a/assets/shaders/custom_material.wgsl +++ b/assets/shaders/custom_material.wgsl @@ -2,9 +2,9 @@ // we can import items from shader modules in the assets folder with a quoted path #import "shaders/custom_material_import.wgsl"::COLOR_MULTIPLIER -@group(2) @binding(0) var material_color: vec4; -@group(2) @binding(1) var material_color_texture: texture_2d; -@group(2) @binding(2) var material_color_sampler: sampler; +@group(3) @binding(0) var material_color: vec4; +@group(3) @binding(1) var material_color_texture: texture_2d; +@group(3) @binding(2) var material_color_sampler: sampler; @fragment fn fragment( diff --git a/assets/shaders/custom_material_screenspace_texture.wgsl b/assets/shaders/custom_material_screenspace_texture.wgsl index 36da2a7f8c204..abad3cc15afd1 100644 --- a/assets/shaders/custom_material_screenspace_texture.wgsl +++ b/assets/shaders/custom_material_screenspace_texture.wgsl @@ -4,8 +4,8 @@ utils::coords_to_viewport_uv, } -@group(2) @binding(0) var texture: texture_2d; -@group(2) @binding(1) var texture_sampler: sampler; +@group(3) @binding(0) var texture: texture_2d; +@group(3) @binding(1) var texture_sampler: sampler; @fragment fn fragment( diff --git a/assets/shaders/custom_vertex_attribute.wgsl b/assets/shaders/custom_vertex_attribute.wgsl index f8062ab77be3f..6b7b93e4c7161 100644 --- a/assets/shaders/custom_vertex_attribute.wgsl +++ b/assets/shaders/custom_vertex_attribute.wgsl @@ -3,7 +3,7 @@ struct CustomMaterial { color: vec4, }; -@group(2) @binding(0) var material: CustomMaterial; +@group(3) @binding(0) var material: CustomMaterial; struct Vertex { @builtin(instance_index) instance_index: u32, diff --git a/assets/shaders/extended_material.wgsl b/assets/shaders/extended_material.wgsl index fc69f30bb56e4..7bad24a331b93 100644 --- a/assets/shaders/extended_material.wgsl +++ b/assets/shaders/extended_material.wgsl @@ -19,7 +19,7 @@ struct MyExtendedMaterial { quantize_steps: u32, } -@group(2) @binding(100) +@group(3) @binding(100) var my_extended_material: MyExtendedMaterial; @fragment diff --git a/assets/shaders/extended_material_bindless.wgsl b/assets/shaders/extended_material_bindless.wgsl index f8650b0da7f60..c9cb07e0c733e 100644 --- a/assets/shaders/extended_material_bindless.wgsl +++ b/assets/shaders/extended_material_bindless.wgsl @@ -42,19 +42,19 @@ struct ExampleBindlessExtendedMaterial { // The indices of the bindless resources in the bindless resource arrays, for // the `ExampleBindlessExtension` fields. -@group(2) @binding(100) var example_extended_material_indices: +@group(3) @binding(100) var example_extended_material_indices: array; // An array that holds the `ExampleBindlessExtendedMaterial` plain old data, // indexed by `ExampleBindlessExtendedMaterialIndices.material`. -@group(2) @binding(101) var example_extended_material: +@group(3) @binding(101) var example_extended_material: array; #else // BINDLESS // In non-bindless mode, we simply use a uniform for the plain old data. -@group(2) @binding(50) var example_extended_material: ExampleBindlessExtendedMaterial; -@group(2) @binding(51) var modulate_texture: texture_2d; -@group(2) @binding(52) var modulate_sampler: sampler; +@group(3) @binding(50) var example_extended_material: ExampleBindlessExtendedMaterial; +@group(3) @binding(51) var modulate_texture: texture_2d; +@group(3) @binding(52) var modulate_sampler: sampler; #endif // BINDLESS diff --git a/assets/shaders/fallback_image_test.wgsl b/assets/shaders/fallback_image_test.wgsl index c48f091bcca4c..c92cbd1577e4e 100644 --- a/assets/shaders/fallback_image_test.wgsl +++ b/assets/shaders/fallback_image_test.wgsl @@ -1,22 +1,22 @@ #import bevy_pbr::forward_io::VertexOutput -@group(2) @binding(0) var test_texture_1d: texture_1d; -@group(2) @binding(1) var test_texture_1d_sampler: sampler; +@group(3) @binding(0) var test_texture_1d: texture_1d; +@group(3) @binding(1) var test_texture_1d_sampler: sampler; -@group(2) @binding(2) var test_texture_2d: texture_2d; -@group(2) @binding(3) var test_texture_2d_sampler: sampler; +@group(3) @binding(2) var test_texture_2d: texture_2d; +@group(3) @binding(3) var test_texture_2d_sampler: sampler; -@group(2) @binding(4) var test_texture_2d_array: texture_2d_array; -@group(2) @binding(5) var test_texture_2d_array_sampler: sampler; +@group(3) @binding(4) var test_texture_2d_array: texture_2d_array; +@group(3) @binding(5) var test_texture_2d_array_sampler: sampler; -@group(2) @binding(6) var test_texture_cube: texture_cube; -@group(2) @binding(7) var test_texture_cube_sampler: sampler; +@group(3) @binding(6) var test_texture_cube: texture_cube; +@group(3) @binding(7) var test_texture_cube_sampler: sampler; -@group(2) @binding(8) var test_texture_cube_array: texture_cube_array; -@group(2) @binding(9) var test_texture_cube_array_sampler: sampler; +@group(3) @binding(8) var test_texture_cube_array: texture_cube_array; +@group(3) @binding(9) var test_texture_cube_array_sampler: sampler; -@group(2) @binding(10) var test_texture_3d: texture_3d; -@group(2) @binding(11) var test_texture_3d_sampler: sampler; +@group(3) @binding(10) var test_texture_3d: texture_3d; +@group(3) @binding(11) var test_texture_3d_sampler: sampler; @fragment fn fragment(in: VertexOutput) {} diff --git a/assets/shaders/irradiance_volume_voxel_visualization.wgsl b/assets/shaders/irradiance_volume_voxel_visualization.wgsl index f34e6f8453dd7..0e12110f3b1da 100644 --- a/assets/shaders/irradiance_volume_voxel_visualization.wgsl +++ b/assets/shaders/irradiance_volume_voxel_visualization.wgsl @@ -12,7 +12,7 @@ struct VoxelVisualizationIrradianceVolumeInfo { intensity: f32, } -@group(2) @binding(100) +@group(3) @binding(100) var irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo; @fragment diff --git a/assets/shaders/line_material.wgsl b/assets/shaders/line_material.wgsl index cc7ca047d5d2d..639762a444ab4 100644 --- a/assets/shaders/line_material.wgsl +++ b/assets/shaders/line_material.wgsl @@ -4,7 +4,7 @@ struct LineMaterial { color: vec4, }; -@group(2) @binding(0) var material: LineMaterial; +@group(3) @binding(0) var material: LineMaterial; @fragment fn fragment( diff --git a/assets/shaders/shader_defs.wgsl b/assets/shaders/shader_defs.wgsl index fdddc4caa1442..776fc9ffe69eb 100644 --- a/assets/shaders/shader_defs.wgsl +++ b/assets/shaders/shader_defs.wgsl @@ -4,7 +4,7 @@ struct CustomMaterial { color: vec4, }; -@group(2) @binding(0) var material: CustomMaterial; +@group(3) @binding(0) var material: CustomMaterial; @fragment fn fragment( diff --git a/assets/shaders/show_prepass.wgsl b/assets/shaders/show_prepass.wgsl index c1b3a89750227..b1a53677ac1ea 100644 --- a/assets/shaders/show_prepass.wgsl +++ b/assets/shaders/show_prepass.wgsl @@ -11,7 +11,7 @@ struct ShowPrepassSettings { padding_1: u32, padding_2: u32, } -@group(2) @binding(0) var settings: ShowPrepassSettings; +@group(3) @binding(0) var settings: ShowPrepassSettings; @fragment fn fragment( diff --git a/assets/shaders/storage_buffer.wgsl b/assets/shaders/storage_buffer.wgsl index c27053b9a21b3..f447333cc9754 100644 --- a/assets/shaders/storage_buffer.wgsl +++ b/assets/shaders/storage_buffer.wgsl @@ -3,7 +3,7 @@ view_transformations::position_world_to_clip } -@group(2) @binding(0) var colors: array, 5>; +@group(3) @binding(0) var colors: array, 5>; struct Vertex { @builtin(instance_index) instance_index: u32, diff --git a/assets/shaders/texture_binding_array.wgsl b/assets/shaders/texture_binding_array.wgsl index de7a4e1b96eca..17b94a74d3209 100644 --- a/assets/shaders/texture_binding_array.wgsl +++ b/assets/shaders/texture_binding_array.wgsl @@ -1,7 +1,7 @@ #import bevy_pbr::forward_io::VertexOutput -@group(2) @binding(0) var textures: binding_array>; -@group(2) @binding(1) var nearest_sampler: sampler; +@group(3) @binding(0) var textures: binding_array>; +@group(3) @binding(1) var nearest_sampler: sampler; // We can also have array of samplers // var samplers: binding_array; diff --git a/assets/shaders/water_material.wgsl b/assets/shaders/water_material.wgsl index 31d04b5f1142d..a8a9e03df4d16 100644 --- a/assets/shaders/water_material.wgsl +++ b/assets/shaders/water_material.wgsl @@ -23,9 +23,9 @@ struct WaterSettings { @group(0) @binding(1) var globals: Globals; -@group(2) @binding(100) var water_normals_texture: texture_2d; -@group(2) @binding(101) var water_normals_sampler: sampler; -@group(2) @binding(102) var water_settings: WaterSettings; +@group(3) @binding(100) var water_normals_texture: texture_2d; +@group(3) @binding(101) var water_normals_sampler: sampler; +@group(3) @binding(102) var water_settings: WaterSettings; // Samples a single octave of noise and returns the resulting normal. fn sample_noise_octave(uv: vec2, strength: f32) -> vec3 { diff --git a/crates/bevy_pbr/src/ssr/mod.rs b/crates/bevy_pbr/src/ssr/mod.rs index 9e5ad5a20ca70..87bad34a6bf06 100644 --- a/crates/bevy_pbr/src/ssr/mod.rs +++ b/crates/bevy_pbr/src/ssr/mod.rs @@ -23,21 +23,14 @@ use bevy_ecs::{ }; use bevy_image::BevyDefault as _; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; -use bevy_render::{ - extract_component::{ExtractComponent, ExtractComponentPlugin}, - render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner}, - render_resource::{ - binding_types, AddressMode, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, - CachedRenderPipelineId, ColorTargetState, ColorWrites, DynamicUniformBuffer, FilterMode, - FragmentState, Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, - RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, Shader, - ShaderStages, ShaderType, SpecializedRenderPipeline, SpecializedRenderPipelines, - TextureFormat, TextureSampleType, - }, - renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue}, - view::{ExtractedView, Msaa, ViewTarget, ViewUniformOffset}, - Render, RenderApp, RenderSystems, -}; +use bevy_render::{extract_component::{ExtractComponent, ExtractComponentPlugin}, render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner}, render_resource::{ + binding_types, AddressMode, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, + CachedRenderPipelineId, ColorTargetState, ColorWrites, DynamicUniformBuffer, FilterMode, + FragmentState, Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, + RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, Shader, + ShaderStages, ShaderType, SpecializedRenderPipeline, SpecializedRenderPipelines, + TextureFormat, TextureSampleType, +}, renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue}, view::{ExtractedView, Msaa, ViewTarget, ViewUniformOffset}, EmptyBindGroup, Render, RenderApp, RenderSystems}; use bevy_render::{load_shader_library, render_graph::RenderGraph}; use bevy_utils::{once, prelude::default}; use tracing::info; @@ -154,6 +147,7 @@ pub struct ScreenSpaceReflectionsPipeline { depth_linear_sampler: Sampler, depth_nearest_sampler: Sampler, bind_group_layout: BindGroupLayout, + empty_layout: BindGroupLayout, binding_arrays_are_usable: bool, shader: Handle, } @@ -332,9 +326,10 @@ impl ViewNode for ScreenSpaceReflectionsNode { **view_environment_map_offset, ], ); + render_pass.set_bind_group(1, &view_bind_group.value_binding_array, &[]); // Perform the SSR render pass. - render_pass.set_bind_group(1, &ssr_bind_group, &[]); + render_pass.set_bind_group(2, &ssr_bind_group, &[]); render_pass.draw(0..3, 0..1); Ok(()) @@ -344,6 +339,7 @@ impl ViewNode for ScreenSpaceReflectionsNode { impl FromWorld for ScreenSpaceReflectionsPipeline { fn from_world(world: &mut World) -> Self { let mesh_view_layouts = world.resource::().clone(); + let empty_layout = world.resource::().layout.clone(); let render_device = world.resource::(); let render_adapter = world.resource::(); @@ -392,6 +388,7 @@ impl FromWorld for ScreenSpaceReflectionsPipeline { Self { mesh_view_layouts, + empty_layout, color_sampler, depth_linear_sampler, depth_nearest_sampler, diff --git a/crates/bevy_pbr/src/ssr/ssr.wgsl b/crates/bevy_pbr/src/ssr/ssr.wgsl index 3dddfa1ba3bda..d646ac69febf9 100644 --- a/crates/bevy_pbr/src/ssr/ssr.wgsl +++ b/crates/bevy_pbr/src/ssr/ssr.wgsl @@ -36,10 +36,10 @@ #endif // The texture representing the color framebuffer. -@group(1) @binding(0) var color_texture: texture_2d; +@group(2) @binding(0) var color_texture: texture_2d; // The sampler that lets us sample from the color framebuffer. -@group(1) @binding(1) var color_sampler: sampler; +@group(2) @binding(1) var color_sampler: sampler; // Group 1, bindings 2 and 3 are in `raymarch.wgsl`. diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index aa1e2da676082..6f8ee8aa471f0 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -499,7 +499,8 @@ impl Plugin for RenderPlugin { .insert_resource(device) .insert_resource(queue) .insert_resource(render_adapter) - .insert_resource(adapter_info); + .insert_resource(adapter_info) + .init_resource::(); } } } @@ -631,3 +632,20 @@ pub fn get_mali_driver_version(adapter: &RenderAdapter) -> Option { None } + + +/// An empty bind group that can be used as a placeholder. +#[derive(Resource)] +pub struct EmptyBindGroup { + pub layout: render_resource::BindGroupLayout, + pub binding: render_resource::BindGroup, +} + +impl FromWorld for EmptyBindGroup { + fn from_world(world: &mut World) -> Self { + let device = world.resource::(); + let layout = device.create_bind_group_layout("empty_bind_group_layout", &[]); + let binding = device.create_bind_group("empty_bind_group", &layout, &[]); + EmptyBindGroup { layout, binding } + } +} From 776b471d831438e2de54f633301660d2db5d6f40 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 19 Jun 2025 22:32:29 -0700 Subject: [PATCH 05/37] Clean up and add empty bind group. --- crates/bevy_gizmos/src/line_joints.wgsl | 2 +- crates/bevy_gizmos/src/pipeline_3d.rs | 20 +++---- .../src/deferred/deferred_lighting.wgsl | 2 +- crates/bevy_pbr/src/deferred/mod.rs | 25 ++++---- crates/bevy_pbr/src/material.rs | 3 +- .../src/meshlet/material_pipeline_prepare.rs | 14 +++-- .../src/meshlet/material_shade_nodes.rs | 2 +- .../src/meshlet/meshlet_bindings.wgsl | 18 +++--- crates/bevy_pbr/src/prepass/mod.rs | 14 ++--- crates/bevy_pbr/src/render/mesh.rs | 58 ++++++++++++++++-- .../bevy_pbr/src/render/mesh_view_bindings.rs | 60 +++++++++++-------- crates/bevy_pbr/src/ssr/mod.rs | 41 +++++++------ crates/bevy_pbr/src/ssr/raymarch.wgsl | 4 +- crates/bevy_pbr/src/volumetric_fog/render.rs | 16 +++-- crates/bevy_pbr/src/wireframe.rs | 6 +- crates/bevy_render/Cargo.toml | 4 +- .../bevy_render/src/diagnostic/tracy_gpu.rs | 8 ++- crates/bevy_render/src/lib.rs | 20 +------ crates/bevy_render/src/render_phase/draw.rs | 6 +- crates/bevy_render/src/render_resource/mod.rs | 20 +++---- .../bevy_render/src/render_resource/shader.rs | 2 + crates/bevy_solari/src/lib.rs | 2 +- examples/app/headless_renderer.rs | 10 ++-- examples/shader/custom_render_phase.rs | 19 +++--- examples/shader/custom_shader_instancing.rs | 4 +- examples/shader/specialized_mesh_pipeline.rs | 20 ++++--- 26 files changed, 234 insertions(+), 166 deletions(-) diff --git a/crates/bevy_gizmos/src/line_joints.wgsl b/crates/bevy_gizmos/src/line_joints.wgsl index 3936578ee8379..cbbf152c02c59 100644 --- a/crates/bevy_gizmos/src/line_joints.wgsl +++ b/crates/bevy_gizmos/src/line_joints.wgsl @@ -14,7 +14,7 @@ struct LineGizmoUniform { #endif } -@group(2) @binding(0) var joints_gizmo: LineGizmoUniform; +@group(1) @binding(0) var joints_gizmo: LineGizmoUniform; struct VertexInput { @location(0) position_a: vec3, diff --git a/crates/bevy_gizmos/src/pipeline_3d.rs b/crates/bevy_gizmos/src/pipeline_3d.rs index 0b99248fd5a35..69854f7de4818 100644 --- a/crates/bevy_gizmos/src/pipeline_3d.rs +++ b/crates/bevy_gizmos/src/pipeline_3d.rs @@ -123,9 +123,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline { .mesh_pipeline .get_view_layout(key.view_key.into()) .clone(); - - let mut layout = view_layout.to_vec(); - layout.push(self.uniform_layout.clone()); + let layout = vec![view_layout.main_layout.clone(), self.uniform_layout.clone()]; let fragment_entry_point = match key.line_style { GizmoLineStyle::Solid => "fragment_solid", @@ -221,9 +219,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { .mesh_pipeline .get_view_layout(key.view_key.into()) .clone(); - - let mut layout = view_layout.to_vec(); - layout.push(self.uniform_layout.clone()); + let layout = vec![view_layout.main_layout.clone(), self.uniform_layout.clone()]; if key.joints == GizmoLineJoint::None { error!("There is no entry point for line joints with GizmoLineJoints::None. Please consider aborting the drawing process before reaching this stage."); @@ -275,20 +271,20 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline { type DrawLineGizmo3d = ( SetItemPipeline, - SetMeshViewBindGroup<0, 1>, - SetLineGizmoBindGroup<2>, + SetMeshViewBindGroup<0>, + SetLineGizmoBindGroup<1>, DrawLineGizmo, ); type DrawLineGizmo3dStrip = ( SetItemPipeline, - SetMeshViewBindGroup<0, 1>, - SetLineGizmoBindGroup<2>, + SetMeshViewBindGroup<0>, + SetLineGizmoBindGroup<1>, DrawLineGizmo, ); type DrawLineJointGizmo3d = ( SetItemPipeline, - SetMeshViewBindGroup<0, 1>, - SetLineGizmoBindGroup<2>, + SetMeshViewBindGroup<0>, + SetLineGizmoBindGroup<1>, DrawLineJointGizmo, ); diff --git a/crates/bevy_pbr/src/deferred/deferred_lighting.wgsl b/crates/bevy_pbr/src/deferred/deferred_lighting.wgsl index 843ed2bbf69ab..7c14eea4baf99 100644 --- a/crates/bevy_pbr/src/deferred/deferred_lighting.wgsl +++ b/crates/bevy_pbr/src/deferred/deferred_lighting.wgsl @@ -29,7 +29,7 @@ struct PbrDeferredLightingDepthId { _webgl2_padding_2: f32, #endif } -@group(1) @binding(0) +@group(2) @binding(0) var depth_id: PbrDeferredLightingDepthId; @vertex diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index f04ce41d5fabb..b8f3a660c0eed 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -184,9 +184,9 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { return Ok(()); }; - let bind_group_1 = render_context.render_device().create_bind_group( - "deferred_lighting_layout_group_1", - &deferred_lighting_layout.bind_group_layout_1, + let bind_group_2 = render_context.render_device().create_bind_group( + "deferred_lighting_layout_group_2", + &deferred_lighting_layout.bind_group_layout_2, &BindGroupEntries::single(deferred_lighting_pass_id_binding), ); @@ -208,7 +208,7 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { render_pass.set_render_pipeline(pipeline); render_pass.set_bind_group( 0, - &mesh_view_bind_group.value, + &mesh_view_bind_group.main, &[ view_uniform_offset.offset, view_lights_offset.offset, @@ -218,7 +218,8 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { **view_environment_map_offset, ], ); - render_pass.set_bind_group(1, &bind_group_1, &[]); + render_pass.set_bind_group(1, &mesh_view_bind_group.binding_array, &[]); + render_pass.set_bind_group(2, &bind_group_2, &[]); render_pass.draw(0..3, 0..1); Ok(()) @@ -228,7 +229,7 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode { #[derive(Resource)] pub struct DeferredLightingLayout { mesh_pipeline: MeshPipeline, - bind_group_layout_1: BindGroupLayout, + bind_group_layout_2: BindGroupLayout, deferred_lighting_shader: Handle, } @@ -346,12 +347,14 @@ impl SpecializedRenderPipeline for DeferredLightingLayout { #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into()); - let mut layout = self.mesh_pipeline.get_view_layout(key.into()).to_vec(); - layout.push(self.bind_group_layout_1.clone()); - + let layout = self.mesh_pipeline.get_view_layout(key.into()); RenderPipelineDescriptor { label: Some("deferred_lighting_pipeline".into()), - layout, + layout: vec![ + layout.main_layout.clone(), + layout.binding_array_layout.clone(), + self.bind_group_layout_2.clone(), + ], vertex: VertexState { shader: self.deferred_lighting_shader.clone(), shader_defs: shader_defs.clone(), @@ -408,7 +411,7 @@ impl FromWorld for DeferredLightingLayout { ); Self { mesh_pipeline: world.resource::().clone(), - bind_group_layout_1: layout, + bind_group_layout_2: layout, deferred_lighting_shader: load_embedded_asset!(world, "deferred_lighting.wgsl"), } } diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 2b25b1b9be660..fc9eea9582dea 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -543,7 +543,8 @@ impl FromWorld for MaterialPipeline { type DrawMaterial = ( SetItemPipeline, - SetMeshViewBindGroup<0, 1>, + SetMeshViewBindGroup<0>, + SetMeshViewBindingArrayBindGroup<1>, SetMeshBindGroup<2>, SetMaterialBindGroup, DrawMesh, diff --git a/crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs b/crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs index 57762bfc8a609..90d35d05142a2 100644 --- a/crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs +++ b/crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs @@ -186,13 +186,17 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass( let mut shader_defs = material_fragment.shader_defs; shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into()); + let layout = mesh_pipeline.get_view_layout(view_key.into()); + let layout = vec![ + layout.main_layout.clone(), + layout.binding_array_layout.clone(), + resource_manager.material_shade_bind_group_layout.clone(), + material_pipeline.material_layout.clone(), + ]; + let pipeline_descriptor = RenderPipelineDescriptor { label: material_pipeline_descriptor.label, - layout: vec![ - mesh_pipeline.get_view_layout(view_key.into()).clone(), - resource_manager.material_shade_bind_group_layout.clone(), - material_pipeline.material_layout.clone(), - ], + layout, push_constant_ranges: vec![], vertex: VertexState { shader: MESHLET_MESH_MATERIAL_SHADER_HANDLE, diff --git a/crates/bevy_pbr/src/meshlet/material_shade_nodes.rs b/crates/bevy_pbr/src/meshlet/material_shade_nodes.rs index 9c2d432d8856a..cb05de38fb822 100644 --- a/crates/bevy_pbr/src/meshlet/material_shade_nodes.rs +++ b/crates/bevy_pbr/src/meshlet/material_shade_nodes.rs @@ -106,7 +106,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode { render_pass.set_bind_group( 0, - &mesh_view_bind_group.value, + &mesh_view_bind_group.main, &[ view_uniform_offset.offset, view_lights_offset.offset, diff --git a/crates/bevy_pbr/src/meshlet/meshlet_bindings.wgsl b/crates/bevy_pbr/src/meshlet/meshlet_bindings.wgsl index e179e78b7ae5e..63e92f15e6feb 100644 --- a/crates/bevy_pbr/src/meshlet/meshlet_bindings.wgsl +++ b/crates/bevy_pbr/src/meshlet/meshlet_bindings.wgsl @@ -149,15 +149,15 @@ fn get_meshlet_vertex_position(meshlet: ptr, vertex_id: u32) #endif #ifdef MESHLET_MESH_MATERIAL_PASS -@group(1) @binding(0) var meshlet_visibility_buffer: texture_storage_2d; -@group(1) @binding(1) var meshlet_cluster_meshlet_ids: array; // Per cluster -@group(1) @binding(2) var meshlets: array; // Per meshlet -@group(1) @binding(3) var meshlet_indices: array; // Many per meshlet -@group(1) @binding(4) var meshlet_vertex_positions: array; // Many per meshlet -@group(1) @binding(5) var meshlet_vertex_normals: array; // Many per meshlet -@group(1) @binding(6) var meshlet_vertex_uvs: array>; // Many per meshlet -@group(1) @binding(7) var meshlet_cluster_instance_ids: array; // Per cluster -@group(1) @binding(8) var meshlet_instance_uniforms: array; // Per entity instance +@group(2) @binding(0) var meshlet_visibility_buffer: texture_storage_2d; +@group(2) @binding(1) var meshlet_cluster_meshlet_ids: array; // Per cluster +@group(2) @binding(2) var meshlets: array; // Per meshlet +@group(2) @binding(3) var meshlet_indices: array; // Many per meshlet +@group(2) @binding(4) var meshlet_vertex_positions: array; // Many per meshlet +@group(2) @binding(5) var meshlet_vertex_normals: array; // Many per meshlet +@group(2) @binding(6) var meshlet_vertex_uvs: array>; // Many per meshlet +@group(2) @binding(7) var meshlet_cluster_instance_ids: array; // Per cluster +@group(2) @binding(8) var meshlet_instance_uniforms: array; // Per entity instance // TODO: Load only twice, instead of 3x in cases where you load 3 indices per thread? fn get_meshlet_vertex_id(index_id: u32) -> u32 { diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 4c610d8e53081..9b407b27b1ba1 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -7,7 +7,8 @@ use crate::{ DrawMesh, EntitySpecializationTicks, Material, MaterialPipeline, MaterialPipelineKey, MeshLayouts, MeshPipeline, MeshPipelineKey, OpaqueRendererMethod, PreparedMaterial, RenderLightmaps, RenderMaterialInstances, RenderMeshInstanceFlags, RenderMeshInstances, - RenderPhaseType, SetMaterialBindGroup, SetMeshBindGroup, ShadowView, StandardMaterial, + RenderPhaseType, SetMaterialBindGroup, SetMeshBindGroup, SetMeshViewEmptyBindGroup, ShadowView, + StandardMaterial, }; use bevy_app::{App, Plugin, PreUpdate}; use bevy_render::{ @@ -1264,10 +1265,8 @@ pub fn queue_prepass_material_meshes( } } -pub struct SetPrepassViewBindGroup; -impl RenderCommand

- for SetPrepassViewBindGroup -{ +pub struct SetPrepassViewBindGroup; +impl RenderCommand

for SetPrepassViewBindGroup { type Param = SRes; type ViewQuery = ( Read, @@ -1309,15 +1308,14 @@ impl RenderCommand

); } } - pass.set_bind_group(J, &prepass_view_bind_group.empty_bind_group, &[]); - RenderCommandResult::Success } } pub type DrawPrepass = ( SetItemPipeline, - SetPrepassViewBindGroup<0, 1>, + SetPrepassViewBindGroup<0>, + SetMeshViewEmptyBindGroup<1>, SetMeshBindGroup<2>, SetMaterialBindGroup, DrawMesh, diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 8700591596670..50d7e98a48011 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1864,7 +1864,10 @@ impl MeshPipeline { } } - pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &[BindGroupLayout; 2] { + pub fn get_view_layout( + &self, + layout_key: MeshPipelineViewLayoutKey, + ) -> &MeshPipelineViewLayout { self.view_layouts.get_view_layout(layout_key) } } @@ -2320,7 +2323,11 @@ impl SpecializedMeshPipeline for MeshPipeline { shader_defs.push("PBR_SPECULAR_TEXTURES_SUPPORTED".into()); } - let mut bind_group_layout = self.get_view_layout(key.into()).to_vec(); + let bind_group_layout = self.get_view_layout(key.into()); + let mut bind_group_layout = vec![ + bind_group_layout.main_layout.clone(), + bind_group_layout.binding_array_layout.clone(), + ]; if key.msaa_samples() > 1 { shader_defs.push("MULTISAMPLED".into()); @@ -2847,8 +2854,8 @@ fn prepare_mesh_bind_groups_for_phase( groups } -pub struct SetMeshViewBindGroup; -impl RenderCommand

for SetMeshViewBindGroup { +pub struct SetMeshViewBindGroup; +impl RenderCommand

for SetMeshViewBindGroup { type Param = (); type ViewQuery = ( Read, @@ -2890,8 +2897,47 @@ impl RenderCommand

for SetMeshV if let Some(layers_count_offset) = maybe_oit_layers_count_offset { offsets.push(layers_count_offset.offset); } - pass.set_bind_group(I, &mesh_view_bind_group.value, &offsets); - pass.set_bind_group(J, &mesh_view_bind_group.value_binding_array, &[]); + pass.set_bind_group(I, &mesh_view_bind_group.main, &offsets); + + RenderCommandResult::Success + } +} + +pub struct SetMeshViewBindingArrayBindGroup; +impl RenderCommand

for SetMeshViewBindingArrayBindGroup { + type Param = (); + type ViewQuery = (Read,); + type ItemQuery = (); + + #[inline] + fn render<'w>( + _item: &P, + (mesh_view_bind_group,): ROQueryItem<'w, '_, Self::ViewQuery>, + _entity: Option<()>, + _: SystemParamItem<'w, '_, Self::Param>, + pass: &mut TrackedRenderPass<'w>, + ) -> RenderCommandResult { + pass.set_bind_group(I, &mesh_view_bind_group.binding_array, &[]); + + RenderCommandResult::Success + } +} + +pub struct SetMeshViewEmptyBindGroup; +impl RenderCommand

for SetMeshViewEmptyBindGroup { + type Param = (); + type ViewQuery = (Read,); + type ItemQuery = (); + + #[inline] + fn render<'w>( + _item: &P, + (mesh_view_bind_group,): ROQueryItem<'w, '_, Self::ViewQuery>, + _entity: Option<()>, + _: SystemParamItem<'w, '_, Self::Param>, + pass: &mut TrackedRenderPass<'w>, + ) -> RenderCommandResult { + pass.set_bind_group(I, &mesh_view_bind_group.empty, &[]); RenderCommandResult::Success } diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.rs b/crates/bevy_pbr/src/render/mesh_view_bindings.rs index 86521d742c1fd..50bbcd20fa9b6 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.rs @@ -59,7 +59,9 @@ use {crate::MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES, bevy_utils::once, traci #[derive(Clone)] pub struct MeshPipelineViewLayout { - pub bind_group_layout: [BindGroupLayout; 2], + pub main_layout: BindGroupLayout, + pub binding_array_layout: BindGroupLayout, + pub empty_layout: BindGroupLayout, #[cfg(debug_assertions)] pub texture_count: usize, @@ -444,13 +446,14 @@ impl FromWorld for MeshPipelineViewLayouts { .count(); MeshPipelineViewLayout { - bind_group_layout: [ - render_device.create_bind_group_layout(key.label().as_str(), &entries[0]), - render_device.create_bind_group_layout( - format!("{}_binding_array", key.label()).as_str(), - &entries[1], - ), - ], + main_layout: render_device + .create_bind_group_layout(key.label().as_str(), &entries[0]), + binding_array_layout: render_device.create_bind_group_layout( + format!("{}_binding_array", key.label()).as_str(), + &entries[1], + ), + empty_layout: render_device + .create_bind_group_layout(format!("{}_empty", key.label()).as_str(), &[]), #[cfg(debug_assertions)] texture_count, } @@ -459,7 +462,10 @@ impl FromWorld for MeshPipelineViewLayouts { } impl MeshPipelineViewLayouts { - pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &[BindGroupLayout; 2] { + pub fn get_view_layout( + &self, + layout_key: MeshPipelineViewLayoutKey, + ) -> &MeshPipelineViewLayout { let index = layout_key.bits() as usize; let layout = &self[index]; @@ -469,7 +475,7 @@ impl MeshPipelineViewLayouts { once!(warn!("Too many textures in mesh pipeline view layout, this might cause us to hit `wgpu::Limits::max_sampled_textures_per_shader_stage` in some environments.")); } - &layout.bind_group_layout + layout } } @@ -495,19 +501,19 @@ pub fn generate_view_layouts( let texture_count: usize = entries .iter() .flat_map(|e| { - e.into_iter() + e.iter() .filter(|entry| matches!(entry.ty, BindingType::Texture { .. })) }) .count(); MeshPipelineViewLayout { - bind_group_layout: [ - render_device.create_bind_group_layout(key.label().as_str(), &entries[0]), - render_device.create_bind_group_layout( - format!("{}_binding_array", key.label()).as_str(), - &entries[1], - ), - ], + main_layout: render_device.create_bind_group_layout(key.label().as_str(), &entries[0]), + binding_array_layout: render_device.create_bind_group_layout( + format!("{}_binding_array", key.label()).as_str(), + &entries[1], + ), + empty_layout: render_device + .create_bind_group_layout(format!("{}_empty", key.label()).as_str(), &[]), #[cfg(debug_assertions)] texture_count, } @@ -516,8 +522,9 @@ pub fn generate_view_layouts( #[derive(Component)] pub struct MeshViewBindGroup { - pub value: BindGroup, - pub value_binding_array: BindGroup, + pub main: BindGroup, + pub binding_array: BindGroup, + pub empty: BindGroup, } pub fn prepare_mesh_view_bind_groups( @@ -779,16 +786,21 @@ pub fn prepare_mesh_view_bind_groups( } commands.entity(entity).insert(MeshViewBindGroup { - value: render_device.create_bind_group( + main: render_device.create_bind_group( "mesh_view_bind_group", - &layout[0], + &layout.main_layout, &entries, ), - value_binding_array: render_device.create_bind_group( + binding_array: render_device.create_bind_group( "mesh_view_bind_group_binding_array", - &layout[1], + &layout.binding_array_layout, &entries_binding_array, ), + empty: render_device.create_bind_group( + "mesh_view_bind_group_empty", + &layout.empty_layout, + &[], + ), }); } } diff --git a/crates/bevy_pbr/src/ssr/mod.rs b/crates/bevy_pbr/src/ssr/mod.rs index 8351ec572bf96..c57802a4ae5c4 100644 --- a/crates/bevy_pbr/src/ssr/mod.rs +++ b/crates/bevy_pbr/src/ssr/mod.rs @@ -23,14 +23,21 @@ use bevy_ecs::{ }; use bevy_image::BevyDefault as _; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; -use bevy_render::{extract_component::{ExtractComponent, ExtractComponentPlugin}, render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner}, render_resource::{ - binding_types, AddressMode, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, - CachedRenderPipelineId, ColorTargetState, ColorWrites, DynamicUniformBuffer, FilterMode, - FragmentState, Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, - RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, Shader, - ShaderStages, ShaderType, SpecializedRenderPipeline, SpecializedRenderPipelines, - TextureFormat, TextureSampleType, -}, renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue}, view::{ExtractedView, Msaa, ViewTarget, ViewUniformOffset}, EmptyBindGroup, Render, RenderApp, RenderSystems}; +use bevy_render::{ + extract_component::{ExtractComponent, ExtractComponentPlugin}, + render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner}, + render_resource::{ + binding_types, AddressMode, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, + CachedRenderPipelineId, ColorTargetState, ColorWrites, DynamicUniformBuffer, FilterMode, + FragmentState, Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, + RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, Shader, + ShaderStages, ShaderType, SpecializedRenderPipeline, SpecializedRenderPipelines, + TextureFormat, TextureSampleType, + }, + renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue}, + view::{ExtractedView, Msaa, ViewTarget, ViewUniformOffset}, + Render, RenderApp, RenderSystems, +}; use bevy_render::{load_shader_library, render_graph::RenderGraph}; use bevy_utils::{once, prelude::default}; use tracing::info; @@ -147,7 +154,6 @@ pub struct ScreenSpaceReflectionsPipeline { depth_linear_sampler: Sampler, depth_nearest_sampler: Sampler, bind_group_layout: BindGroupLayout, - empty_layout: BindGroupLayout, binding_arrays_are_usable: bool, shader: Handle, } @@ -316,7 +322,7 @@ impl ViewNode for ScreenSpaceReflectionsNode { render_pass.set_render_pipeline(render_pipeline); render_pass.set_bind_group( 0, - &view_bind_group.value, + &view_bind_group.main, &[ view_uniform_offset.offset, view_lights_offset.offset, @@ -326,7 +332,7 @@ impl ViewNode for ScreenSpaceReflectionsNode { **view_environment_map_offset, ], ); - render_pass.set_bind_group(1, &view_bind_group.value_binding_array, &[]); + render_pass.set_bind_group(1, &view_bind_group.binding_array, &[]); // Perform the SSR render pass. render_pass.set_bind_group(2, &ssr_bind_group, &[]); @@ -339,7 +345,6 @@ impl ViewNode for ScreenSpaceReflectionsNode { impl FromWorld for ScreenSpaceReflectionsPipeline { fn from_world(world: &mut World) -> Self { let mesh_view_layouts = world.resource::().clone(); - let empty_layout = world.resource::().layout.clone(); let render_device = world.resource::(); let render_adapter = world.resource::(); @@ -388,7 +393,6 @@ impl FromWorld for ScreenSpaceReflectionsPipeline { Self { mesh_view_layouts, - empty_layout, color_sampler, depth_linear_sampler, depth_nearest_sampler, @@ -512,11 +516,14 @@ impl SpecializedRenderPipeline for ScreenSpaceReflectionsPipeline { type Key = ScreenSpaceReflectionsPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let mut layout = self + let layout = self .mesh_view_layouts - .get_view_layout(key.mesh_pipeline_view_key) - .to_vec(); - layout.push(self.bind_group_layout.clone()); + .get_view_layout(key.mesh_pipeline_view_key); + let layout = vec![ + layout.main_layout.clone(), + layout.binding_array_layout.clone(), + self.bind_group_layout.clone(), + ]; let mut shader_defs = vec![ "DEPTH_PREPASS".into(), diff --git a/crates/bevy_pbr/src/ssr/raymarch.wgsl b/crates/bevy_pbr/src/ssr/raymarch.wgsl index e149edfbbc239..12140c91e3170 100644 --- a/crates/bevy_pbr/src/ssr/raymarch.wgsl +++ b/crates/bevy_pbr/src/ssr/raymarch.wgsl @@ -25,10 +25,10 @@ } // Allows us to sample from the depth buffer with bilinear filtering. -@group(1) @binding(2) var depth_linear_sampler: sampler; +@group(2) @binding(2) var depth_linear_sampler: sampler; // Allows us to sample from the depth buffer with nearest-neighbor filtering. -@group(1) @binding(3) var depth_nearest_sampler: sampler; +@group(2) @binding(3) var depth_nearest_sampler: sampler; // Main code diff --git a/crates/bevy_pbr/src/volumetric_fog/render.rs b/crates/bevy_pbr/src/volumetric_fog/render.rs index 526828fe7d6ae..a5cd8e56f3c1e 100644 --- a/crates/bevy_pbr/src/volumetric_fog/render.rs +++ b/crates/bevy_pbr/src/volumetric_fog/render.rs @@ -461,7 +461,7 @@ impl ViewNode for VolumetricFogNode { render_pass.set_pipeline(pipeline); render_pass.set_bind_group( 0, - &view_bind_group.value, + &view_bind_group.main, &[ view_uniform_offset.offset, view_lights_offset.offset, @@ -511,10 +511,6 @@ impl SpecializedRenderPipeline for VolumetricFogPipeline { type Key = VolumetricFogPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let mesh_view_layout = self - .mesh_view_layouts - .get_view_layout(key.mesh_pipeline_view_key); - // We always use hardware 2x2 filtering for sampling the shadow map; the // more accurate versions with percentage-closer filtering aren't worth // the overhead. @@ -559,11 +555,13 @@ impl SpecializedRenderPipeline for VolumetricFogPipeline { shader_defs.push("DENSITY_TEXTURE".into()); } - let mut layout = self + let layout = self .mesh_view_layouts - .get_view_layout(key.mesh_pipeline_view_key) - .to_vec(); - layout.push(volumetric_view_bind_group_layout.clone()); + .get_view_layout(key.mesh_pipeline_view_key); + let layout = vec![ + layout.main_layout.clone(), + volumetric_view_bind_group_layout.clone(), + ]; RenderPipelineDescriptor { label: Some("volumetric lighting pipeline".into()), diff --git a/crates/bevy_pbr/src/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index 74cf3a4d5f6c8..b830a3a16e3d0 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -1,6 +1,7 @@ use crate::{ DrawMesh, MeshPipeline, MeshPipelineKey, RenderMeshInstanceFlags, RenderMeshInstances, - SetMeshBindGroup, SetMeshViewBindGroup, ViewKeyCache, ViewSpecializationTicks, + SetMeshBindGroup, SetMeshViewBindGroup, SetMeshViewBindingArrayBindGroup, ViewKeyCache, + ViewSpecializationTicks, }; use bevy_app::{App, Plugin, PostUpdate, Startup, Update}; use bevy_asset::{ @@ -317,7 +318,8 @@ impl RenderCommand

for SetWireframe3dPushConstants { pub type DrawWireframe3d = ( SetItemPipeline, - SetMeshViewBindGroup<0, 1>, + SetMeshViewBindGroup<0>, + SetMeshViewBindingArrayBindGroup<1>, SetMeshBindGroup<2>, SetWireframe3dPushConstants, DrawMesh, diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index b2c05a7bf5a79..ca5c471774f58 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -119,7 +119,7 @@ wesl = { version = "0.1.2", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # Omit the `glsl` feature in non-WebAssembly by default. -naga_oil = { path = "../../../naga_oil", default-features = false, features = [ +naga_oil = { git = "https://github.com/bevyengine/naga_oil", default-features = false, features = [ "test_shader", ] } @@ -127,7 +127,7 @@ naga_oil = { path = "../../../naga_oil", default-features = false, features = [ proptest = "1" [target.'cfg(target_arch = "wasm32")'.dependencies] -naga_oil = { path = "../../../naga_oil" } +naga_oil = { git = "https://github.com/bevyengine/naga_oil" } js-sys = "0.3" web-sys = { version = "0.3.67", features = [ 'Blob', diff --git a/crates/bevy_render/src/diagnostic/tracy_gpu.rs b/crates/bevy_render/src/diagnostic/tracy_gpu.rs index c059b8baa5d00..7a66db4ea6da4 100644 --- a/crates/bevy_render/src/diagnostic/tracy_gpu.rs +++ b/crates/bevy_render/src/diagnostic/tracy_gpu.rs @@ -1,7 +1,7 @@ use crate::renderer::{RenderAdapterInfo, RenderDevice, RenderQueue}; use tracy_client::{Client, GpuContext, GpuContextType}; use wgpu::{ - Backend, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Maintain, MapMode, + Backend, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, MapMode, PollType, QuerySetDescriptor, QueryType, QUERY_SIZE, }; @@ -14,7 +14,7 @@ pub fn new_tracy_gpu_context( Backend::Vulkan => GpuContextType::Vulkan, Backend::Dx12 => GpuContextType::Direct3D12, Backend::Gl => GpuContextType::OpenGL, - Backend::Metal | Backend::BrowserWebGpu | Backend::Empty => GpuContextType::Invalid, + Backend::Metal | Backend::BrowserWebGpu | Backend::Noop => GpuContextType::Invalid, }; let tracy_client = Client::running().unwrap(); @@ -60,7 +60,9 @@ fn initial_timestamp(device: &RenderDevice, queue: &RenderQueue) -> i64 { queue.submit([timestamp_encoder.finish(), copy_encoder.finish()]); map_buffer.slice(..).map_async(MapMode::Read, |_| ()); - device.poll(Maintain::Wait); + device + .poll(PollType::Wait) + .expect("Failed to poll device for map async"); let view = map_buffer.slice(..).get_mapped_range(); i64::from_le_bytes((*view).try_into().unwrap()) diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 6f8ee8aa471f0..aa1e2da676082 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -499,8 +499,7 @@ impl Plugin for RenderPlugin { .insert_resource(device) .insert_resource(queue) .insert_resource(render_adapter) - .insert_resource(adapter_info) - .init_resource::(); + .insert_resource(adapter_info); } } } @@ -632,20 +631,3 @@ pub fn get_mali_driver_version(adapter: &RenderAdapter) -> Option { None } - - -/// An empty bind group that can be used as a placeholder. -#[derive(Resource)] -pub struct EmptyBindGroup { - pub layout: render_resource::BindGroupLayout, - pub binding: render_resource::BindGroup, -} - -impl FromWorld for EmptyBindGroup { - fn from_world(world: &mut World) -> Self { - let device = world.resource::(); - let layout = device.create_bind_group_layout("empty_bind_group_layout", &[]); - let binding = device.create_bind_group("empty_bind_group", &layout, &[]); - EmptyBindGroup { layout, binding } - } -} diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index 02b7de48652eb..39c6a074e6f57 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -167,13 +167,15 @@ impl DrawFunctions

{ /// /// ``` /// # use bevy_render::render_phase::SetItemPipeline; -/// # struct SetMeshViewBindGroup; +/// # struct SetMeshViewBindGroup; +/// # struct SetMeshViewBindingArrayBindGroup; /// # struct SetMeshBindGroup; /// # struct SetMaterialBindGroup(std::marker::PhantomData); /// # struct DrawMesh; /// pub type DrawMaterial = ( /// SetItemPipeline, -/// SetMeshViewBindGroup<0, 1>, +/// SetMeshViewBindGroup<0>, +/// SetMeshViewBindingArrayBindGroup<1>, /// SetMeshBindGroup<2>, /// SetMaterialBindGroup, /// DrawMesh, diff --git a/crates/bevy_render/src/render_resource/mod.rs b/crates/bevy_render/src/render_resource/mod.rs index b40e6273294a1..09be66e840b11 100644 --- a/crates/bevy_render/src/render_resource/mod.rs +++ b/crates/bevy_render/src/render_resource/mod.rs @@ -51,16 +51,16 @@ pub use wgpu::{ Extent3d, Face, Features as WgpuFeatures, FilterMode, FragmentState as RawFragmentState, FrontFace, ImageSubresourceRange, IndexFormat, Limits as WgpuLimits, LoadOp, MapMode, MultisampleState, Operations, Origin3d, PipelineCompilationOptions, PipelineLayout, - PipelineLayoutDescriptor, PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange, - RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor, - RenderPipelineDescriptor as RawRenderPipelineDescriptor, Sampler as WgpuSampler, - SamplerBindingType, SamplerBindingType as WgpuSamplerBindingType, SamplerDescriptor, - ShaderModule, ShaderModuleDescriptor, ShaderSource, ShaderStages, StencilFaceState, - StencilOperation, StencilState, StorageTextureAccess, StoreOp, TexelCopyBufferInfo, - TexelCopyBufferLayout, TexelCopyTextureInfo, TextureAspect, TextureDescriptor, - TextureDimension, TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, - TextureSampleType, TextureUsages, TextureView as WgpuTextureView, TextureViewDescriptor, - TextureViewDimension, Tlas, TlasInstance, TlasPackage, VertexAttribute, + PipelineLayoutDescriptor, PollType, PolygonMode, PrimitiveState, PrimitiveTopology, + PushConstantRange, RenderPassColorAttachment, RenderPassDepthStencilAttachment, + RenderPassDescriptor, RenderPipelineDescriptor as RawRenderPipelineDescriptor, + Sampler as WgpuSampler, SamplerBindingType, SamplerBindingType as WgpuSamplerBindingType, + SamplerDescriptor, ShaderModule, ShaderModuleDescriptor, ShaderSource, ShaderStages, + StencilFaceState, StencilOperation, StencilState, StorageTextureAccess, StoreOp, + TexelCopyBufferInfo, TexelCopyBufferLayout, TexelCopyTextureInfo, TextureAspect, + TextureDescriptor, TextureDimension, TextureFormat, TextureFormatFeatureFlags, + TextureFormatFeatures, TextureSampleType, TextureUsages, TextureView as WgpuTextureView, + TextureViewDescriptor, TextureViewDimension, Tlas, TlasInstance, TlasPackage, VertexAttribute, VertexBufferLayout as RawVertexBufferLayout, VertexFormat, VertexState as RawVertexState, VertexStepMode, COPY_BUFFER_ALIGNMENT, }; diff --git a/crates/bevy_render/src/render_resource/shader.rs b/crates/bevy_render/src/render_resource/shader.rs index ff8430b951f63..1be9fd7427568 100644 --- a/crates/bevy_render/src/render_resource/shader.rs +++ b/crates/bevy_render/src/render_resource/shader.rs @@ -301,6 +301,8 @@ impl From<&Source> for naga_oil::compose::ShaderType { naga::ShaderStage::Vertex => naga_oil::compose::ShaderType::GlslVertex, naga::ShaderStage::Fragment => naga_oil::compose::ShaderType::GlslFragment, naga::ShaderStage::Compute => panic!("glsl compute not yet implemented"), + naga::ShaderStage::Task => panic!("task shaders not yet implemented"), + naga::ShaderStage::Mesh => panic!("mesh shaders not yet implemented"), }, #[cfg(all(not(feature = "shader_format_glsl"), not(target_arch = "wasm32")))] Source::Glsl(_, _) => panic!( diff --git a/crates/bevy_solari/src/lib.rs b/crates/bevy_solari/src/lib.rs index 022f44b5c5aee..eb5a7005a60a3 100644 --- a/crates/bevy_solari/src/lib.rs +++ b/crates/bevy_solari/src/lib.rs @@ -45,7 +45,7 @@ impl SolariPlugin { | WgpuFeatures::EXPERIMENTAL_RAY_QUERY | WgpuFeatures::BUFFER_BINDING_ARRAY | WgpuFeatures::TEXTURE_BINDING_ARRAY - | WgpuFeatures::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING + | WgpuFeatures::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING | WgpuFeatures::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING | WgpuFeatures::PARTIALLY_BOUND_BINDING_ARRAY } diff --git a/examples/app/headless_renderer.rs b/examples/app/headless_renderer.rs index 2038c85a29ab7..8034b931695c9 100644 --- a/examples/app/headless_renderer.rs +++ b/examples/app/headless_renderer.rs @@ -22,8 +22,8 @@ use bevy::{ render_asset::{RenderAssetUsages, RenderAssets}, render_graph::{self, NodeRunError, RenderGraph, RenderGraphContext, RenderLabel}, render_resource::{ - Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, Maintain, - MapMode, TexelCopyBufferInfo, TexelCopyBufferLayout, TextureDimension, TextureFormat, + Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, MapMode, + TexelCopyBufferInfo, TexelCopyBufferLayout, TextureDimension, TextureFormat, TextureUsages, }, renderer::{RenderContext, RenderDevice, RenderQueue}, @@ -31,6 +31,7 @@ use bevy::{ }, winit::WinitPlugin, }; +use bevy_render::render_resource::PollType; use crossbeam_channel::{Receiver, Sender}; use std::{ ops::{Deref, DerefMut}, @@ -41,7 +42,6 @@ use std::{ }, time::Duration, }; - // To communicate between the main world and the render world we need a channel. // Since the main world and render world run in parallel, there will always be a frame of latency // between the data sent from the render world and the data received in the main world @@ -460,7 +460,9 @@ fn receive_image_from_buffer( // `Maintain::Wait` will cause the thread to wait on native but not on WebGpu. // This blocks until the gpu is done executing everything - render_device.poll(Maintain::wait()).panic_on_timeout(); + render_device + .poll(PollType::Wait) + .expect("Failed to poll device for map async"); // This blocks until the buffer is mapped r.recv().expect("Failed to receive the map_async message"); diff --git a/examples/shader/custom_render_phase.rs b/examples/shader/custom_render_phase.rs index e985a8f784e96..129136c396834 100644 --- a/examples/shader/custom_render_phase.rs +++ b/examples/shader/custom_render_phase.rs @@ -12,6 +12,7 @@ use std::ops::Range; +use bevy::pbr::SetMeshViewEmptyBindGroup; use bevy::{ core_pipeline::core_3d::graph::{Core3d, Node3d}, ecs::{ @@ -192,17 +193,19 @@ impl SpecializedMeshPipeline for StencilPipeline { } // This will automatically generate the correct `VertexBufferLayout` based on the vertex attributes let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?; - + let view_layout = self + .mesh_pipeline + .get_view_layout(MeshPipelineViewLayoutKey::from(key)); Ok(RenderPipelineDescriptor { label: Some("Specialized Mesh Pipeline".into()), // We want to reuse the data from bevy so we use the same bind groups as the default // mesh pipeline layout: vec![ // Bind group 0 is the view uniform - self.mesh_pipeline - .get_view_layout(MeshPipelineViewLayoutKey::from(key)) - .clone(), - // Bind group 1 is the mesh uniform + view_layout.main_layout.clone(), + // Bind group 1 is empty + view_layout.empty_layout.clone(), + // Bind group 2 is the mesh uniform self.mesh_pipeline.mesh_layouts.model_only.clone(), ], push_constant_ranges: vec![], @@ -242,8 +245,10 @@ impl SpecializedMeshPipeline for StencilPipeline { type DrawMesh3dStencil = ( SetItemPipeline, // This will set the view bindings in group 0 - SetMeshViewBindGroup<0, 1>, - // This will set the mesh bindings in group 1 + SetMeshViewBindGroup<0>, + // This will set an empty bind group in group 1 + SetMeshViewEmptyBindGroup<1>, + // This will set the mesh bindings in group 2 SetMeshBindGroup<2>, // This will draw the mesh DrawMesh, diff --git a/examples/shader/custom_shader_instancing.rs b/examples/shader/custom_shader_instancing.rs index 368aadb49106f..358a2beac7039 100644 --- a/examples/shader/custom_shader_instancing.rs +++ b/examples/shader/custom_shader_instancing.rs @@ -7,6 +7,7 @@ //! implementation using bevy's low level rendering api. //! It's generally recommended to try the built-in instancing before going with this approach. +use bevy::pbr::SetMeshViewBindingArrayBindGroup; use bevy::{ core_pipeline::core_3d::Transparent3d, ecs::{ @@ -247,7 +248,8 @@ impl SpecializedMeshPipeline for CustomPipeline { type DrawCustom = ( SetItemPipeline, - SetMeshViewBindGroup<0, 1>, + SetMeshViewBindGroup<0>, + SetMeshViewBindingArrayBindGroup<1>, SetMeshBindGroup<2>, DrawMeshInstanced, ); diff --git a/examples/shader/specialized_mesh_pipeline.rs b/examples/shader/specialized_mesh_pipeline.rs index 8be91f918162d..bd19ff227add0 100644 --- a/examples/shader/specialized_mesh_pipeline.rs +++ b/examples/shader/specialized_mesh_pipeline.rs @@ -42,6 +42,7 @@ use bevy::{ Render, RenderApp, RenderSystems, }, }; +use bevy_internal::pbr::SetMeshViewEmptyBindGroup; const SHADER_ASSET_PATH: &str = "shaders/specialized_mesh_pipeline.wgsl"; @@ -152,8 +153,10 @@ type DrawSpecializedPipelineCommands = ( // Set the pipeline SetItemPipeline, // Set the view uniform at bind group 0 - SetMeshViewBindGroup<0, 1>, - // Set the mesh uniform at bind group 1 + SetMeshViewBindGroup<0>, + // Set an empty material bind group at bind group 1 + SetMeshViewEmptyBindGroup<1>, + // Set the mesh uniform at bind group 2 SetMeshBindGroup<2>, // Draw the mesh DrawMesh, @@ -209,16 +212,17 @@ impl SpecializedMeshPipeline for CustomMeshPipeline { // This will automatically generate the correct `VertexBufferLayout` based on the vertex attributes let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?; - let mut layout = self + let view_layout = self .mesh_pipeline - .get_view_layout(MeshPipelineViewLayoutKey::from(mesh_key)) - .clone() - .to_vec(); - layout.push(self.mesh_pipeline.mesh_layouts.model_only.clone()); + .get_view_layout(MeshPipelineViewLayoutKey::from(mesh_key)); Ok(RenderPipelineDescriptor { label: Some("Specialized Mesh Pipeline".into()), - layout, + layout: vec![ + view_layout.main_layout.clone(), + view_layout.empty_layout.clone(), + self.mesh_pipeline.mesh_layouts.model_only.clone(), + ], push_constant_ranges: vec![], vertex: VertexState { shader: self.shader_handle.clone(), From c3b4350c09d19b47b42ee520bd4957a8b930b1f9 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 19 Jun 2025 22:37:12 -0700 Subject: [PATCH 06/37] Ci. --- examples/app/headless_renderer.rs | 3 +-- examples/shader/specialized_mesh_pipeline.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/app/headless_renderer.rs b/examples/app/headless_renderer.rs index 8034b931695c9..5d027b2115580 100644 --- a/examples/app/headless_renderer.rs +++ b/examples/app/headless_renderer.rs @@ -23,7 +23,7 @@ use bevy::{ render_graph::{self, NodeRunError, RenderGraph, RenderGraphContext, RenderLabel}, render_resource::{ Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, MapMode, - TexelCopyBufferInfo, TexelCopyBufferLayout, TextureDimension, TextureFormat, + PollType, TexelCopyBufferInfo, TexelCopyBufferLayout, TextureDimension, TextureFormat, TextureUsages, }, renderer::{RenderContext, RenderDevice, RenderQueue}, @@ -31,7 +31,6 @@ use bevy::{ }, winit::WinitPlugin, }; -use bevy_render::render_resource::PollType; use crossbeam_channel::{Receiver, Sender}; use std::{ ops::{Deref, DerefMut}, diff --git a/examples/shader/specialized_mesh_pipeline.rs b/examples/shader/specialized_mesh_pipeline.rs index bd19ff227add0..1e1aa543ce2a5 100644 --- a/examples/shader/specialized_mesh_pipeline.rs +++ b/examples/shader/specialized_mesh_pipeline.rs @@ -12,7 +12,7 @@ use bevy::{ math::{vec3, vec4}, pbr::{ DrawMesh, MeshPipeline, MeshPipelineKey, MeshPipelineViewLayoutKey, RenderMeshInstances, - SetMeshBindGroup, SetMeshViewBindGroup, + SetMeshBindGroup, SetMeshViewBindGroup, SetMeshViewEmptyBindGroup, }, prelude::*, render::{ @@ -42,7 +42,6 @@ use bevy::{ Render, RenderApp, RenderSystems, }, }; -use bevy_internal::pbr::SetMeshViewEmptyBindGroup; const SHADER_ASSET_PATH: &str = "shaders/specialized_mesh_pipeline.wgsl"; From dddade56e3879ce681421042eb772c5850bc5587 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 19 Jun 2025 22:38:01 -0700 Subject: [PATCH 07/37] Bump codespan. --- crates/bevy_render/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index ca5c471774f58..44b7361a8b5aa 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -80,7 +80,7 @@ bevy_platform = { path = "../bevy_platform", version = "0.16.0-dev", default-fea image = { version = "0.25.2", default-features = false } # misc -codespan-reporting = "0.11.0" +codespan-reporting = "0.12.0" # `fragile-send-sync-non-atomic-wasm` feature means we can't use Wasm threads for rendering # It is enabled for now to avoid having to do a significant overhaul of the renderer just for wasm. # When the 'atomics' feature is enabled `fragile-send-sync-non-atomic` does nothing From b629a65d276e9fb7560fda6adab013ee79348e7b Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 19 Jun 2025 23:17:41 -0700 Subject: [PATCH 08/37] Add missing backends. --- crates/bevy_render/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 44b7361a8b5aa..0ef7594e1bbae 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -89,6 +89,8 @@ wgpu = { version = "25", default-features = false, features = [ "wgsl", "dx12", "metal", + "vulkan", + "gles", "naga-ir", "fragile-send-sync-non-atomic-wasm", ] } From a79f15a8f20f94bb064dc76de23b2e2b28475557 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 19 Jun 2025 23:19:56 -0700 Subject: [PATCH 09/37] Fix gizmos. --- crates/bevy_gizmos/src/lines.wgsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_gizmos/src/lines.wgsl b/crates/bevy_gizmos/src/lines.wgsl index d06ccfa20d3c1..1181e3f59cdb8 100644 --- a/crates/bevy_gizmos/src/lines.wgsl +++ b/crates/bevy_gizmos/src/lines.wgsl @@ -17,7 +17,7 @@ struct LineGizmoUniform { #endif } -@group(2) @binding(0) var line_gizmo: LineGizmoUniform; +@group(1) @binding(0) var line_gizmo: LineGizmoUniform; struct VertexInput { @location(0) position_a: vec3, From 9dde56163f4e13309697db7e5af6db547ce51b57 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 19 Jun 2025 23:27:25 -0700 Subject: [PATCH 10/37] Fix prepass. --- crates/bevy_pbr/src/prepass/mod.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 9b407b27b1ba1..8732f92e8277e 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -7,8 +7,7 @@ use crate::{ DrawMesh, EntitySpecializationTicks, Material, MaterialPipeline, MaterialPipelineKey, MeshLayouts, MeshPipeline, MeshPipelineKey, OpaqueRendererMethod, PreparedMaterial, RenderLightmaps, RenderMaterialInstances, RenderMeshInstanceFlags, RenderMeshInstances, - RenderPhaseType, SetMaterialBindGroup, SetMeshBindGroup, SetMeshViewEmptyBindGroup, ShadowView, - StandardMaterial, + RenderPhaseType, SetMaterialBindGroup, SetMeshBindGroup, ShadowView, StandardMaterial, }; use bevy_app::{App, Plugin, PreUpdate}; use bevy_render::{ @@ -1312,10 +1311,30 @@ impl RenderCommand

for SetPrepassViewBindGroup< } } +pub struct SetPrepassViewEmptyBindGroup; +impl RenderCommand

for SetPrepassViewEmptyBindGroup { + type Param = SRes; + type ViewQuery = (); + type ItemQuery = (); + + #[inline] + fn render<'w>( + _item: &P, + _view: (), + _entity: Option<()>, + prepass_view_bind_group: SystemParamItem<'w, '_, Self::Param>, + pass: &mut TrackedRenderPass<'w>, + ) -> RenderCommandResult { + let prepass_view_bind_group = prepass_view_bind_group.into_inner(); + pass.set_bind_group(I, &prepass_view_bind_group.empty_bind_group, &[]); + RenderCommandResult::Success + } +} + pub type DrawPrepass = ( SetItemPipeline, SetPrepassViewBindGroup<0>, - SetMeshViewEmptyBindGroup<1>, + SetPrepassViewEmptyBindGroup<1>, SetMeshBindGroup<2>, SetMaterialBindGroup, DrawMesh, From aab1cfb4c4afdc2d043ed2c3222ffe0de13dbab6 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 19 Jun 2025 23:43:58 -0700 Subject: [PATCH 11/37] Fix skinning. --- crates/bevy_pbr/src/render/skinning.wgsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_pbr/src/render/skinning.wgsl b/crates/bevy_pbr/src/render/skinning.wgsl index 1762a73887c94..6c4da0754ad8f 100644 --- a/crates/bevy_pbr/src/render/skinning.wgsl +++ b/crates/bevy_pbr/src/render/skinning.wgsl @@ -6,9 +6,9 @@ #ifdef SKINNED #ifdef SKINS_USE_UNIFORM_BUFFERS -@group(1) @binding(1) var joint_matrices: SkinnedMesh; +@group(2) @binding(1) var joint_matrices: SkinnedMesh; #else // SKINS_USE_UNIFORM_BUFFERS -@group(1) @binding(1) var joint_matrices: array>; +@group(2) @binding(1) var joint_matrices: array>; #endif // SKINS_USE_UNIFORM_BUFFERS // An array of matrices specifying the joint positions from the previous frame. @@ -18,9 +18,9 @@ // If this is the first frame, or we're otherwise prevented from using data from // the previous frame, this is simply the same as `joint_matrices` above. #ifdef SKINS_USE_UNIFORM_BUFFERS -@group(1) @binding(6) var prev_joint_matrices: SkinnedMesh; +@group(2) @binding(6) var prev_joint_matrices: SkinnedMesh; #else // SKINS_USE_UNIFORM_BUFFERS -@group(1) @binding(6) var prev_joint_matrices: array>; +@group(2) @binding(6) var prev_joint_matrices: array>; #endif // SKINS_USE_UNIFORM_BUFFERS fn skin_model( From 88cba3dee550525dda76591a497f802769fb081c Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 19 Jun 2025 23:56:08 -0700 Subject: [PATCH 12/37] Migration. --- release-content/migration-guides/wgpu_25.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 release-content/migration-guides/wgpu_25.md diff --git a/release-content/migration-guides/wgpu_25.md b/release-content/migration-guides/wgpu_25.md new file mode 100644 index 0000000000000..3e4c5e02d9326 --- /dev/null +++ b/release-content/migration-guides/wgpu_25.md @@ -0,0 +1,18 @@ +--- +title: `wgpu` 25 +pull_requests: [19563] +--- + +`wgpu` 25 introduces a number of breaking changes, most notably in the way Bevy is required to handle +uniforms with dynamic offsets which are used pervasively in the renderer. Dynamic offsets and uniforms +of any kind are no longer allowed to be used in the same bind group as binding arrays. As such, the +following changes to the default bind group numbering have been made in 3d: +- `@group(0)` view uniforms +- `@group(1)` view uniforms requiring binding arrays +- `@group(2)` mesh uniforms +- `@group(3)` material uniforms + +Most users who are not using mid-level render APIs will simply need to switch their material bind groups +from `@group(2)` to `@group(3)`. + +See the changelog [here](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v2500-2025-04-10). From 8ab8f276b4048c5ea98b59c16a3886093eba721f Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Fri, 20 Jun 2025 00:23:17 -0700 Subject: [PATCH 13/37] Markdown. --- release-content/migration-guides/wgpu_25.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/release-content/migration-guides/wgpu_25.md b/release-content/migration-guides/wgpu_25.md index 3e4c5e02d9326..2fc5e57eaa76e 100644 --- a/release-content/migration-guides/wgpu_25.md +++ b/release-content/migration-guides/wgpu_25.md @@ -5,14 +5,15 @@ pull_requests: [19563] `wgpu` 25 introduces a number of breaking changes, most notably in the way Bevy is required to handle uniforms with dynamic offsets which are used pervasively in the renderer. Dynamic offsets and uniforms -of any kind are no longer allowed to be used in the same bind group as binding arrays. As such, the +of any kind are no longer allowed to be used in the same bind group as binding arrays. As such, the following changes to the default bind group numbering have been made in 3d: + - `@group(0)` view uniforms - `@group(1)` view uniforms requiring binding arrays - `@group(2)` mesh uniforms -- `@group(3)` material uniforms +- `@group(3)` material uniforms Most users who are not using mid-level render APIs will simply need to switch their material bind groups -from `@group(2)` to `@group(3)`. +from `@group(2)` to `@group(3)`. See the changelog [here](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v2500-2025-04-10). From 56296bfa510abbc7e416b5f4b8d3d96fe6636d58 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Fri, 20 Jun 2025 00:24:16 -0700 Subject: [PATCH 14/37] Markdown. --- release-content/migration-guides/wgpu_25.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release-content/migration-guides/wgpu_25.md b/release-content/migration-guides/wgpu_25.md index 2fc5e57eaa76e..16415049b0156 100644 --- a/release-content/migration-guides/wgpu_25.md +++ b/release-content/migration-guides/wgpu_25.md @@ -1,6 +1,6 @@ --- -title: `wgpu` 25 -pull_requests: [19563] +title: `wgpu` 25 +pull_requests: [ 19563 ] --- `wgpu` 25 introduces a number of breaking changes, most notably in the way Bevy is required to handle From e869d43fbea7c1ff772232f63b7d1e8778cf28b2 Mon Sep 17 00:00:00 2001 From: charlotte Date: Fri, 20 Jun 2025 01:00:00 -0700 Subject: [PATCH 15/37] 5488 fixed upstream. --- crates/bevy_render/src/renderer/mod.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/bevy_render/src/renderer/mod.rs b/crates/bevy_render/src/renderer/mod.rs index 084e7cb0608b5..5df4967757749 100644 --- a/crates/bevy_render/src/renderer/mod.rs +++ b/crates/bevy_render/src/renderer/mod.rs @@ -180,12 +180,6 @@ pub async fn initialize_renderer( features.remove(wgpu::Features::MAPPABLE_PRIMARY_BUFFERS); } - // RAY_QUERY and RAY_TRACING_ACCELERATION STRUCTURE will sometimes cause DeviceLost failures on platforms - // that report them as supported: - // - features.remove(wgpu::Features::EXPERIMENTAL_RAY_QUERY); - features.remove(wgpu::Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE); - limits = adapter.limits(); } From 9b52a0b1dc4859069e05100fb360502a5538532c Mon Sep 17 00:00:00 2001 From: charlotte Date: Fri, 20 Jun 2025 15:14:07 -0700 Subject: [PATCH 16/37] Bindless resources 2->3 --- crates/bevy_render/src/bindless.wgsl | 18 +++++++++--------- .../src/render_resource/pipeline_cache.rs | 1 - 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/bevy_render/src/bindless.wgsl b/crates/bevy_render/src/bindless.wgsl index 05517a1746d29..717e9c1047c60 100644 --- a/crates/bevy_render/src/bindless.wgsl +++ b/crates/bevy_render/src/bindless.wgsl @@ -16,22 +16,22 @@ // Binding 0 is the bindless index table. // Filtering samplers. -@group(2) @binding(1) var bindless_samplers_filtering: binding_array; +@group(3) @binding(1) var bindless_samplers_filtering: binding_array; // Non-filtering samplers (nearest neighbor). -@group(2) @binding(2) var bindless_samplers_non_filtering: binding_array; +@group(3) @binding(2) var bindless_samplers_non_filtering: binding_array; // Comparison samplers (typically for shadow mapping). -@group(2) @binding(3) var bindless_samplers_comparison: binding_array; +@group(3) @binding(3) var bindless_samplers_comparison: binding_array; // 1D textures. -@group(2) @binding(4) var bindless_textures_1d: binding_array>; +@group(3) @binding(4) var bindless_textures_1d: binding_array>; // 2D textures. -@group(2) @binding(5) var bindless_textures_2d: binding_array>; +@group(3) @binding(5) var bindless_textures_2d: binding_array>; // 2D array textures. -@group(2) @binding(6) var bindless_textures_2d_array: binding_array>; +@group(3) @binding(6) var bindless_textures_2d_array: binding_array>; // 3D textures. -@group(2) @binding(7) var bindless_textures_3d: binding_array>; +@group(3) @binding(7) var bindless_textures_3d: binding_array>; // Cubemap textures. -@group(2) @binding(8) var bindless_textures_cube: binding_array>; +@group(3) @binding(8) var bindless_textures_cube: binding_array>; // Cubemap array textures. -@group(2) @binding(9) var bindless_textures_cube_array: binding_array>; +@group(3) @binding(9) var bindless_textures_cube_array: binding_array>; #endif // BINDLESS diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 144f4d3f66d9f..879825abb1cc6 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -1233,6 +1233,5 @@ fn get_capabilities(features: Features, downlevel: DownlevelFlags) -> Capabiliti Capabilities::TEXTURE_INT64_ATOMIC, features.contains(Features::TEXTURE_INT64_ATOMIC), ); - capabilities } From 88c949258ebb9568e9909400bec074d8fcf9a0cd Mon Sep 17 00:00:00 2001 From: charlotte Date: Fri, 20 Jun 2025 15:22:13 -0700 Subject: [PATCH 17/37] Add new caps. --- crates/bevy_render/src/render_resource/pipeline_cache.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 879825abb1cc6..e1ac5c786453d 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -1233,5 +1233,14 @@ fn get_capabilities(features: Features, downlevel: DownlevelFlags) -> Capabiliti Capabilities::TEXTURE_INT64_ATOMIC, features.contains(Features::TEXTURE_INT64_ATOMIC), ); + capabilities.set( + Capabilities::SHADER_FLOAT16, + features.contains(Features::SHADER_F16), + ); + capabilities.set( + Capabilities::RAY_HIT_VERTEX_POSITION, + features.intersects(Features::EXPERIMENTAL_RAY_HIT_VERTEX_RETURN), + ); + capabilities } From c180bd79a62f18990ad371421d886700719fcbb3 Mon Sep 17 00:00:00 2001 From: charlotte Date: Fri, 20 Jun 2025 15:23:19 -0700 Subject: [PATCH 18/37] WebGPU compliant dual source blending. --- crates/bevy_pbr/src/atmosphere/render_sky.wgsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/atmosphere/render_sky.wgsl b/crates/bevy_pbr/src/atmosphere/render_sky.wgsl index e488656df4cd6..b7b110879aba1 100644 --- a/crates/bevy_pbr/src/atmosphere/render_sky.wgsl +++ b/crates/bevy_pbr/src/atmosphere/render_sky.wgsl @@ -19,9 +19,9 @@ #endif struct RenderSkyOutput { - @location(0) inscattering: vec4, + @location(0) @blend_src(0) inscattering: vec4, #ifdef DUAL_SOURCE_BLENDING - @location(0) @second_blend_source transmittance: vec4, + @location(0) @blend_src(1) transmittance: vec4, #endif } From 92db3a97af918239645ff77d6115ac2e74bf3da8 Mon Sep 17 00:00:00 2001 From: charlotte Date: Fri, 20 Jun 2025 17:12:23 -0700 Subject: [PATCH 19/37] add necessary directive. --- crates/bevy_pbr/src/atmosphere/render_sky.wgsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_pbr/src/atmosphere/render_sky.wgsl b/crates/bevy_pbr/src/atmosphere/render_sky.wgsl index b7b110879aba1..b6cb8d826fddd 100644 --- a/crates/bevy_pbr/src/atmosphere/render_sky.wgsl +++ b/crates/bevy_pbr/src/atmosphere/render_sky.wgsl @@ -1,3 +1,5 @@ +enable dual_source_blending; + #import bevy_pbr::atmosphere::{ types::{Atmosphere, AtmosphereSettings}, bindings::{atmosphere, view, atmosphere_transforms}, From 9495fa60c9febc2d924c48beb1d0cc6d24c9f926 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Mon, 23 Jun 2025 20:59:28 -0700 Subject: [PATCH 20/37] Fmt. --- crates/bevy_render/src/render_resource/pipeline_cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index e1ac5c786453d..ebd3229636ad5 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -1234,7 +1234,7 @@ fn get_capabilities(features: Features, downlevel: DownlevelFlags) -> Capabiliti features.contains(Features::TEXTURE_INT64_ATOMIC), ); capabilities.set( - Capabilities::SHADER_FLOAT16, + Capabilities::SHADER_FLOAT16, features.contains(Features::SHADER_F16), ); capabilities.set( From e7f11a73c880a526420719f21892936b2719e8c7 Mon Sep 17 00:00:00 2001 From: charlotte Date: Mon, 23 Jun 2025 21:24:36 -0700 Subject: [PATCH 21/37] Fix lightmaps. --- crates/bevy_pbr/src/lightmap/lightmap.wgsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_pbr/src/lightmap/lightmap.wgsl b/crates/bevy_pbr/src/lightmap/lightmap.wgsl index da10ece9b1c01..4ba6f51bc9a4b 100644 --- a/crates/bevy_pbr/src/lightmap/lightmap.wgsl +++ b/crates/bevy_pbr/src/lightmap/lightmap.wgsl @@ -3,11 +3,11 @@ #import bevy_pbr::mesh_bindings::mesh #ifdef MULTIPLE_LIGHTMAPS_IN_ARRAY -@group(1) @binding(4) var lightmaps_textures: binding_array, 4>; -@group(1) @binding(5) var lightmaps_samplers: binding_array; +@group(2) @binding(4) var lightmaps_textures: binding_array, 4>; +@group(2) @binding(5) var lightmaps_samplers: binding_array; #else // MULTIPLE_LIGHTMAPS_IN_ARRAY -@group(1) @binding(4) var lightmaps_texture: texture_2d; -@group(1) @binding(5) var lightmaps_sampler: sampler; +@group(2) @binding(4) var lightmaps_texture: texture_2d; +@group(2) @binding(5) var lightmaps_sampler: sampler; #endif // MULTIPLE_LIGHTMAPS_IN_ARRAY // Samples the lightmap, if any, and returns indirect illumination from it. From ef83e59f0d310fca5399b457fb55693bd8f52fd0 Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 00:06:21 -0700 Subject: [PATCH 22/37] Fix decal. --- crates/bevy_pbr/src/decal/forward_decal.wgsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/decal/forward_decal.wgsl b/crates/bevy_pbr/src/decal/forward_decal.wgsl index ce24d57bf5998..f0414bc807625 100644 --- a/crates/bevy_pbr/src/decal/forward_decal.wgsl +++ b/crates/bevy_pbr/src/decal/forward_decal.wgsl @@ -10,7 +10,7 @@ } #import bevy_render::maths::project_onto -@group(2) @binding(200) +@group(3) @binding(200) var inv_depth_fade_factor: f32; struct ForwardDecalInformation { From aa7dd745613431e9e48e1d6a03b002bdd8ca020d Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 00:08:00 -0700 Subject: [PATCH 23/37] GLSL --- crates/bevy_pbr/src/render/morph.wgsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_pbr/src/render/morph.wgsl b/crates/bevy_pbr/src/render/morph.wgsl index 939b714c777ed..6689d68cc6415 100644 --- a/crates/bevy_pbr/src/render/morph.wgsl +++ b/crates/bevy_pbr/src/render/morph.wgsl @@ -4,9 +4,9 @@ #import bevy_pbr::mesh_types::MorphWeights; -@group(1) @binding(2) var morph_weights: MorphWeights; -@group(1) @binding(3) var morph_targets: texture_3d; -@group(1) @binding(7) var prev_morph_weights: MorphWeights; +@group(2) @binding(2) var morph_weights: MorphWeights; +@group(2) @binding(3) var morph_targets: texture_3d; +@group(2) @binding(7) var prev_morph_weights: MorphWeights; // NOTE: Those are the "hardcoded" values found in `MorphAttributes` struct // in crates/bevy_render/src/mesh/morph/visitors.rs From 03e61f2893646a9a511d8fabbd3b8f065674a2fa Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 00:11:15 -0700 Subject: [PATCH 24/37] GLSL --- assets/shaders/custom_material.frag | 6 +++--- assets/shaders/custom_material.vert | 4 ++-- examples/README.md | 4 +--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/assets/shaders/custom_material.frag b/assets/shaders/custom_material.frag index a6bc9af0d2a7d..0617a08ae7291 100644 --- a/assets/shaders/custom_material.frag +++ b/assets/shaders/custom_material.frag @@ -3,10 +3,10 @@ layout(location = 0) in vec2 v_Uv; layout(location = 0) out vec4 o_Target; -layout(set = 2, binding = 0) uniform vec4 CustomMaterial_color; +layout(set = 3, binding = 0) uniform vec4 CustomMaterial_color; -layout(set = 2, binding = 1) uniform texture2D CustomMaterial_texture; -layout(set = 2, binding = 2) uniform sampler CustomMaterial_sampler; +layout(set = 3, binding = 1) uniform texture2D CustomMaterial_texture; +layout(set = 3, binding = 2) uniform sampler CustomMaterial_sampler; // wgsl modules can be imported and used in glsl // FIXME - this doesn't work any more ... diff --git a/assets/shaders/custom_material.vert b/assets/shaders/custom_material.vert index 86ca3629e261f..f9a2813a37994 100644 --- a/assets/shaders/custom_material.vert +++ b/assets/shaders/custom_material.vert @@ -25,9 +25,9 @@ struct Mesh { }; #ifdef PER_OBJECT_BUFFER_BATCH_SIZE -layout(set = 1, binding = 0) uniform Mesh Meshes[#{PER_OBJECT_BUFFER_BATCH_SIZE}]; +layout(set = 2, binding = 0) uniform Mesh Meshes[#{PER_OBJECT_BUFFER_BATCH_SIZE}]; #else -layout(set = 1, binding = 0) readonly buffer _Meshes { +layout(set = 2, binding = 0) readonly buffer _Meshes { Mesh Meshes[]; }; #endif // PER_OBJECT_BUFFER_BATCH_SIZE diff --git a/examples/README.md b/examples/README.md index b966e75d1dc07..6b07f36f12848 100644 --- a/examples/README.md +++ b/examples/README.md @@ -763,9 +763,7 @@ following commands. ```sh cargo build --release --example lighting --target wasm32-unknown-unknown -wasm-bindgen --out-name wasm_example \ - --out-dir examples/wasm/target \ - --target web target/wasm32-unknown-unknown/release/examples/lighting.wasm +wasm-bindgen --out-name wasm_example --out-dir examples/wasm/target --target web target/wasm32-unknown-unknown/release/examples/lighting.wasm ``` The first command will build the example for the wasm target, creating a binary. Then, From a6179f9337165b33f92eb36bbae7b773d167d075 Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 00:21:49 -0700 Subject: [PATCH 25/37] Oops. --- examples/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/README.md b/examples/README.md index 6b07f36f12848..bccadd438eab9 100644 --- a/examples/README.md +++ b/examples/README.md @@ -129,7 +129,6 @@ Example | Description [Sprite Tile](../examples/2d/sprite_tile.rs) | Renders a sprite tiled in a grid [Text 2D](../examples/2d/text2d.rs) | Generates text in 2D [Texture Atlas](../examples/2d/texture_atlas.rs) | Generates a texture atlas (sprite sheet) from individual sprites -[Tilemap Chunk](../examples/2d/tilemap_chunk.rs) | Renders a tilemap chunk [Transparency in 2D](../examples/2d/transparency_2d.rs) | Demonstrates transparency in 2d ## 3D Rendering @@ -186,7 +185,7 @@ Example | Description [Shadow Biases](../examples/3d/shadow_biases.rs) | Demonstrates how shadow biases affect shadows in a 3d scene [Shadow Caster and Receiver](../examples/3d/shadow_caster_receiver.rs) | Demonstrates how to prevent meshes from casting/receiving shadows in a 3d scene [Skybox](../examples/3d/skybox.rs) | Load a cubemap texture onto a cube like a skybox and cycle through different compressed texture formats. -[Solari](../examples/3d/solari.rs) | Demonstrates realtime dynamic raytraced lighting using Bevy Solari. +[Solari](../examples/3d/solari.rs) | Demonstrates realtime dynamic global illumination rendering using Bevy Solari. [Specular Tint](../examples/3d/specular_tint.rs) | Demonstrates specular tints and maps [Spherical Area Lights](../examples/3d/spherical_area_lights.rs) | Demonstrates how point light radius values affect light behavior [Split Screen](../examples/3d/split_screen.rs) | Demonstrates how to render two cameras to the same window to accomplish "split screen" @@ -585,7 +584,7 @@ Example | Description Example | Description --- | --- -[Context Menu](../examples/usage/context_menu.rs) | Example of a context menu +[Context Menu](../examples/usages/context_menu.rs) | Example of a context menu [Cooldown](../examples/usage/cooldown.rs) | Example for cooldown on button clicks ## Window @@ -763,7 +762,9 @@ following commands. ```sh cargo build --release --example lighting --target wasm32-unknown-unknown -wasm-bindgen --out-name wasm_example --out-dir examples/wasm/target --target web target/wasm32-unknown-unknown/release/examples/lighting.wasm +wasm-bindgen --out-name wasm_example \ + --out-dir examples/wasm/target \ + --target web target/wasm32-unknown-unknown/release/examples/lighting.wasm ``` The first command will build the example for the wasm target, creating a binary. Then, From c821f358fe5fe5f12580fe733d5a9c16e53a8854 Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 00:28:48 -0700 Subject: [PATCH 26/37] Fix examples --- examples/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/README.md b/examples/README.md index bccadd438eab9..b966e75d1dc07 100644 --- a/examples/README.md +++ b/examples/README.md @@ -129,6 +129,7 @@ Example | Description [Sprite Tile](../examples/2d/sprite_tile.rs) | Renders a sprite tiled in a grid [Text 2D](../examples/2d/text2d.rs) | Generates text in 2D [Texture Atlas](../examples/2d/texture_atlas.rs) | Generates a texture atlas (sprite sheet) from individual sprites +[Tilemap Chunk](../examples/2d/tilemap_chunk.rs) | Renders a tilemap chunk [Transparency in 2D](../examples/2d/transparency_2d.rs) | Demonstrates transparency in 2d ## 3D Rendering @@ -185,7 +186,7 @@ Example | Description [Shadow Biases](../examples/3d/shadow_biases.rs) | Demonstrates how shadow biases affect shadows in a 3d scene [Shadow Caster and Receiver](../examples/3d/shadow_caster_receiver.rs) | Demonstrates how to prevent meshes from casting/receiving shadows in a 3d scene [Skybox](../examples/3d/skybox.rs) | Load a cubemap texture onto a cube like a skybox and cycle through different compressed texture formats. -[Solari](../examples/3d/solari.rs) | Demonstrates realtime dynamic global illumination rendering using Bevy Solari. +[Solari](../examples/3d/solari.rs) | Demonstrates realtime dynamic raytraced lighting using Bevy Solari. [Specular Tint](../examples/3d/specular_tint.rs) | Demonstrates specular tints and maps [Spherical Area Lights](../examples/3d/spherical_area_lights.rs) | Demonstrates how point light radius values affect light behavior [Split Screen](../examples/3d/split_screen.rs) | Demonstrates how to render two cameras to the same window to accomplish "split screen" @@ -584,7 +585,7 @@ Example | Description Example | Description --- | --- -[Context Menu](../examples/usages/context_menu.rs) | Example of a context menu +[Context Menu](../examples/usage/context_menu.rs) | Example of a context menu [Cooldown](../examples/usage/cooldown.rs) | Example for cooldown on button clicks ## Window From a480511a0e800c4419ae8d125a18e32fd5a2f968 Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 00:47:04 -0700 Subject: [PATCH 27/37] ShaderStages::all() is broken in WebGPU. --- .../bevy_pbr/src/meshlet/resource_manager.rs | 4 ++-- .../bevy_render/macros/src/as_bind_group.rs | 20 ++++++++++++------- .../src/render_resource/bindless.rs | 20 +++++++++---------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/crates/bevy_pbr/src/meshlet/resource_manager.rs b/crates/bevy_pbr/src/meshlet/resource_manager.rs index 9b45d7676ab43..d33752d426142 100644 --- a/crates/bevy_pbr/src/meshlet/resource_manager.rs +++ b/crates/bevy_pbr/src/meshlet/resource_manager.rs @@ -206,7 +206,7 @@ impl ResourceManager { visibility_buffer_raster_bind_group_layout: render_device.create_bind_group_layout( "meshlet_visibility_buffer_raster_bind_group_layout", &BindGroupLayoutEntries::sequential( - ShaderStages::all(), + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, ( storage_buffer_read_only_sized(false, None), storage_buffer_read_only_sized(false, None), @@ -225,7 +225,7 @@ impl ResourceManager { .create_bind_group_layout( "meshlet_visibility_buffer_raster_shadow_view_bind_group_layout", &BindGroupLayoutEntries::sequential( - ShaderStages::all(), + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, ( storage_buffer_read_only_sized(false, None), storage_buffer_read_only_sized(false, None), diff --git a/crates/bevy_render/macros/src/as_bind_group.rs b/crates/bevy_render/macros/src/as_bind_group.rs index 4252929170f19..35d394c432140 100644 --- a/crates/bevy_render/macros/src/as_bind_group.rs +++ b/crates/bevy_render/macros/src/as_bind_group.rs @@ -204,7 +204,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_array_binding, - visibility: #render_path::render_resource::ShaderStages::all(), + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -253,7 +253,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_array_binding, - visibility: #render_path::render_resource::ShaderStages::all(), + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -279,7 +279,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_index, - visibility: #render_path::render_resource::ShaderStages::all(), + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -519,7 +519,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_array_binding, - visibility: #render_path::render_resource::ShaderStages::all(), + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, ty: #render_path::render_resource::BindingType::Buffer { ty: #render_path::render_resource::BufferBindingType::Storage { read_only: #read_only @@ -834,7 +834,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_index, - visibility: #render_path::render_resource::ShaderStages::all(), + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -881,7 +881,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { non_bindless_binding_layouts.push(quote!{ #bind_group_layout_entries.push(#render_path::render_resource::BindGroupLayoutEntry { binding: #binding_index, - visibility: #render_path::render_resource::ShaderStages::all(), + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -1337,7 +1337,13 @@ impl VisibilityFlags { impl ShaderStageVisibility { fn hygienic_quote(&self, path: &proc_macro2::TokenStream) -> proc_macro2::TokenStream { match self { - ShaderStageVisibility::All => quote! { #path::ShaderStages::all() }, + ShaderStageVisibility::All => quote! { + if cfg!(feature = "webgpu") { + todo!("Please use a more specific shader stage: https://github.com/gfx-rs/wgpu/issues/7708") + } else { + #path::ShaderStages::all() + } + }, ShaderStageVisibility::None => quote! { #path::ShaderStages::NONE }, ShaderStageVisibility::Flags(flags) => { let mut quoted = Vec::new(); diff --git a/crates/bevy_render/src/render_resource/bindless.rs b/crates/bevy_render/src/render_resource/bindless.rs index 64a0fa2c1fe84..9ec809cf5d022 100644 --- a/crates/bevy_render/src/render_resource/bindless.rs +++ b/crates/bevy_render/src/render_resource/bindless.rs @@ -243,35 +243,35 @@ pub fn create_bindless_bind_group_layout_entries( false, NonZeroU64::new(bindless_index_table_length as u64 * size_of::() as u64), ) - .build(*bindless_index_table_binding_number, ShaderStages::all()), + .build(*bindless_index_table_binding_number, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), // Continue with the common bindless resource arrays. sampler(SamplerBindingType::Filtering) .count(bindless_slab_resource_limit) - .build(1, ShaderStages::all()), + .build(1, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), sampler(SamplerBindingType::NonFiltering) .count(bindless_slab_resource_limit) - .build(2, ShaderStages::all()), + .build(2, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), sampler(SamplerBindingType::Comparison) .count(bindless_slab_resource_limit) - .build(3, ShaderStages::all()), + .build(3, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), texture_1d(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(4, ShaderStages::all()), + .build(4, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), texture_2d(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(5, ShaderStages::all()), + .build(5, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), texture_2d_array(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(6, ShaderStages::all()), + .build(6, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), texture_3d(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(7, ShaderStages::all()), + .build(7, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), texture_cube(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(8, ShaderStages::all()), + .build(8, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), texture_cube_array(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(9, ShaderStages::all()), + .build(9, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), ] } From 653c8e3cfcf1949fd87354ee19fa16ed93c43c08 Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 00:49:06 -0700 Subject: [PATCH 28/37] Compute. --- crates/bevy_render/macros/src/as_bind_group.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bevy_render/macros/src/as_bind_group.rs b/crates/bevy_render/macros/src/as_bind_group.rs index 35d394c432140..7bac6796acbc8 100644 --- a/crates/bevy_render/macros/src/as_bind_group.rs +++ b/crates/bevy_render/macros/src/as_bind_group.rs @@ -204,7 +204,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_array_binding, - visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -253,7 +253,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_array_binding, - visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -279,7 +279,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_index, - visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -519,7 +519,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_array_binding, - visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE, ty: #render_path::render_resource::BindingType::Buffer { ty: #render_path::render_resource::BufferBindingType::Storage { read_only: #read_only @@ -834,7 +834,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { #bind_group_layout_entries.push( #render_path::render_resource::BindGroupLayoutEntry { binding: #binding_index, - visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, @@ -881,7 +881,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { non_bindless_binding_layouts.push(quote!{ #bind_group_layout_entries.push(#render_path::render_resource::BindGroupLayoutEntry { binding: #binding_index, - visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::VERTEX, + visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE, ty: #render_path::render_resource::BindingType::Buffer { ty: #uniform_binding_type, has_dynamic_offset: false, From 8ec93404fc8f7ae194a5ffc6bb70a96e471f7ac7 Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 10:56:56 -0700 Subject: [PATCH 29/37] Fix solari. --- crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl b/crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl index aad064590f263..945bb5cc7575d 100644 --- a/crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl +++ b/crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl @@ -120,7 +120,7 @@ fn resolve_material(material: Material, uv: vec2) -> ResolvedMaterial { fn resolve_ray_hit_full(ray_hit: RayIntersection) -> ResolvedRayHitFull { let barycentrics = vec3(1.0 - ray_hit.barycentrics.x - ray_hit.barycentrics.y, ray_hit.barycentrics); - return resolve_triangle_data_full(ray_hit.instance_id, ray_hit.primitive_index, barycentrics); + return resolve_triangle_data_full(ray_hit.instance_index, ray_hit.primitive_index, barycentrics); } fn resolve_triangle_data_full(instance_id: u32, triangle_id: u32, barycentrics: vec3) -> ResolvedRayHitFull { From 5a72ae88c5fc2654051903b734fe899f1651520a Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 11:37:34 -0700 Subject: [PATCH 30/37] Solari. --- crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl b/crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl index 945bb5cc7575d..974ee50d7dc54 100644 --- a/crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl +++ b/crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl @@ -71,8 +71,8 @@ struct DirectionalLight { @group(0) @binding(9) var light_sources: array; @group(0) @binding(10) var directional_lights: array; -const RAY_T_MIN = 0.01; -const RAY_T_MAX = 100000.0; +const RAY_T_MIN = 0.01f; +const RAY_T_MAX = 100000.0f; const RAY_NO_CULL = 0xFFu; From 31236ca481965eee0ef45591e0be0d7d6c88aef1 Mon Sep 17 00:00:00 2001 From: charlotte Date: Tue, 24 Jun 2025 12:13:47 -0700 Subject: [PATCH 31/37] Note exported float constants. --- release-content/migration-guides/wgpu_25.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/release-content/migration-guides/wgpu_25.md b/release-content/migration-guides/wgpu_25.md index 16415049b0156..acf9395ffbda2 100644 --- a/release-content/migration-guides/wgpu_25.md +++ b/release-content/migration-guides/wgpu_25.md @@ -16,4 +16,7 @@ following changes to the default bind group numbering have been made in 3d: Most users who are not using mid-level render APIs will simply need to switch their material bind groups from `@group(2)` to `@group(3)`. -See the changelog [here](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v2500-2025-04-10). +Exported float constants from shaders without an explicit type declaration like `const FOO = 1.0;` are no +longer supported and must be explicitly typed like `const FOO: f32 = 1.0;`. + +See the full changelog [here](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v2500-2025-04-10). From a91d3878627d62031cb6b1a2f24203fbde16cc01 Mon Sep 17 00:00:00 2001 From: charlotte Date: Wed, 25 Jun 2025 10:36:09 -0700 Subject: [PATCH 32/37] Remove unecessary solari feature. --- crates/bevy_solari/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_solari/src/lib.rs b/crates/bevy_solari/src/lib.rs index 377108e21a0f2..d5a22e014b8c5 100644 --- a/crates/bevy_solari/src/lib.rs +++ b/crates/bevy_solari/src/lib.rs @@ -46,7 +46,6 @@ impl SolariPlugin { | WgpuFeatures::EXPERIMENTAL_RAY_QUERY | WgpuFeatures::BUFFER_BINDING_ARRAY | WgpuFeatures::TEXTURE_BINDING_ARRAY - | WgpuFeatures::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING | WgpuFeatures::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING | WgpuFeatures::PARTIALLY_BOUND_BINDING_ARRAY } From ac04ed5ebb07cbb8f0d8674c501c70dfa7657906 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Wed, 25 Jun 2025 16:29:09 -0700 Subject: [PATCH 33/37] Fmt. --- .../src/render_resource/bindless.rs | 50 +++++++++++++++---- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/crates/bevy_render/src/render_resource/bindless.rs b/crates/bevy_render/src/render_resource/bindless.rs index 9ec809cf5d022..dc3bf00eee95c 100644 --- a/crates/bevy_render/src/render_resource/bindless.rs +++ b/crates/bevy_render/src/render_resource/bindless.rs @@ -243,35 +243,65 @@ pub fn create_bindless_bind_group_layout_entries( false, NonZeroU64::new(bindless_index_table_length as u64 * size_of::() as u64), ) - .build(*bindless_index_table_binding_number, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + *bindless_index_table_binding_number, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), // Continue with the common bindless resource arrays. sampler(SamplerBindingType::Filtering) .count(bindless_slab_resource_limit) - .build(1, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 1, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), sampler(SamplerBindingType::NonFiltering) .count(bindless_slab_resource_limit) - .build(2, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 2, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), sampler(SamplerBindingType::Comparison) .count(bindless_slab_resource_limit) - .build(3, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 3, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), texture_1d(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(4, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 4, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), texture_2d(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(5, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 5, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), texture_2d_array(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(6, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 6, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), texture_3d(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(7, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 7, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), texture_cube(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(8, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 8, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), texture_cube_array(TextureSampleType::Float { filterable: true }) .count(bindless_slab_resource_limit) - .build(9, ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE), + .build( + 9, + ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE, + ), ] } From f1cce9d3e32663423de0cea6cc3e38c5abd17124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Wed, 25 Jun 2025 20:36:42 -0700 Subject: [PATCH 34/37] Update crates/bevy_pbr/src/atmosphere/render_sky.wgsl Co-authored-by: Elabajaba --- crates/bevy_pbr/src/atmosphere/render_sky.wgsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/atmosphere/render_sky.wgsl b/crates/bevy_pbr/src/atmosphere/render_sky.wgsl index b6cb8d826fddd..1bd1bc395fccc 100644 --- a/crates/bevy_pbr/src/atmosphere/render_sky.wgsl +++ b/crates/bevy_pbr/src/atmosphere/render_sky.wgsl @@ -21,8 +21,8 @@ enable dual_source_blending; #endif struct RenderSkyOutput { - @location(0) @blend_src(0) inscattering: vec4, #ifdef DUAL_SOURCE_BLENDING + @location(0) @blend_src(0) inscattering: vec4, @location(0) @blend_src(1) transmittance: vec4, #endif } From 1284668c75df71a56737c5e7a43602e2d336e9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Wed, 25 Jun 2025 20:36:49 -0700 Subject: [PATCH 35/37] Update crates/bevy_pbr/src/atmosphere/render_sky.wgsl Co-authored-by: Elabajaba --- crates/bevy_pbr/src/atmosphere/render_sky.wgsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_pbr/src/atmosphere/render_sky.wgsl b/crates/bevy_pbr/src/atmosphere/render_sky.wgsl index 1bd1bc395fccc..f8298272caa69 100644 --- a/crates/bevy_pbr/src/atmosphere/render_sky.wgsl +++ b/crates/bevy_pbr/src/atmosphere/render_sky.wgsl @@ -24,6 +24,8 @@ struct RenderSkyOutput { #ifdef DUAL_SOURCE_BLENDING @location(0) @blend_src(0) inscattering: vec4, @location(0) @blend_src(1) transmittance: vec4, +#else + @location(0) inscattering: vec4, #endif } From 7a39c20681208d22f22603c0191ca32e30840622 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Wed, 25 Jun 2025 20:39:09 -0700 Subject: [PATCH 36/37] Clarify language. --- release-content/migration-guides/wgpu_25.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/release-content/migration-guides/wgpu_25.md b/release-content/migration-guides/wgpu_25.md index acf9395ffbda2..dfbead7e286ca 100644 --- a/release-content/migration-guides/wgpu_25.md +++ b/release-content/migration-guides/wgpu_25.md @@ -8,10 +8,10 @@ uniforms with dynamic offsets which are used pervasively in the renderer. Dynami of any kind are no longer allowed to be used in the same bind group as binding arrays. As such, the following changes to the default bind group numbering have been made in 3d: -- `@group(0)` view uniforms -- `@group(1)` view uniforms requiring binding arrays -- `@group(2)` mesh uniforms -- `@group(3)` material uniforms +- `@group(0)` view binding resources +- `@group(1)` view resources requiring binding arrays +- `@group(2)` mesh binding resources +- `@group(3)` material binding resources Most users who are not using mid-level render APIs will simply need to switch their material bind groups from `@group(2)` to `@group(3)`. From d62fd5380dcbb9db8d4a8128f6f635529fdcbbf5 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Thu, 26 Jun 2025 10:48:32 -0700 Subject: [PATCH 37/37] naga_oil released. --- crates/bevy_render/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 225184e550661..a657da4f0e641 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -125,7 +125,7 @@ wesl = { version = "0.1.2", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # Omit the `glsl` feature in non-WebAssembly by default. -naga_oil = { git = "https://github.com/bevyengine/naga_oil", default-features = false, features = [ +naga_oil = { version = "0.18", default-features = false, features = [ "test_shader", ] } @@ -133,7 +133,7 @@ naga_oil = { git = "https://github.com/bevyengine/naga_oil", default-features = proptest = "1" [target.'cfg(target_arch = "wasm32")'.dependencies] -naga_oil = { git = "https://github.com/bevyengine/naga_oil" } +naga_oil = { version = "0.18" } js-sys = "0.3" web-sys = { version = "0.3.67", features = [ 'Blob',