diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 9ecf1b3616be4..a7f0011c0bf31 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -18,6 +18,13 @@ use bevy_render::{ view::{ExtractedView, RenderLayers, ViewVisibility}, Extract, }; +#[cfg(any( + not(feature = "webgl"), + not(target_arch = "wasm32"), + feature = "webgpu" +))] +use bevy_render::{renderer::RenderAdapter, DownlevelFlags}; + use bevy_transform::{components::GlobalTransform, prelude::Transform}; #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; @@ -507,12 +514,24 @@ pub(crate) fn spot_light_clip_from_view(angle: f32) -> Mat4 { Mat4::perspective_infinite_reverse_rh(angle * 2.0, 1.0, POINT_LIGHT_NEAR_Z) } +#[derive(Default)] +pub struct PrepareLightsWarningEmitted { + max_directional_lights: bool, + max_cascades_per_light: bool, +} + #[allow(clippy::too_many_arguments)] pub fn prepare_lights( mut commands: Commands, mut texture_cache: ResMut, render_device: Res, render_queue: Res, + #[cfg(any( + not(feature = "webgl"), + not(target_arch = "wasm32"), + feature = "webgpu" + ))] + render_adapter: Res, mut global_light_meta: ResMut, mut light_meta: ResMut, views: Query< @@ -528,8 +547,7 @@ pub fn prepare_lights( point_light_shadow_map: Res, directional_light_shadow_map: Res, mut shadow_render_phases: ResMut>, - mut max_directional_lights_warning_emitted: Local, - mut max_cascades_per_light_warning_emitted: Local, + mut warning_emitted: Local, point_lights: Query<( Entity, &ExtractedPointLight, @@ -578,17 +596,17 @@ pub fn prepare_lights( #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] let max_texture_cubes = 1; - if !*max_directional_lights_warning_emitted && directional_lights.len() > MAX_DIRECTIONAL_LIGHTS + if !warning_emitted.max_directional_lights && directional_lights.len() > MAX_DIRECTIONAL_LIGHTS { warn!( "The amount of directional lights of {} is exceeding the supported limit of {}.", directional_lights.len(), MAX_DIRECTIONAL_LIGHTS ); - *max_directional_lights_warning_emitted = true; + warning_emitted.max_directional_lights = true; } - if !*max_cascades_per_light_warning_emitted + if !warning_emitted.max_cascades_per_light && directional_lights .iter() .any(|(_, light)| light.cascade_shadow_config.bounds.len() > MAX_CASCADES_PER_LIGHT) @@ -597,7 +615,7 @@ pub fn prepare_lights( "The number of cascades configured for a directional light exceeds the supported limit of {}.", MAX_CASCADES_PER_LIGHT ); - *max_cascades_per_light_warning_emitted = true; + warning_emitted.max_cascades_per_light = true; } let point_light_count = point_lights @@ -1091,34 +1109,38 @@ pub fn prepare_lights( } } - let point_light_depth_texture_view = - point_light_depth_texture - .texture - .create_view(&TextureViewDescriptor { - label: Some("point_light_shadow_map_array_texture_view"), - format: None, - // NOTE: iOS Simulator is missing CubeArray support so we use Cube instead. - // See https://github.com/bevyengine/bevy/pull/12052 - remove if support is added. - #[cfg(all( - not(feature = "ios_simulator"), - any( - not(feature = "webgl"), - not(target_arch = "wasm32"), - feature = "webgpu" - ) - ))] - dimension: Some(TextureViewDimension::CubeArray), - #[cfg(any( - feature = "ios_simulator", - all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")) - ))] - dimension: Some(TextureViewDimension::Cube), - aspect: TextureAspect::DepthOnly, - base_mip_level: 0, - mip_level_count: None, - base_array_layer: 0, - array_layer_count: None, - }); + #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] + let supports_cube_array_textures = false; + + #[cfg(any( + not(feature = "webgl"), + not(target_arch = "wasm32"), + feature = "webgpu" + ))] + let supports_cube_array_textures = render_adapter + .get_downlevel_capabilities() + .flags + .contains(DownlevelFlags::CUBE_ARRAY_TEXTURES); + + let point_light_texture_descriptor = &TextureViewDescriptor { + label: Some("point_light_shadow_map_array_texture_view"), + format: None, + dimension: if supports_cube_array_textures { + Some(TextureViewDimension::CubeArray) + } else { + Some(TextureViewDimension::Cube) + }, + aspect: TextureAspect::DepthOnly, + base_mip_level: 0, + mip_level_count: None, + base_array_layer: 0, + array_layer_count: None, + }; + + let point_light_depth_texture_view = point_light_depth_texture + .texture + .create_view(point_light_texture_descriptor); + let directional_light_depth_texture_view = directional_light_depth_texture .texture .create_view(&TextureViewDescriptor { diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index f3e52b3780640..c0658e20863f7 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1185,6 +1185,7 @@ impl FromWorld for MeshPipeline { Res, Res, )> = SystemState::new(world); + let (render_device, default_sampler, render_queue, view_layouts) = system_state.get_mut(world); diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.rs b/crates/bevy_pbr/src/render/mesh_view_bindings.rs index 36c5d7bfe044f..985a7488e114a 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.rs @@ -19,7 +19,7 @@ use bevy_render::{ globals::{GlobalsBuffer, GlobalsUniform}, render_asset::RenderAssets, render_resource::{binding_types::*, *}, - renderer::RenderDevice, + renderer::{RenderAdapter, RenderDevice}, texture::{BevyDefault, FallbackImage, FallbackImageMsaa, FallbackImageZero, GpuImage}, view::{ Msaa, RenderVisibilityRanges, ViewUniform, ViewUniforms, @@ -27,6 +27,13 @@ use bevy_render::{ }, }; +#[cfg(any( + not(feature = "webgl"), + not(target_arch = "wasm32"), + feature = "webgpu" +))] +use bevy_render::DownlevelFlags; + #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] use bevy_render::render_resource::binding_types::texture_cube; #[cfg(debug_assertions)] @@ -184,7 +191,28 @@ fn layout_entries( visibility_ranges_buffer_binding_type: BufferBindingType, layout_key: MeshPipelineViewLayoutKey, render_device: &RenderDevice, + #[cfg(any( + not(feature = "webgl"), + not(target_arch = "wasm32"), + feature = "webgpu" + ))] + render_adapter: &RenderAdapter, + #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] + _render_adapter: &RenderAdapter, ) -> Vec { + #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] + let supports_cube_array_textures = false; + + #[cfg(any( + not(feature = "webgl"), + not(target_arch = "wasm32"), + feature = "webgpu" + ))] + let supports_cube_array_textures = render_adapter + .get_downlevel_capabilities() + .flags + .contains(DownlevelFlags::CUBE_ARRAY_TEXTURES); + let mut entries = DynamicBindGroupLayoutEntries::new_with_indices( ShaderStages::FRAGMENT, ( @@ -198,20 +226,11 @@ fn layout_entries( // Point Shadow Texture Cube Array ( 2, - #[cfg(all( - not(feature = "ios_simulator"), - any( - not(feature = "webgl"), - not(target_arch = "wasm32"), - feature = "webgpu" - ) - ))] - texture_cube_array(TextureSampleType::Depth), - #[cfg(any( - feature = "ios_simulator", - all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")) - ))] - texture_cube(TextureSampleType::Depth), + if supports_cube_array_textures { + texture_cube_array(TextureSampleType::Depth) + } else { + texture_cube(TextureSampleType::Depth) + }, ), // Point Shadow Texture Array Sampler (3, sampler(SamplerBindingType::Comparison)), @@ -361,6 +380,7 @@ impl FromWorld for MeshPipelineViewLayouts { // [`MeshPipelineViewLayoutKey`] flags. let render_device = world.resource::(); + let render_adapter = world.resource::(); let clustered_forward_buffer_binding_type = render_device .get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT); @@ -374,6 +394,7 @@ impl FromWorld for MeshPipelineViewLayouts { visibility_ranges_buffer_binding_type, key, render_device, + render_adapter, ); #[cfg(debug_assertions)] let texture_count: usize = entries @@ -410,6 +431,7 @@ impl MeshPipelineViewLayouts { /// [`MeshPipelineViewLayoutKey`] flags. pub fn generate_view_layouts( render_device: &RenderDevice, + render_adapter: &RenderAdapter, clustered_forward_buffer_binding_type: BufferBindingType, visibility_ranges_buffer_binding_type: BufferBindingType, ) -> [MeshPipelineViewLayout; MeshPipelineViewLayoutKey::COUNT] { @@ -420,6 +442,7 @@ pub fn generate_view_layouts( visibility_ranges_buffer_binding_type, key, render_device, + render_adapter, ); #[cfg(debug_assertions)] diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index d03a7a6e010fe..9cbde4271a255 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -56,6 +56,7 @@ use batching::gpu_preprocessing::BatchingPlugin; use bevy_ecs::schedule::ScheduleBuildSettings; use bevy_utils::prelude::default; pub use extract_param::Extract; +pub use wgpu::DownlevelFlags; use bevy_hierarchy::ValidParentCheckPlugin; use bevy_window::{PrimaryWindow, RawHandleWrapperHolder}; diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 6e9b712535417..4632376727919 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -261,7 +261,11 @@ impl ShaderCache { shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into()); } - if cfg!(feature = "ios_simulator") { + if !self + .composer + .capabilities + .contains(Capabilities::CUBE_ARRAY_TEXTURES) + { shader_defs.push("NO_CUBE_ARRAY_TEXTURES_SUPPORT".into()); }