Skip to content

Commit 24baf32

Browse files
authored
Allowlist mali drivers for gpu preprocessing support. (#18769)
Fixes #17591 Looking at the arm downloads page, "r48p0" is a version number that increments, where rXX is the major version and pX seems to be a patch version. Take the conservative approach here that we know gpu preprocessing is working on at least version 48 and presumably higher. The assumption here is that the driver_info string will be reported similarly on non-pixel devices.
1 parent 31bb878 commit 24baf32

File tree

3 files changed

+55
-30
lines changed

3 files changed

+55
-30
lines changed

crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
88
use core::array;
99

10+
use crate::core_3d::{
11+
graph::{Core3d, Node3d},
12+
prepare_core_3d_depth_textures,
13+
};
1014
use bevy_app::{App, Plugin};
1115
use bevy_asset::{load_internal_asset, weak_handle, Handle};
1216
use bevy_derive::{Deref, DerefMut};
@@ -21,6 +25,7 @@ use bevy_ecs::{
2125
world::{FromWorld, World},
2226
};
2327
use bevy_math::{uvec2, UVec2, Vec4Swizzles as _};
28+
use bevy_render::batching::gpu_preprocessing::GpuPreprocessingSupport;
2429
use bevy_render::{
2530
experimental::occlusion_culling::{
2631
OcclusionCulling, OcclusionCullingSubview, OcclusionCullingSubviewEntities,
@@ -30,23 +35,19 @@ use bevy_render::{
3035
binding_types::{sampler, texture_2d, texture_2d_multisampled, texture_storage_2d},
3136
BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries,
3237
CachedComputePipelineId, ComputePassDescriptor, ComputePipeline, ComputePipelineDescriptor,
33-
DownlevelFlags, Extent3d, IntoBinding, PipelineCache, PushConstantRange, Sampler,
34-
SamplerBindingType, SamplerDescriptor, Shader, ShaderStages, SpecializedComputePipeline,
38+
Extent3d, IntoBinding, PipelineCache, PushConstantRange, Sampler, SamplerBindingType,
39+
SamplerDescriptor, Shader, ShaderStages, SpecializedComputePipeline,
3540
SpecializedComputePipelines, StorageTextureAccess, TextureAspect, TextureDescriptor,
3641
TextureDimension, TextureFormat, TextureSampleType, TextureUsages, TextureView,
3742
TextureViewDescriptor, TextureViewDimension,
3843
},
39-
renderer::{RenderAdapter, RenderContext, RenderDevice},
44+
renderer::{RenderContext, RenderDevice},
4045
texture::TextureCache,
4146
view::{ExtractedView, NoIndirectDrawing, ViewDepthTexture},
4247
Render, RenderApp, RenderSet,
4348
};
4449
use bitflags::bitflags;
45-
46-
use crate::core_3d::{
47-
graph::{Core3d, Node3d},
48-
prepare_core_3d_depth_textures,
49-
};
50+
use tracing::debug;
5051

5152
/// Identifies the `downsample_depth.wgsl` shader.
5253
pub const DOWNSAMPLE_DEPTH_SHADER_HANDLE: Handle<Shader> =
@@ -325,26 +326,14 @@ pub struct DownsampleDepthPipelines {
325326
sampler: Sampler,
326327
}
327328

328-
fn supports_compute_shaders(device: &RenderDevice, adapter: &RenderAdapter) -> bool {
329-
adapter
330-
.get_downlevel_capabilities()
331-
.flags
332-
.contains(DownlevelFlags::COMPUTE_SHADERS)
333-
// Even if the adapter supports compute, we might be simulating a lack of
334-
// compute via device limits (see `WgpuSettingsPriority::WebGL2` and
335-
// `wgpu::Limits::downlevel_webgl2_defaults()`). This will have set all the
336-
// `max_compute_*` limits to zero, so we arbitrarily pick one as a canary.
337-
&& (device.limits().max_compute_workgroup_storage_size != 0)
338-
}
339-
340329
/// Creates the [`DownsampleDepthPipelines`] if downsampling is supported on the
341330
/// current platform.
342331
fn create_downsample_depth_pipelines(
343332
mut commands: Commands,
344333
render_device: Res<RenderDevice>,
345-
render_adapter: Res<RenderAdapter>,
346334
pipeline_cache: Res<PipelineCache>,
347335
mut specialized_compute_pipelines: ResMut<SpecializedComputePipelines<DownsampleDepthPipeline>>,
336+
gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
348337
mut has_run: Local<bool>,
349338
) {
350339
// Only run once.
@@ -356,9 +345,8 @@ fn create_downsample_depth_pipelines(
356345
}
357346
*has_run = true;
358347

359-
// If we don't have compute shaders, we can't invoke the downsample depth
360-
// compute shader.
361-
if !supports_compute_shaders(&render_device, &render_adapter) {
348+
if !gpu_preprocessing_support.is_culling_supported() {
349+
debug!("Downsample depth is not supported on this platform.");
362350
return;
363351
}
364352

crates/bevy_render/src/batching/gpu_preprocessing.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use bytemuck::{Pod, Zeroable};
2020
use encase::{internal::WriteInto, ShaderSize};
2121
use indexmap::IndexMap;
2222
use nonmax::NonMaxU32;
23-
use tracing::error;
23+
use tracing::{error, info};
2424
use wgpu::{BindingResource, BufferUsages, DownlevelFlags, Features};
2525

2626
use crate::{
@@ -1093,12 +1093,13 @@ impl FromWorld for GpuPreprocessingSupport {
10931093
let adapter = world.resource::<RenderAdapter>();
10941094
let device = world.resource::<RenderDevice>();
10951095

1096-
// Filter some Qualcomm devices on Android as they crash when using GPU
1097-
// preprocessing.
1098-
// We filter out Adreno 730 and earlier GPUs (except 720, as it's newer
1099-
// than 730).
1096+
// Filter Android drivers that are incompatible with GPU preprocessing:
1097+
// - We filter out Adreno 730 and earlier GPUs (except 720, as it's newer
1098+
// than 730).
1099+
// - We filter out Mali GPUs with driver versions lower than 48.
11001100
fn is_non_supported_android_device(adapter: &RenderAdapter) -> bool {
11011101
crate::get_adreno_model(adapter).is_some_and(|model| model != 720 && model <= 730)
1102+
|| crate::get_mali_driver_version(adapter).is_some_and(|version| version < 48)
11021103
}
11031104

11041105
let culling_feature_support = device.features().contains(
@@ -1107,18 +1108,31 @@ impl FromWorld for GpuPreprocessingSupport {
11071108
| Features::PUSH_CONSTANTS,
11081109
);
11091110
// Depth downsampling for occlusion culling requires 12 textures
1110-
let limit_support = device.limits().max_storage_textures_per_shader_stage >= 12;
1111+
let limit_support = device.limits().max_storage_textures_per_shader_stage >= 12 &&
1112+
// Even if the adapter supports compute, we might be simulating a lack of
1113+
// compute via device limits (see `WgpuSettingsPriority::WebGL2` and
1114+
// `wgpu::Limits::downlevel_webgl2_defaults()`). This will have set all the
1115+
// `max_compute_*` limits to zero, so we arbitrarily pick one as a canary.
1116+
device.limits().max_compute_workgroup_storage_size != 0;
1117+
11111118
let downlevel_support = adapter.get_downlevel_capabilities().flags.contains(
1119+
DownlevelFlags::COMPUTE_SHADERS |
11121120
DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW
11131121
);
11141122

11151123
let max_supported_mode = if device.limits().max_compute_workgroup_size_x == 0
11161124
|| is_non_supported_android_device(adapter)
11171125
{
1126+
info!(
1127+
"GPU preprocessing is not supported on this device. \
1128+
Falling back to CPU preprocessing.",
1129+
);
11181130
GpuPreprocessingMode::None
11191131
} else if !(culling_feature_support && limit_support && downlevel_support) {
1132+
info!("Some GPU preprocessing are limited on this device.");
11201133
GpuPreprocessingMode::PreprocessingOnly
11211134
} else {
1135+
info!("GPU preprocessing is fully supported on this device.");
11221136
GpuPreprocessingMode::Culling
11231137
};
11241138

crates/bevy_render/src/lib.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,3 +584,26 @@ pub fn get_adreno_model(adapter: &RenderAdapter) -> Option<u32> {
584584
.fold(0, |acc, digit| acc * 10 + digit),
585585
)
586586
}
587+
588+
/// Get the Mali driver version if the adapter is a Mali GPU.
589+
pub fn get_mali_driver_version(adapter: &RenderAdapter) -> Option<u32> {
590+
if !cfg!(target_os = "android") {
591+
return None;
592+
}
593+
594+
let driver_name = adapter.get_info().name;
595+
if !driver_name.contains("Mali") {
596+
return None;
597+
}
598+
let driver_info = adapter.get_info().driver_info;
599+
if let Some(start_pos) = driver_info.find("v1.r") {
600+
if let Some(end_pos) = driver_info[start_pos..].find('p') {
601+
let start_idx = start_pos + 4; // Skip "v1.r"
602+
let end_idx = start_pos + end_pos;
603+
604+
return driver_info[start_idx..end_idx].parse::<u32>().ok();
605+
}
606+
}
607+
608+
None
609+
}

0 commit comments

Comments
 (0)