From caa7ec68d41252217068c0bd330203990a6603d7 Mon Sep 17 00:00:00 2001 From: Sam Pettersson Date: Fri, 23 Feb 2024 02:24:59 +0100 Subject: [PATCH] FIX: iOS Simulator not rendering due to missing CUBE_ARRAY_TEXTURES (#12052) This PR closes #11978 # Objective Fix rendering on iOS Simulators. iOS Simulator doesn't support the capability CUBE_ARRAY_TEXTURES, since 0.13 this started to make iOS Simulator not render anything with the following message being outputted: ``` 2024-02-19T14:59:34.896266Z ERROR bevy_render::render_resource::pipeline_cache: failed to create shader module: Validation Error Caused by: In Device::create_shader_module Shader validation error: Type [40] '' is invalid Capability Capabilities(CUBE_ARRAY_TEXTURES) is required ``` ## Solution - Split up NO_ARRAY_TEXTURES_SUPPORT into both NO_ARRAY_TEXTURES_SUPPORT and NO_CUBE_ARRAY_TEXTURES_SUPPORT and correctly apply NO_ARRAY_TEXTURES_SUPPORT for iOS Simulator using the cfg flag introduced in #10178. --- ## Changelog ### Fixed - Rendering on iOS Simulator due to missing CUBE_ARRAY_TEXTURES support. --------- Co-authored-by: Sam Pettersson --- crates/bevy_pbr/src/render/light.rs | 20 +++++++------ .../bevy_pbr/src/render/mesh_view_bindings.rs | 16 +++++++---- .../src/render/mesh_view_bindings.wgsl | 2 +- crates/bevy_pbr/src/render/shadows.wgsl | 2 +- crates/bevy_render/src/lib.rs | 1 + .../src/render_resource/pipeline_cache.rs | 28 ++++++++++++++----- 6 files changed, 47 insertions(+), 22 deletions(-) diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 5a923e73b1..1a40be695d 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -1210,16 +1210,20 @@ pub fn prepare_lights( .create_view(&TextureViewDescriptor { label: Some("point_light_shadow_map_array_texture_view"), format: None, - #[cfg(any( - not(feature = "webgl"), - not(target_arch = "wasm32"), - feature = "webgpu" + // 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(ios_simulator), + any( + not(feature = "webgl"), + not(target_arch = "wasm32"), + feature = "webgpu" + ) ))] dimension: Some(TextureViewDimension::CubeArray), - #[cfg(all( - feature = "webgl", - target_arch = "wasm32", - not(feature = "webgpu") + #[cfg(any( + ios_simulator, + all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")) ))] dimension: Some(TextureViewDimension::Cube), aspect: TextureAspect::DepthOnly, diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.rs b/crates/bevy_pbr/src/render/mesh_view_bindings.rs index b0a1dc768d..e7d7a78c7a 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.rs +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.rs @@ -191,13 +191,19 @@ fn layout_entries( // Point Shadow Texture Cube Array ( 2, - #[cfg(any( - not(feature = "webgl"), - not(target_arch = "wasm32"), - feature = "webgpu" + #[cfg(all( + not(ios_simulator), + any( + not(feature = "webgl"), + not(target_arch = "wasm32"), + feature = "webgpu" + ) ))] texture_cube_array(TextureSampleType::Depth), - #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] + #[cfg(any( + ios_simulator, + all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")) + ))] texture_cube(TextureSampleType::Depth), ), // Point Shadow Texture Array Sampler diff --git a/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl b/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl index 1d77f73928..20a3578af4 100644 --- a/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl +++ b/crates/bevy_pbr/src/render/mesh_view_bindings.wgsl @@ -8,7 +8,7 @@ @group(0) @binding(0) var view: View; @group(0) @binding(1) var lights: types::Lights; -#ifdef NO_ARRAY_TEXTURES_SUPPORT +#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT @group(0) @binding(2) var point_shadow_textures: texture_depth_cube; #else @group(0) @binding(2) var point_shadow_textures: texture_depth_cube_array; diff --git a/crates/bevy_pbr/src/render/shadows.wgsl b/crates/bevy_pbr/src/render/shadows.wgsl index 4ccbd5f850..1b2d526c14 100644 --- a/crates/bevy_pbr/src/render/shadows.wgsl +++ b/crates/bevy_pbr/src/render/shadows.wgsl @@ -44,7 +44,7 @@ fn fetch_point_shadow(light_id: u32, frag_position: vec4, surface_normal: v // a quad (2x2 fragments) being processed not being sampled, and this messing with // mip-mapping functionality. The shadow maps have no mipmaps so Level just samples // from LOD 0. -#ifdef NO_ARRAY_TEXTURES_SUPPORT +#ifdef NO_CUBE_ARRAY_TEXTURES_SUPPORT return textureSampleCompare(view_bindings::point_shadow_textures, view_bindings::point_shadow_textures_sampler, frag_ls * flip_z, depth); #else return textureSampleCompareLevel(view_bindings::point_shadow_textures, view_bindings::point_shadow_textures_sampler, frag_ls * flip_z, i32(light_id), depth); diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 28a29405db..22a4efee72 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -363,6 +363,7 @@ impl Plugin for RenderPlugin { .insert_resource(instance) .insert_resource(PipelineCache::new( device.clone(), + render_adapter.clone(), self.synchronous_pipeline_compilation, )) .insert_resource(device) diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index dc5190170a..fe014e7c34 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -1,3 +1,4 @@ +use crate::renderer::RenderAdapter; use crate::{render_resource::*, renderer::RenderDevice, Extract}; use bevy_asset::{AssetEvent, AssetId, Assets}; use bevy_ecs::system::{Res, ResMut}; @@ -21,7 +22,7 @@ use thiserror::Error; #[cfg(feature = "shader_format_spirv")] use wgpu::util::make_spirv; use wgpu::{ - Features, PipelineLayoutDescriptor, PushConstantRange, ShaderModuleDescriptor, + DownlevelFlags, Features, PipelineLayoutDescriptor, PushConstantRange, ShaderModuleDescriptor, VertexBufferLayout as RawVertexBufferLayout, }; @@ -167,7 +168,7 @@ impl ShaderDefVal { } impl ShaderCache { - fn new(render_device: &RenderDevice) -> Self { + fn new(render_device: &RenderDevice, render_adapter: &RenderAdapter) -> Self { const CAPABILITIES: &[(Features, Capabilities)] = &[ (Features::PUSH_CONSTANTS, Capabilities::PUSH_CONSTANT), (Features::SHADER_F64, Capabilities::FLOAT64), @@ -196,9 +197,13 @@ impl ShaderCache { } } - // TODO: Check if this is supported, though I'm not sure if bevy works without this feature? - // We can't compile for native at least without it. - capabilities |= Capabilities::CUBE_ARRAY_TEXTURES; + if render_adapter + .get_downlevel_capabilities() + .flags + .contains(DownlevelFlags::CUBE_ARRAY_TEXTURES) + { + capabilities |= Capabilities::CUBE_ARRAY_TEXTURES; + } #[cfg(debug_assertions)] let composer = naga_oil::compose::Composer::default(); @@ -279,9 +284,14 @@ impl ShaderCache { #[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))] { shader_defs.push("NO_ARRAY_TEXTURES_SUPPORT".into()); + shader_defs.push("NO_CUBE_ARRAY_TEXTURES_SUPPORT".into()); shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into()); } + if cfg!(ios_simulator) { + shader_defs.push("NO_CUBE_ARRAY_TEXTURES_SUPPORT".into()); + } + shader_defs.push(ShaderDefVal::UInt( String::from("AVAILABLE_STORAGE_BUFFER_BINDINGS"), render_device.limits().max_storage_buffers_per_shader_stage, @@ -491,9 +501,13 @@ impl PipelineCache { } /// Create a new pipeline cache associated with the given render device. - pub fn new(device: RenderDevice, synchronous_pipeline_compilation: bool) -> Self { + pub fn new( + device: RenderDevice, + render_adapter: RenderAdapter, + synchronous_pipeline_compilation: bool, + ) -> Self { Self { - shader_cache: Arc::new(Mutex::new(ShaderCache::new(&device))), + shader_cache: Arc::new(Mutex::new(ShaderCache::new(&device, &render_adapter))), device, layout_cache: default(), waiting_pipelines: default(),