Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix several regressions from recent rendering changes. #16890

Merged
merged 2 commits into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions crates/bevy_pbr/src/light_probe/environment_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use bevy_render::{
BindGroupLayoutEntryBuilder, Sampler, SamplerBindingType, Shader, ShaderStages,
TextureSampleType, TextureView,
},
renderer::RenderDevice,
renderer::{RenderAdapter, RenderDevice},
texture::{FallbackImage, GpuImage},
};

Expand Down Expand Up @@ -232,10 +232,11 @@ impl ExtractInstance for EnvironmentMapIds {
/// specular binding arrays respectively, in addition to the sampler.
pub(crate) fn get_bind_group_layout_entries(
render_device: &RenderDevice,
render_adapter: &RenderAdapter,
) -> [BindGroupLayoutEntryBuilder; 4] {
let mut texture_cube_binding =
binding_types::texture_cube(TextureSampleType::Float { filterable: true });
if binding_arrays_are_usable(render_device) {
if binding_arrays_are_usable(render_device, render_adapter) {
texture_cube_binding =
texture_cube_binding.count(NonZero::<u32>::new(MAX_VIEW_LIGHT_PROBES as _).unwrap());
}
Expand All @@ -256,8 +257,9 @@ impl<'a> RenderViewEnvironmentMapBindGroupEntries<'a> {
images: &'a RenderAssets<GpuImage>,
fallback_image: &'a FallbackImage,
render_device: &RenderDevice,
render_adapter: &RenderAdapter,
) -> RenderViewEnvironmentMapBindGroupEntries<'a> {
if binding_arrays_are_usable(render_device) {
if binding_arrays_are_usable(render_device, render_adapter) {
let mut diffuse_texture_views = vec![];
let mut specular_texture_views = vec![];
let mut sampler = None;
Expand Down
8 changes: 5 additions & 3 deletions crates/bevy_pbr/src/light_probe/irradiance_volume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ use bevy_render::{
binding_types, BindGroupLayoutEntryBuilder, Sampler, SamplerBindingType, Shader,
TextureSampleType, TextureView,
},
renderer::RenderDevice,
renderer::{RenderAdapter, RenderDevice},
texture::{FallbackImage, GpuImage},
};
use bevy_utils::default;
Expand Down Expand Up @@ -242,8 +242,9 @@ impl<'a> RenderViewIrradianceVolumeBindGroupEntries<'a> {
images: &'a RenderAssets<GpuImage>,
fallback_image: &'a FallbackImage,
render_device: &RenderDevice,
render_adapter: &RenderAdapter,
) -> RenderViewIrradianceVolumeBindGroupEntries<'a> {
if binding_arrays_are_usable(render_device) {
if binding_arrays_are_usable(render_device, render_adapter) {
RenderViewIrradianceVolumeBindGroupEntries::get_multiple(
render_view_irradiance_volumes,
images,
Expand Down Expand Up @@ -328,10 +329,11 @@ impl<'a> RenderViewIrradianceVolumeBindGroupEntries<'a> {
/// respectively.
pub(crate) fn get_bind_group_layout_entries(
render_device: &RenderDevice,
render_adapter: &RenderAdapter,
) -> [BindGroupLayoutEntryBuilder; 2] {
let mut texture_3d_binding =
binding_types::texture_3d(TextureSampleType::Float { filterable: true });
if binding_arrays_are_usable(render_device) {
if binding_arrays_are_usable(render_device, render_adapter) {
texture_3d_binding =
texture_3d_binding.count(NonZero::<u32>::new(MAX_VIEW_LIGHT_PROBES as _).unwrap());
}
Expand Down
11 changes: 8 additions & 3 deletions crates/bevy_pbr/src/light_probe/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use bevy_render::{
primitives::{Aabb, Frustum},
render_asset::RenderAssets,
render_resource::{DynamicUniformBuffer, Sampler, Shader, ShaderType, TextureView},
renderer::{RenderDevice, RenderQueue},
renderer::{RenderAdapter, RenderDevice, RenderQueue},
settings::WgpuFeatures,
sync_world::RenderEntity,
texture::{FallbackImage, GpuImage},
Expand Down Expand Up @@ -778,15 +778,20 @@ pub(crate) fn add_cubemap_texture_view<'a>(
/// enough texture bindings available in the fragment shader.
///
/// 3. If binding arrays aren't supported on the hardware, then we obviously
/// can't use them.
/// can't use them. Adreno <= 610 claims to support bindless, but seems to be
/// too buggy to be usable.
///
/// 4. If binding arrays are supported on the hardware, but they can only be
/// accessed by uniform indices, that's not good enough, and we bail out.
///
/// If binding arrays aren't usable, we disable reflection probes and limit the
/// number of irradiance volumes in the scene to 1.
pub(crate) fn binding_arrays_are_usable(render_device: &RenderDevice) -> bool {
pub(crate) fn binding_arrays_are_usable(
render_device: &RenderDevice,
render_adapter: &RenderAdapter,
) -> bool {
!cfg!(feature = "shader_format_glsl")
&& bevy_render::get_adreno_model(render_adapter).is_none_or(|model| model > 610)
&& render_device.limits().max_storage_textures_per_shader_stage
>= (STANDARD_MATERIAL_FRAGMENT_SHADER_MIN_TEXTURE_BINDINGS + MAX_VIEW_LIGHT_PROBES)
as u32
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/lightmap/lightmap.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#import bevy_pbr::mesh_bindings::mesh

#ifdef MULTIPLE_LIGHTMAPS_IN_ARRAY
@group(1) @binding(4) var lightmaps_textures: binding_array<texture_2d<f32>>;
@group(1) @binding(5) var lightmaps_samplers: binding_array<sampler>;
@group(1) @binding(4) var lightmaps_textures: binding_array<texture_2d<f32>, 4>;
@group(1) @binding(5) var lightmaps_samplers: binding_array<sampler, 4>;
#else // MULTIPLE_LIGHTMAPS_IN_ARRAY
@group(1) @binding(4) var lightmaps_texture: texture_2d<f32>;
@group(1) @binding(5) var lightmaps_sampler: sampler;
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_pbr/src/lightmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{
render_asset::RenderAssets,
render_resource::{Sampler, Shader, TextureView, WgpuSampler, WgpuTextureView},
renderer::RenderAdapter,
sync_world::MainEntity,
texture::{FallbackImage, GpuImage},
view::ViewVisibility,
Expand All @@ -71,7 +72,7 @@ pub const LIGHTMAP_SHADER_HANDLE: Handle<Shader> =
///
/// If bindless textures aren't in use, then only a single lightmap can be bound
/// at a time.
pub const LIGHTMAPS_PER_SLAB: usize = 16;
pub const LIGHTMAPS_PER_SLAB: usize = 4;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for the 4 specifically or is it just a nice number that happens to still work because it's small enough??


/// A plugin that provides an implementation of lightmaps.
pub struct LightmapPlugin;
Expand Down Expand Up @@ -332,7 +333,9 @@ impl Default for Lightmap {
impl FromWorld for RenderLightmaps {
fn from_world(world: &mut World) -> Self {
let render_device = world.resource::<RenderDevice>();
let bindless_supported = binding_arrays_are_usable(render_device);
let render_adapter = world.resource::<RenderAdapter>();

let bindless_supported = binding_arrays_are_usable(render_device, render_adapter);

RenderLightmaps {
render_lightmaps: default(),
Expand Down
9 changes: 5 additions & 4 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use bevy_render::{
RenderCommandResult, SortedRenderPhasePlugin, TrackedRenderPass,
},
render_resource::*,
renderer::{RenderDevice, RenderQueue},
renderer::{RenderAdapter, RenderDevice, RenderQueue},
texture::DefaultImageSampler,
view::{
prepare_view_targets, NoFrustumCulling, NoIndirectDrawing, RenderVisibilityRanges,
Expand Down Expand Up @@ -1484,11 +1484,12 @@ impl FromWorld for MeshPipeline {
fn from_world(world: &mut World) -> Self {
let mut system_state: SystemState<(
Res<RenderDevice>,
Res<RenderAdapter>,
Res<DefaultImageSampler>,
Res<RenderQueue>,
Res<MeshPipelineViewLayouts>,
)> = SystemState::new(world);
let (render_device, default_sampler, render_queue, view_layouts) =
let (render_device, render_adapter, default_sampler, render_queue, view_layouts) =
system_state.get_mut(world);

let clustered_forward_buffer_binding_type = render_device
Expand Down Expand Up @@ -1532,9 +1533,9 @@ impl FromWorld for MeshPipeline {
view_layouts: view_layouts.clone(),
clustered_forward_buffer_binding_type,
dummy_white_gpu_image,
mesh_layouts: MeshLayouts::new(&render_device),
mesh_layouts: MeshLayouts::new(&render_device, &render_adapter),
per_object_buffer_batch_size: GpuArrayBuffer::<MeshUniform>::batch_size(&render_device),
binding_arrays_are_usable: binding_arrays_are_usable(&render_device),
binding_arrays_are_usable: binding_arrays_are_usable(&render_device, &render_adapter),
skins_use_uniform_buffers: skin::skins_use_uniform_buffers(&render_device),
}
}
Expand Down
17 changes: 12 additions & 5 deletions crates/bevy_pbr/src/render/mesh_bindings.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
//! Bind group layout related definitions for the mesh pipeline.

use bevy_math::Mat4;
use bevy_render::{mesh::morph::MAX_MORPH_WEIGHTS, render_resource::*, renderer::RenderDevice};
use bevy_render::{
mesh::morph::MAX_MORPH_WEIGHTS,
render_resource::*,
renderer::{RenderAdapter, RenderDevice},
};

use crate::{binding_arrays_are_usable, render::skin::MAX_JOINTS, LightmapSlab};

Expand Down Expand Up @@ -194,10 +198,10 @@ impl MeshLayouts {
/// Prepare the layouts used by the default bevy [`Mesh`].
///
/// [`Mesh`]: bevy_render::prelude::Mesh
pub fn new(render_device: &RenderDevice) -> Self {
pub fn new(render_device: &RenderDevice, render_adapter: &RenderAdapter) -> Self {
MeshLayouts {
model_only: Self::model_only_layout(render_device),
lightmapped: Self::lightmapped_layout(render_device),
lightmapped: Self::lightmapped_layout(render_device, render_adapter),
skinned: Self::skinned_layout(render_device),
skinned_motion: Self::skinned_motion_layout(render_device),
morphed: Self::morphed_layout(render_device),
Expand Down Expand Up @@ -329,8 +333,11 @@ impl MeshLayouts {
)
}

fn lightmapped_layout(render_device: &RenderDevice) -> BindGroupLayout {
if binding_arrays_are_usable(render_device) {
fn lightmapped_layout(
render_device: &RenderDevice,
render_adapter: &RenderAdapter,
) -> BindGroupLayout {
if binding_arrays_are_usable(render_device, render_adapter) {
render_device.create_bind_group_layout(
"lightmapped_mesh_layout",
&BindGroupLayoutEntries::with_indices(
Expand Down
8 changes: 6 additions & 2 deletions crates/bevy_pbr/src/render/mesh_view_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,8 @@ fn layout_entries(
);

// EnvironmentMapLight
let environment_map_entries = environment_map::get_bind_group_layout_entries(render_device);
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]),
Expand All @@ -323,7 +324,7 @@ fn layout_entries(
// Irradiance volumes
if IRRADIANCE_VOLUMES_ARE_USABLE {
let irradiance_volume_entries =
irradiance_volume::get_bind_group_layout_entries(render_device);
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]),
Expand Down Expand Up @@ -493,6 +494,7 @@ pub struct MeshViewBindGroup {
pub fn prepare_mesh_view_bind_groups(
mut commands: Commands,
render_device: Res<RenderDevice>,
render_adapter: Res<RenderAdapter>,
mesh_pipeline: Res<MeshPipeline>,
shadow_samplers: Res<ShadowSamplers>,
(light_meta, global_light_meta): (Res<LightMeta>, Res<GlobalClusterableObjectMeta>),
Expand Down Expand Up @@ -607,6 +609,7 @@ pub fn prepare_mesh_view_bind_groups(
&images,
&fallback_image,
&render_device,
&render_adapter,
);

match environment_map_bind_group_entries {
Expand Down Expand Up @@ -642,6 +645,7 @@ pub fn prepare_mesh_view_bind_groups(
&images,
&fallback_image,
&render_device,
&render_adapter,
))
} else {
None
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_pbr/src/render/pbr_functions.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ fn apply_pbr_lighting(
}

let transmitted_light_contrib =
lighting::point_light(light_id, &transmissive_lighting_input);
lighting::point_light(light_id, &transmissive_lighting_input, enable_diffuse);
transmitted_light += transmitted_light_contrib * transmitted_shadow;
#endif
}
Expand Down Expand Up @@ -501,7 +501,7 @@ fn apply_pbr_lighting(
}

let transmitted_light_contrib =
lighting::spot_light(light_id, &transmissive_lighting_input);
lighting::spot_light(light_id, &transmissive_lighting_input, enable_diffuse);
transmitted_light += transmitted_light_contrib * transmitted_shadow;
#endif
}
Expand Down Expand Up @@ -557,7 +557,7 @@ fn apply_pbr_lighting(
}

let transmitted_light_contrib =
lighting::directional_light(i, &transmissive_lighting_input);
lighting::directional_light(i, &transmissive_lighting_input, enable_diffuse);
transmitted_light += transmitted_light_contrib * transmitted_shadow;
#endif
}
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_pbr/src/ssr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use bevy_render::{
ShaderStages, ShaderType, SpecializedRenderPipeline, SpecializedRenderPipelines,
TextureFormat, TextureSampleType,
},
renderer::{RenderContext, RenderDevice, RenderQueue},
renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue},
view::{ExtractedView, Msaa, ViewTarget, ViewUniformOffset},
Render, RenderApp, RenderSet,
};
Expand Down Expand Up @@ -354,6 +354,7 @@ impl FromWorld for ScreenSpaceReflectionsPipeline {
fn from_world(world: &mut World) -> Self {
let mesh_view_layouts = world.resource::<MeshPipelineViewLayouts>().clone();
let render_device = world.resource::<RenderDevice>();
let render_adapter = world.resource::<RenderAdapter>();

// Create the bind group layout.
let bind_group_layout = render_device.create_bind_group_layout(
Expand Down Expand Up @@ -404,7 +405,7 @@ impl FromWorld for ScreenSpaceReflectionsPipeline {
depth_linear_sampler,
depth_nearest_sampler,
bind_group_layout,
binding_arrays_are_usable: binding_arrays_are_usable(render_device),
binding_arrays_are_usable: binding_arrays_are_usable(render_device, render_adapter),
}
}
}
Expand Down
26 changes: 5 additions & 21 deletions crates/bevy_render/src/batching/gpu_preprocessing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,28 +354,12 @@ impl FromWorld for GpuPreprocessingSupport {
let adapter = world.resource::<RenderAdapter>();
let device = world.resource::<RenderDevice>();

// filter some Qualcomm devices on Android as they crash when using GPU preprocessing.
// Filter some Qualcomm devices on Android as they crash when using GPU
// preprocessing.
// We filter out Adreno 730 and earlier GPUs (except 720, as it's newer
// than 730).
fn is_non_supported_android_device(adapter: &RenderAdapter) -> bool {
if cfg!(target_os = "android") {
let adapter_name = adapter.get_info().name;

// Filter out Adreno 730 and earlier GPUs (except 720, as it's newer than 730)
// while also taking suffixes into account like Adreno 642L.
pcwalton marked this conversation as resolved.
Show resolved Hide resolved
let non_supported_adreno_model = |model: &str| -> bool {
let model = model
.chars()
.map_while(|c| c.to_digit(10))
.fold(0, |acc, digit| acc * 10 + digit);

model != 720 && model <= 730
};

adapter_name
.strip_prefix("Adreno (TM) ")
.is_some_and(non_supported_adreno_model)
} else {
false
}
crate::get_adreno_model(adapter).is_some_and(|model| model != 720 && model <= 730)
}

let max_supported_mode = if device.limits().max_compute_workgroup_size_x == 0 || is_non_supported_android_device(adapter)
Expand Down
22 changes: 21 additions & 1 deletion crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ use bevy_window::{PrimaryWindow, RawHandleWrapperHolder};
use extract_resource::ExtractResourcePlugin;
use globals::GlobalsPlugin;
use render_asset::RenderAssetBytesPerFrame;
use renderer::{RenderDevice, RenderQueue};
use renderer::{RenderAdapter, RenderDevice, RenderQueue};
use settings::RenderResources;
use sync_world::{
despawn_temporary_render_entities, entity_sync_system, SyncToRenderWorld, SyncWorldPlugin,
Expand Down Expand Up @@ -514,3 +514,23 @@ fn apply_extract_commands(render_world: &mut World) {
.apply_deferred(render_world);
});
}

/// If the [`RenderAdapter`] is a Qualcomm Adreno, returns its model number.
///
/// This lets us work around hardware bugs.
pub fn get_adreno_model(adapter: &RenderAdapter) -> Option<u32> {
if !cfg!(target_os = "android") {
return None;
}

let adapter_name = adapter.get_info().name;
let adreno_model = adapter_name.strip_prefix("Adreno (TM) ")?;

// Take suffixes into account (like Adreno 642L).
Some(
adreno_model
.chars()
.map_while(|c| c.to_digit(10))
.fold(0, |acc, digit| acc * 10 + digit),
)
}
Loading