From 16dbb8780a4510bb4d789dca57883385b7f401a0 Mon Sep 17 00:00:00 2001 From: charlotte Date: Wed, 9 Jul 2025 14:05:53 -0700 Subject: [PATCH 1/3] Use naga oil constant for material bind group. --- 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.wgsl | 6 +- assets/shaders/custom_material_2d.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/manual_material.wgsl | 4 +- 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/decal/forward_decal.wgsl | 2 +- crates/bevy_pbr/src/material.rs | 18 ++++- crates/bevy_pbr/src/render/pbr_bindings.wgsl | 66 +++++++++---------- crates/bevy_render/src/bindless.wgsl | 18 ++--- .../src/mesh2d/color_material.wgsl | 6 +- crates/bevy_sprite/src/mesh2d/material.rs | 18 ++++- .../tilemap_chunk/tilemap_chunk_material.wgsl | 6 +- 26 files changed, 134 insertions(+), 102 deletions(-) diff --git a/assets/shaders/array_texture.wgsl b/assets/shaders/array_texture.wgsl index 293f3316654e4..1bc6c46c404bf 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(3) @binding(0) var my_array_texture: texture_2d_array; -@group(3) @binding(1) var my_array_texture_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var my_array_texture: texture_2d_array; +@group(#{MATERIAL_BIND_GROUP}) @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 ca2195df0d4de..320f03aa6a7ba 100644 --- a/assets/shaders/automatic_instancing.wgsl +++ b/assets/shaders/automatic_instancing.wgsl @@ -3,8 +3,8 @@ view_transformations::position_world_to_clip } -@group(3) @binding(0) var texture: texture_2d; -@group(3) @binding(1) var texture_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @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 f7fa795d94c1c..edc463615bdd6 100644 --- a/assets/shaders/bindless_material.wgsl +++ b/assets/shaders/bindless_material.wgsl @@ -15,12 +15,12 @@ struct MaterialBindings { } #ifdef BINDLESS -@group(3) @binding(0) var materials: array; -@group(3) @binding(10) var material_color: binding_array; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var materials: array; +@group(#{MATERIAL_BIND_GROUP}) @binding(10) var material_color: binding_array; #else // BINDLESS -@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; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material_color: Color; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var material_color_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @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 81e153e408dfb..16b5cdfd30568 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(3) @binding(0) var base_color_texture: texture_cube_array; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var base_color_texture: texture_cube_array; #else -@group(3) @binding(0) var base_color_texture: texture_cube; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var base_color_texture: texture_cube; #endif -@group(3) @binding(1) var base_color_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var base_color_sampler: sampler; @fragment fn fragment( diff --git a/assets/shaders/custom_material.wgsl b/assets/shaders/custom_material.wgsl index 7548d2223c8af..810bf16a58568 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(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; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material_color: vec4; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var material_color_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(2) var material_color_sampler: sampler; @fragment fn fragment( diff --git a/assets/shaders/custom_material_2d.wgsl b/assets/shaders/custom_material_2d.wgsl index eee352493dd53..a90cd76b6cd08 100644 --- a/assets/shaders/custom_material_2d.wgsl +++ b/assets/shaders/custom_material_2d.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 base_color_texture: texture_2d; -@group(2) @binding(2) var base_color_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material_color: vec4; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var base_color_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(2) var base_color_sampler: sampler; @fragment fn fragment(mesh: VertexOutput) -> @location(0) vec4 { diff --git a/assets/shaders/custom_material_screenspace_texture.wgsl b/assets/shaders/custom_material_screenspace_texture.wgsl index abad3cc15afd1..4401ccc4fa911 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(3) @binding(0) var texture: texture_2d; -@group(3) @binding(1) var texture_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @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 6b7b93e4c7161..3d16fb12afd0e 100644 --- a/assets/shaders/custom_vertex_attribute.wgsl +++ b/assets/shaders/custom_vertex_attribute.wgsl @@ -3,7 +3,7 @@ struct CustomMaterial { color: vec4, }; -@group(3) @binding(0) var material: CustomMaterial; +@group(#{MATERIAL_BIND_GROUP}) @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 7bad24a331b93..e70fee016ba57 100644 --- a/assets/shaders/extended_material.wgsl +++ b/assets/shaders/extended_material.wgsl @@ -19,7 +19,7 @@ struct MyExtendedMaterial { quantize_steps: u32, } -@group(3) @binding(100) +@group(#{MATERIAL_BIND_GROUP}) @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 c9cb07e0c733e..9db5d246835b7 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(3) @binding(100) var example_extended_material_indices: +@group(#{MATERIAL_BIND_GROUP}) @binding(100) var example_extended_material_indices: array; // An array that holds the `ExampleBindlessExtendedMaterial` plain old data, // indexed by `ExampleBindlessExtendedMaterialIndices.material`. -@group(3) @binding(101) var example_extended_material: +@group(#{MATERIAL_BIND_GROUP}) @binding(101) var example_extended_material: array; #else // BINDLESS // In non-bindless mode, we simply use a uniform for the plain old data. -@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; +@group(#{MATERIAL_BIND_GROUP}) @binding(50) var example_extended_material: ExampleBindlessExtendedMaterial; +@group(#{MATERIAL_BIND_GROUP}) @binding(51) var modulate_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @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 c92cbd1577e4e..50ac6b8549ad3 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(3) @binding(0) var test_texture_1d: texture_1d; -@group(3) @binding(1) var test_texture_1d_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var test_texture_1d: texture_1d; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var test_texture_1d_sampler: sampler; -@group(3) @binding(2) var test_texture_2d: texture_2d; -@group(3) @binding(3) var test_texture_2d_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(2) var test_texture_2d: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(3) var test_texture_2d_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(#{MATERIAL_BIND_GROUP}) @binding(4) var test_texture_2d_array: texture_2d_array; +@group(#{MATERIAL_BIND_GROUP}) @binding(5) var test_texture_2d_array_sampler: sampler; -@group(3) @binding(6) var test_texture_cube: texture_cube; -@group(3) @binding(7) var test_texture_cube_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(6) var test_texture_cube: texture_cube; +@group(#{MATERIAL_BIND_GROUP}) @binding(7) var test_texture_cube_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(#{MATERIAL_BIND_GROUP}) @binding(8) var test_texture_cube_array: texture_cube_array; +@group(#{MATERIAL_BIND_GROUP}) @binding(9) var test_texture_cube_array_sampler: sampler; -@group(3) @binding(10) var test_texture_3d: texture_3d; -@group(3) @binding(11) var test_texture_3d_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(10) var test_texture_3d: texture_3d; +@group(#{MATERIAL_BIND_GROUP}) @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 0e12110f3b1da..d510e75eb866f 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(3) @binding(100) +@group(#{MATERIAL_BIND_GROUP}) @binding(100) var irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo; @fragment diff --git a/assets/shaders/line_material.wgsl b/assets/shaders/line_material.wgsl index 639762a444ab4..c19fb3dc03e66 100644 --- a/assets/shaders/line_material.wgsl +++ b/assets/shaders/line_material.wgsl @@ -4,7 +4,7 @@ struct LineMaterial { color: vec4, }; -@group(3) @binding(0) var material: LineMaterial; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material: LineMaterial; @fragment fn fragment( diff --git a/assets/shaders/manual_material.wgsl b/assets/shaders/manual_material.wgsl index 557a1412c73d2..4b3b2662eb7a7 100644 --- a/assets/shaders/manual_material.wgsl +++ b/assets/shaders/manual_material.wgsl @@ -1,7 +1,7 @@ #import bevy_pbr::forward_io::VertexOutput -@group(3) @binding(0) var material_color_texture: texture_2d; -@group(3) @binding(1) var material_color_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material_color_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var material_color_sampler: sampler; @fragment fn fragment( diff --git a/assets/shaders/shader_defs.wgsl b/assets/shaders/shader_defs.wgsl index 776fc9ffe69eb..f36453c402169 100644 --- a/assets/shaders/shader_defs.wgsl +++ b/assets/shaders/shader_defs.wgsl @@ -4,7 +4,7 @@ struct CustomMaterial { color: vec4, }; -@group(3) @binding(0) var material: CustomMaterial; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material: CustomMaterial; @fragment fn fragment( diff --git a/assets/shaders/show_prepass.wgsl b/assets/shaders/show_prepass.wgsl index b1a53677ac1ea..11313c50e1df9 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(3) @binding(0) var settings: ShowPrepassSettings; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var settings: ShowPrepassSettings; @fragment fn fragment( diff --git a/assets/shaders/storage_buffer.wgsl b/assets/shaders/storage_buffer.wgsl index f447333cc9754..17ec47b736612 100644 --- a/assets/shaders/storage_buffer.wgsl +++ b/assets/shaders/storage_buffer.wgsl @@ -3,7 +3,7 @@ view_transformations::position_world_to_clip } -@group(3) @binding(0) var colors: array, 5>; +@group(#{MATERIAL_BIND_GROUP}) @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 17b94a74d3209..98ffce0f65bf1 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(3) @binding(0) var textures: binding_array>; -@group(3) @binding(1) var nearest_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var textures: binding_array>; +@group(#{MATERIAL_BIND_GROUP}) @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 a8a9e03df4d16..bd5bd929036de 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(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; +@group(#{MATERIAL_BIND_GROUP}) @binding(100) var water_normals_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(101) var water_normals_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @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/decal/forward_decal.wgsl b/crates/bevy_pbr/src/decal/forward_decal.wgsl index f0414bc807625..ffbb5f958b189 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(3) @binding(200) +@group(#{MATERIAL_BIND_GROUP}) @binding(200) var inv_depth_fade_factor: f32; struct ForwardDecalInformation { diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index bb1f9afde3e20..50959fb46d9ba 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -58,6 +58,8 @@ use core::{hash::Hash, marker::PhantomData}; use smallvec::SmallVec; use tracing::error; +pub const MATERIAL_BIND_GROUP_INDEX: usize = 3; + /// Materials are used alongside [`MaterialPlugin`], [`Mesh3d`], and [`MeshMaterial3d`] /// to spawn entities that are rendered with a specific [`Material`] type. They serve as an easy to use high level /// way to render [`Mesh3d`] entities with custom shader logic. @@ -457,6 +459,20 @@ impl SpecializedMeshPipeline for MaterialPipelineSpecializer { .pipeline .mesh_pipeline .specialize(key.mesh_key, layout)?; + descriptor.vertex.shader_defs.push( + ShaderDefVal::UInt( + "MATERIAL_BIND_GROUP".into(), + MATERIAL_BIND_GROUP_INDEX as u32, + ) + ); + if let Some(ref mut fragment) = descriptor.fragment { + fragment.shader_defs.push( + ShaderDefVal::UInt( + "MATERIAL_BIND_GROUP".into(), + MATERIAL_BIND_GROUP_INDEX as u32, + ) + ); + }; if let Some(vertex_shader) = self.properties.get_shader(MaterialVertexShader) { descriptor.vertex.shader = vertex_shader.clone(); } @@ -498,7 +514,7 @@ pub type DrawMaterial = ( SetMeshViewBindGroup<0>, SetMeshViewBindingArrayBindGroup<1>, SetMeshBindGroup<2>, - SetMaterialBindGroup<3>, + SetMaterialBindGroup, DrawMesh, ); diff --git a/crates/bevy_pbr/src/render/pbr_bindings.wgsl b/crates/bevy_pbr/src/render/pbr_bindings.wgsl index 373d0bdd54436..6d21c81f9e5da 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(3) @binding(0) var material_indices: array; -@group(3) @binding(10) var material_array: array; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material_indices: array; +@group(#{MATERIAL_BIND_GROUP}) @binding(10) var material_array: array; #else // BINDLESS -@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; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material: StandardMaterial; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var base_color_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(2) var base_color_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(3) var emissive_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(4) var emissive_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(5) var metallic_roughness_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(6) var metallic_roughness_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(7) var occlusion_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(8) var occlusion_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(9) var normal_map_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(10) var normal_map_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(11) var depth_map_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(12) var depth_map_sampler: sampler; #ifdef PBR_ANISOTROPY_TEXTURE_SUPPORTED -@group(3) @binding(13) var anisotropy_texture: texture_2d; -@group(3) @binding(14) var anisotropy_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(13) var anisotropy_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(14) var anisotropy_sampler: sampler; #endif // PBR_ANISOTROPY_TEXTURE_SUPPORTED #ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED -@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; +@group(#{MATERIAL_BIND_GROUP}) @binding(15) var specular_transmission_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(16) var specular_transmission_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(17) var thickness_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(18) var thickness_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(19) var diffuse_transmission_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(20) var diffuse_transmission_sampler: sampler; #endif // PBR_TRANSMISSION_TEXTURES_SUPPORTED #ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED -@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; +@group(#{MATERIAL_BIND_GROUP}) @binding(21) var clearcoat_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(22) var clearcoat_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(23) var clearcoat_roughness_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(24) var clearcoat_roughness_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(25) var clearcoat_normal_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(26) var clearcoat_normal_sampler: sampler; #endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED #ifdef PBR_SPECULAR_TEXTURES_SUPPORTED -@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; +@group(#{MATERIAL_BIND_GROUP}) @binding(27) var specular_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(28) var specular_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(29) var specular_tint_texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(30) var specular_tint_sampler: sampler; #endif // PBR_SPECULAR_TEXTURES_SUPPORTED #endif // BINDLESS diff --git a/crates/bevy_render/src/bindless.wgsl b/crates/bevy_render/src/bindless.wgsl index 717e9c1047c60..6c8eff1a29aed 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(3) @binding(1) var bindless_samplers_filtering: binding_array; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var bindless_samplers_filtering: binding_array; // Non-filtering samplers (nearest neighbor). -@group(3) @binding(2) var bindless_samplers_non_filtering: binding_array; +@group(#{MATERIAL_BIND_GROUP}) @binding(2) var bindless_samplers_non_filtering: binding_array; // Comparison samplers (typically for shadow mapping). -@group(3) @binding(3) var bindless_samplers_comparison: binding_array; +@group(#{MATERIAL_BIND_GROUP}) @binding(3) var bindless_samplers_comparison: binding_array; // 1D textures. -@group(3) @binding(4) var bindless_textures_1d: binding_array>; +@group(#{MATERIAL_BIND_GROUP}) @binding(4) var bindless_textures_1d: binding_array>; // 2D textures. -@group(3) @binding(5) var bindless_textures_2d: binding_array>; +@group(#{MATERIAL_BIND_GROUP}) @binding(5) var bindless_textures_2d: binding_array>; // 2D array textures. -@group(3) @binding(6) var bindless_textures_2d_array: binding_array>; +@group(#{MATERIAL_BIND_GROUP}) @binding(6) var bindless_textures_2d_array: binding_array>; // 3D textures. -@group(3) @binding(7) var bindless_textures_3d: binding_array>; +@group(#{MATERIAL_BIND_GROUP}) @binding(7) var bindless_textures_3d: binding_array>; // Cubemap textures. -@group(3) @binding(8) var bindless_textures_cube: binding_array>; +@group(#{MATERIAL_BIND_GROUP}) @binding(8) var bindless_textures_cube: binding_array>; // Cubemap array textures. -@group(3) @binding(9) var bindless_textures_cube_array: binding_array>; +@group(#{MATERIAL_BIND_GROUP}) @binding(9) var bindless_textures_cube_array: binding_array>; #endif // BINDLESS diff --git a/crates/bevy_sprite/src/mesh2d/color_material.wgsl b/crates/bevy_sprite/src/mesh2d/color_material.wgsl index a2dbe4e055937..bb3972426bbe5 100644 --- a/crates/bevy_sprite/src/mesh2d/color_material.wgsl +++ b/crates/bevy_sprite/src/mesh2d/color_material.wgsl @@ -21,9 +21,9 @@ const COLOR_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE: u32 = 0u; // (0u32 const COLOR_MATERIAL_FLAGS_ALPHA_MODE_MASK: u32 = 1073741824u; // (1u32 << 30) const COLOR_MATERIAL_FLAGS_ALPHA_MODE_BLEND: u32 = 2147483648u; // (2u32 << 30) -@group(2) @binding(0) var material: ColorMaterial; -@group(2) @binding(1) var texture: texture_2d; -@group(2) @binding(2) var texture_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var material: ColorMaterial; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var texture: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(2) var texture_sampler: sampler; @fragment fn fragment( diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 06914690ca127..8f03ce9b6aef3 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -23,7 +23,7 @@ use bevy_platform::collections::HashMap; use bevy_reflect::{prelude::ReflectDefault, Reflect}; use bevy_render::camera::extract_cameras; use bevy_render::render_phase::{DrawFunctionId, InputUniformIndex}; -use bevy_render::render_resource::CachedRenderPipelineId; +use bevy_render::render_resource::{CachedRenderPipelineId, ShaderDefVal}; use bevy_render::view::RenderVisibleEntities; use bevy_render::{ mesh::{MeshVertexBufferLayoutRef, RenderMesh}, @@ -50,6 +50,8 @@ use core::{hash::Hash, marker::PhantomData}; use derive_more::derive::From; use tracing::error; +pub const MATERIAL_2D_BIND_GROUP_INDEX: usize = 2; + /// Materials are used alongside [`Material2dPlugin`], [`Mesh2d`], and [`MeshMaterial2d`] /// to spawn entities that are rendered with a specific [`Material2d`] type. They serve as an easy to use high level /// way to render [`Mesh2d`] entities with custom shader logic. @@ -449,6 +451,20 @@ where layout: &MeshVertexBufferLayoutRef, ) -> Result { let mut descriptor = self.mesh2d_pipeline.specialize(key.mesh_key, layout)?; + descriptor.vertex.shader_defs.push( + ShaderDefVal::UInt( + "MATERIAL_BIND_GROUP".into(), + MATERIAL_2D_BIND_GROUP_INDEX as u32, + ) + ); + if let Some(ref mut fragment) = descriptor.fragment { + fragment.shader_defs.push( + ShaderDefVal::UInt( + "MATERIAL_BIND_GROUP".into(), + MATERIAL_2D_BIND_GROUP_INDEX as u32, + ) + ); + } if let Some(vertex_shader) = &self.vertex_shader { descriptor.vertex.shader = vertex_shader.clone(); } diff --git a/crates/bevy_sprite/src/tilemap_chunk/tilemap_chunk_material.wgsl b/crates/bevy_sprite/src/tilemap_chunk/tilemap_chunk_material.wgsl index 7424995e22954..7f1ff0d552d49 100644 --- a/crates/bevy_sprite/src/tilemap_chunk/tilemap_chunk_material.wgsl +++ b/crates/bevy_sprite/src/tilemap_chunk/tilemap_chunk_material.wgsl @@ -16,9 +16,9 @@ struct VertexOutput { @location(1) tile_index: u32, } -@group(2) @binding(0) var tileset: texture_2d_array; -@group(2) @binding(1) var tileset_sampler: sampler; -@group(2) @binding(2) var tile_indices: texture_2d; +@group(#{MATERIAL_BIND_GROUP}) @binding(0) var tileset: texture_2d_array; +@group(#{MATERIAL_BIND_GROUP}) @binding(1) var tileset_sampler: sampler; +@group(#{MATERIAL_BIND_GROUP}) @binding(2) var tile_indices: texture_2d; @vertex fn vertex(vertex: Vertex) -> VertexOutput { From a0121e004e7429697148e41d794457e281dd2823 Mon Sep 17 00:00:00 2001 From: charlotte Date: Wed, 9 Jul 2025 14:07:05 -0700 Subject: [PATCH 2/3] Update release notes. --- release-content/migration-guides/wgpu_25.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release-content/migration-guides/wgpu_25.md b/release-content/migration-guides/wgpu_25.md index dfbead7e286ca..3f30a4d593ca8 100644 --- a/release-content/migration-guides/wgpu_25.md +++ b/release-content/migration-guides/wgpu_25.md @@ -14,7 +14,8 @@ following changes to the default bind group numbering have been made in 3d: - `@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 `@group(2)` to `@group(#{MATERIAL_BIND_GROUP})`. The `MATERIAL_BIND_GROUP` shader def has been added +to ensure backwards compatibility in the event the bind group numbering changes again in the future. 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;`. From e74b5be45d03025619640b11b6137430e81ad92b Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Fri, 11 Jul 2025 10:33:12 -0700 Subject: [PATCH 3/3] Ci. --- crates/bevy_pbr/src/material.rs | 18 +++++++----------- crates/bevy_sprite/src/mesh2d/material.rs | 18 +++++++----------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 50959fb46d9ba..91afe1b21cd42 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -459,19 +459,15 @@ impl SpecializedMeshPipeline for MaterialPipelineSpecializer { .pipeline .mesh_pipeline .specialize(key.mesh_key, layout)?; - descriptor.vertex.shader_defs.push( - ShaderDefVal::UInt( + descriptor.vertex.shader_defs.push(ShaderDefVal::UInt( + "MATERIAL_BIND_GROUP".into(), + MATERIAL_BIND_GROUP_INDEX as u32, + )); + if let Some(ref mut fragment) = descriptor.fragment { + fragment.shader_defs.push(ShaderDefVal::UInt( "MATERIAL_BIND_GROUP".into(), MATERIAL_BIND_GROUP_INDEX as u32, - ) - ); - if let Some(ref mut fragment) = descriptor.fragment { - fragment.shader_defs.push( - ShaderDefVal::UInt( - "MATERIAL_BIND_GROUP".into(), - MATERIAL_BIND_GROUP_INDEX as u32, - ) - ); + )); }; if let Some(vertex_shader) = self.properties.get_shader(MaterialVertexShader) { descriptor.vertex.shader = vertex_shader.clone(); diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 8f03ce9b6aef3..e30cb4d042f51 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -451,19 +451,15 @@ where layout: &MeshVertexBufferLayoutRef, ) -> Result { let mut descriptor = self.mesh2d_pipeline.specialize(key.mesh_key, layout)?; - descriptor.vertex.shader_defs.push( - ShaderDefVal::UInt( + descriptor.vertex.shader_defs.push(ShaderDefVal::UInt( + "MATERIAL_BIND_GROUP".into(), + MATERIAL_2D_BIND_GROUP_INDEX as u32, + )); + if let Some(ref mut fragment) = descriptor.fragment { + fragment.shader_defs.push(ShaderDefVal::UInt( "MATERIAL_BIND_GROUP".into(), MATERIAL_2D_BIND_GROUP_INDEX as u32, - ) - ); - if let Some(ref mut fragment) = descriptor.fragment { - fragment.shader_defs.push( - ShaderDefVal::UInt( - "MATERIAL_BIND_GROUP".into(), - MATERIAL_2D_BIND_GROUP_INDEX as u32, - ) - ); + )); } if let Some(vertex_shader) = &self.vertex_shader { descriptor.vertex.shader = vertex_shader.clone();