From 87635cdec106e7ec52a4c8833051ad04cec4673c Mon Sep 17 00:00:00 2001 From: Kevin Chen Date: Mon, 11 May 2026 21:37:20 -0400 Subject: [PATCH 1/3] Revert "Move visibility range checking from the CPU to the GPU if `NoCpuCulling` is specified. (#23115)" This reverts commit ebfbc3f5c8f37c94cee1977e1c86fe3e515bec66. --- crates/bevy_camera/src/visibility/range.rs | 9 +-- crates/bevy_pbr/src/render/gpu_preprocess.rs | 58 +++++-------------- crates/bevy_pbr/src/render/mesh.rs | 24 ++------ .../bevy_pbr/src/render/mesh_preprocess.wgsl | 43 +++----------- crates/bevy_pbr/src/render/mesh_types.wgsl | 1 - examples/3d/visibility_range.rs | 34 ++--------- 6 files changed, 38 insertions(+), 131 deletions(-) diff --git a/crates/bevy_camera/src/visibility/range.rs b/crates/bevy_camera/src/visibility/range.rs index b57119c989171..9b9c3f8442c59 100644 --- a/crates/bevy_camera/src/visibility/range.rs +++ b/crates/bevy_camera/src/visibility/range.rs @@ -10,7 +10,7 @@ use bevy_app::{App, Plugin, PostUpdate}; use bevy_ecs::{ component::Component, entity::{Entity, EntityHashMap}, - query::{With, Without}, + query::With, reflect::ReflectComponent, resource::Resource, schedule::IntoScheduleConfigs as _, @@ -22,7 +22,7 @@ use bevy_transform::components::GlobalTransform; use bevy_utils::Parallel; use super::{check_visibility_cpu_culling, VisibilitySystems}; -use crate::{camera::Camera, primitives::Aabb, visibility::NoCpuCulling}; +use crate::{camera::Camera, primitives::Aabb}; /// A plugin that enables [`VisibilityRange`]s, which allow entities to be /// hidden or shown based on distance to the camera. @@ -243,10 +243,7 @@ pub fn check_visibility_ranges( mut visible_entity_ranges: ResMut, view_query: Query<(Entity, &GlobalTransform), With>, mut par_local: Local>>, - entity_query: Query< - (Entity, &GlobalTransform, Option<&Aabb>, &VisibilityRange), - Without, - >, + entity_query: Query<(Entity, &GlobalTransform, Option<&Aabb>, &VisibilityRange)>, ) { visible_entity_ranges.clear(); diff --git a/crates/bevy_pbr/src/render/gpu_preprocess.rs b/crates/bevy_pbr/src/render/gpu_preprocess.rs index 33617abac86dc..63b87fc482694 100644 --- a/crates/bevy_pbr/src/render/gpu_preprocess.rs +++ b/crates/bevy_pbr/src/render/gpu_preprocess.rs @@ -32,7 +32,6 @@ use bevy_ecs::{ world::{FromWorld, World}, }; use bevy_log::warn_once; -use bevy_math::Vec4; use bevy_platform::collections::HashMap; use bevy_render::{ batching::gpu_preprocessing::{ @@ -51,7 +50,7 @@ use bevy_render::{ render_resource::{ binding_types::{storage_buffer, storage_buffer_read_only, texture_2d, uniform_buffer}, BindGroup, BindGroupEntries, BindGroupLayoutDescriptor, BindGroupLayoutEntries, - BindingResource, Buffer, BufferBinding, BufferVec, CachedComputePipelineId, + BindingResource, Buffer, BufferBinding, CachedComputePipelineId, ComputePassDescriptor, ComputePipelineDescriptor, DynamicBindGroupLayoutEntries, PartialBufferVec, PipelineCache, RawBufferVec, ShaderStages, ShaderType, SparseBufferUpdateBindGroups, SparseBufferUpdateJobs, SparseBufferUpdatePipelines, @@ -60,10 +59,7 @@ use bevy_render::{ }, renderer::{RenderContext, RenderDevice, RenderQueue, ViewQuery}, settings::WgpuFeatures, - view::{ - ExtractedView, NoIndirectDrawing, RenderVisibilityRanges, RetainedViewEntity, ViewUniform, - ViewUniformOffset, ViewUniforms, - }, + view::{ExtractedView, NoIndirectDrawing, RetainedViewEntity, ViewUniform, ViewUniformOffset, ViewUniforms}, GpuResourceAppExt, Render, RenderApp, RenderSystems, }; use bevy_shader::Shader; @@ -1267,11 +1263,11 @@ impl FromWorld for PreprocessPipelines { let gpu_early_occlusion_culling_bind_group_layout_entries = gpu_occlusion_culling_bind_group_layout_entries().extend_with_indices(( ( - 12, + 11, storage_buffer::(/*has_dynamic_offset=*/ false), ), ( - 13, + 12, storage_buffer::( /*has_dynamic_offset=*/ false, ), @@ -1279,7 +1275,7 @@ impl FromWorld for PreprocessPipelines { )); let gpu_late_occlusion_culling_bind_group_layout_entries = gpu_occlusion_culling_bind_group_layout_entries().extend_with_indices((( - 13, + 12, storage_buffer_read_only::( /*has_dynamic_offset=*/ false, ), @@ -1470,11 +1466,6 @@ fn gpu_culling_bind_group_layout_entries() -> DynamicBindGroupLayoutEntries { 9, storage_buffer_read_only::(/* has_dynamic_offset= */ false), ), - // `visibility_ranges` - ( - 10, - storage_buffer_read_only::(/* has_dynamic_offset= */ false), - ), )) } @@ -1485,7 +1476,7 @@ fn gpu_occlusion_culling_bind_group_layout_entries() -> DynamicBindGroupLayoutEn uniform_buffer::(/*has_dynamic_offset=*/ false), ), ( - 11, + 10, texture_2d(TextureSampleType::Float { filterable: true }), ), )) @@ -1805,7 +1796,6 @@ pub fn prepare_preprocess_bind_groups( indirect_parameters_buffers: Res, bin_unpacking_buffers: Res, mesh_culling_data_buffer: Res, - visibility_ranges: Res, view_uniforms: Res, previous_view_uniforms: Res, pipelines: Res, @@ -1866,7 +1856,6 @@ pub fn prepare_preprocess_bind_groups( pipeline_cache: &pipeline_cache, phase_indirect_parameters_buffers, mesh_culling_data_buffer: &mesh_culling_data_buffer, - visibility_range_data_buffer: visibility_ranges.buffer(), view_uniforms: &view_uniforms, previous_view_uniforms: &previous_view_uniforms, pipelines: &pipelines, @@ -1976,9 +1965,6 @@ struct PreprocessBindGroupBuilder<'a> { phase_indirect_parameters_buffers: &'a UntypedPhaseIndirectParametersBuffers, /// The GPU buffer that stores the information needed to cull each mesh. mesh_culling_data_buffer: &'a MeshCullingDataBuffer, - /// The device buffer that stores the information needed to process - /// visibility ranges on the GPU. - visibility_range_data_buffer: &'a BufferVec, /// The GPU buffer that stores information about the view. view_uniforms: &'a ViewUniforms, /// The GPU buffer that stores information about the view from last frame. @@ -2095,7 +2081,6 @@ impl<'a> PreprocessBindGroupBuilder<'a> { late_indexed_work_item_buffer: &UninitBufferVec, ) -> Option { let mesh_culling_data_buffer = self.mesh_culling_data_buffer.buffer()?; - let visibility_range_binding = self.visibility_range_data_buffer.binding()?; let view_uniforms_binding = self.view_uniforms.uniforms.binding()?; let previous_view_buffer = self.previous_view_uniforms.uniforms.buffer()?; @@ -2150,9 +2135,8 @@ impl<'a> PreprocessBindGroupBuilder<'a> { (7, indexed_cpu_metadata_buffer.as_entire_binding()), (8, indexed_gpu_metadata_buffer.as_entire_binding()), (9, mesh_culling_data_buffer.as_entire_binding()), - (10, visibility_range_binding.clone()), (0, view_uniforms_binding.clone()), - (11, &view_depth_pyramid.all_mips), + (10, &view_depth_pyramid.all_mips), ( 2, BufferBinding { @@ -2162,7 +2146,7 @@ impl<'a> PreprocessBindGroupBuilder<'a> { }, ), ( - 12, + 11, BufferBinding { buffer: late_indexed_work_item_gpu_buffer, offset: 0, @@ -2170,7 +2154,7 @@ impl<'a> PreprocessBindGroupBuilder<'a> { }, ), ( - 13, + 12, BufferBinding { buffer: late_indexed_indirect_parameters_buffer, offset: 0, @@ -2197,7 +2181,6 @@ impl<'a> PreprocessBindGroupBuilder<'a> { late_non_indexed_work_item_buffer: &UninitBufferVec, ) -> Option { let mesh_culling_data_buffer = self.mesh_culling_data_buffer.buffer()?; - let visibility_range_binding = self.visibility_range_data_buffer.binding()?; let view_uniforms_binding = self.view_uniforms.uniforms.binding()?; let previous_view_buffer = self.previous_view_uniforms.uniforms.buffer()?; @@ -2252,9 +2235,8 @@ impl<'a> PreprocessBindGroupBuilder<'a> { (7, non_indexed_cpu_metadata_buffer.as_entire_binding()), (8, non_indexed_gpu_metadata_buffer.as_entire_binding()), (9, mesh_culling_data_buffer.as_entire_binding()), - (10, visibility_range_binding.clone()), (0, view_uniforms_binding.clone()), - (11, &view_depth_pyramid.all_mips), + (10, &view_depth_pyramid.all_mips), ( 2, BufferBinding { @@ -2264,7 +2246,7 @@ impl<'a> PreprocessBindGroupBuilder<'a> { }, ), ( - 12, + 11, BufferBinding { buffer: late_non_indexed_work_item_buffer, offset: 0, @@ -2272,7 +2254,7 @@ impl<'a> PreprocessBindGroupBuilder<'a> { }, ), ( - 13, + 12, BufferBinding { buffer: late_non_indexed_indirect_parameters_buffer, offset: 0, @@ -2298,7 +2280,6 @@ impl<'a> PreprocessBindGroupBuilder<'a> { late_indexed_work_item_buffer: &UninitBufferVec, ) -> Option { let mesh_culling_data_buffer = self.mesh_culling_data_buffer.buffer()?; - let visibility_range_binding = self.visibility_range_data_buffer.binding()?; let view_uniforms_binding = self.view_uniforms.uniforms.binding()?; let previous_view_buffer = self.previous_view_uniforms.uniforms.buffer()?; @@ -2351,9 +2332,8 @@ impl<'a> PreprocessBindGroupBuilder<'a> { (7, indexed_cpu_metadata_buffer.as_entire_binding()), (8, indexed_gpu_metadata_buffer.as_entire_binding()), (9, mesh_culling_data_buffer.as_entire_binding()), - (10, visibility_range_binding.clone()), (0, view_uniforms_binding.clone()), - (11, &view_depth_pyramid.all_mips), + (10, &view_depth_pyramid.all_mips), ( 2, BufferBinding { @@ -2363,7 +2343,7 @@ impl<'a> PreprocessBindGroupBuilder<'a> { }, ), ( - 13, + 12, BufferBinding { buffer: late_indexed_indirect_parameters_buffer, offset: 0, @@ -2389,7 +2369,6 @@ impl<'a> PreprocessBindGroupBuilder<'a> { late_non_indexed_work_item_buffer: &UninitBufferVec, ) -> Option { let mesh_culling_data_buffer = self.mesh_culling_data_buffer.buffer()?; - let visibility_range_binding = self.visibility_range_data_buffer.binding()?; let view_uniforms_binding = self.view_uniforms.uniforms.binding()?; let previous_view_buffer = self.previous_view_uniforms.uniforms.buffer()?; @@ -2442,9 +2421,8 @@ impl<'a> PreprocessBindGroupBuilder<'a> { (7, non_indexed_cpu_metadata_buffer.as_entire_binding()), (8, non_indexed_gpu_metadata_buffer.as_entire_binding()), (9, mesh_culling_data_buffer.as_entire_binding()), - (10, visibility_range_binding.clone()), (0, view_uniforms_binding.clone()), - (11, &view_depth_pyramid.all_mips), + (10, &view_depth_pyramid.all_mips), ( 2, BufferBinding { @@ -2454,7 +2432,7 @@ impl<'a> PreprocessBindGroupBuilder<'a> { }, ), ( - 13, + 12, BufferBinding { buffer: late_non_indexed_indirect_parameters_buffer, offset: 0, @@ -2494,7 +2472,6 @@ impl<'a> PreprocessBindGroupBuilder<'a> { indexed_work_item_buffer: &PartialBufferVec, ) -> Option { let mesh_culling_data_buffer = self.mesh_culling_data_buffer.buffer()?; - let visibility_range_binding = self.visibility_range_data_buffer.binding()?; let view_uniforms_binding = self.view_uniforms.uniforms.binding()?; match ( @@ -2544,7 +2521,6 @@ impl<'a> PreprocessBindGroupBuilder<'a> { (7, indexed_cpu_metadata_buffer.as_entire_binding()), (8, indexed_gpu_metadata_buffer.as_entire_binding()), (9, mesh_culling_data_buffer.as_entire_binding()), - (10, visibility_range_binding.clone()), (0, view_uniforms_binding.clone()), )), ), @@ -2561,7 +2537,6 @@ impl<'a> PreprocessBindGroupBuilder<'a> { non_indexed_work_item_buffer: &PartialBufferVec, ) -> Option { let mesh_culling_data_buffer = self.mesh_culling_data_buffer.buffer()?; - let visibility_range_binding = self.visibility_range_data_buffer.binding()?; let view_uniforms_binding = self.view_uniforms.uniforms.binding()?; match ( @@ -2611,7 +2586,6 @@ impl<'a> PreprocessBindGroupBuilder<'a> { (7, non_indexed_cpu_metadata_buffer.as_entire_binding()), (8, non_indexed_gpu_metadata_buffer.as_entire_binding()), (9, mesh_culling_data_buffer.as_entire_binding()), - (10, visibility_range_binding.clone()), (0, view_uniforms_binding.clone()), )), ), diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 253540c6dbcb9..754b937e14a76 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -707,12 +707,6 @@ bitflags::bitflags! { /// /// This will be `u16::MAX` if this mesh has no LOD. const LOD_INDEX_MASK = (1 << 16) - 1; - /// Whether visibility ranges use the center of the AABB to compute - /// distance from the camera. - /// - /// If false, this uses distance from the world-space translation of the - /// mesh instead. - const AABB_BASED_VISIBILITY_RANGE = 1 << 27; /// Disables frustum culling for this mesh. /// /// This corresponds to the @@ -732,7 +726,6 @@ impl MeshFlags { fn from_components( transform: &GlobalTransform, lod_index: Option, - visibility_range: Option<&VisibilityRange>, no_frustum_culling: bool, not_shadow_receiver: bool, transmitted_receiver: bool, @@ -742,9 +735,6 @@ impl MeshFlags { } else { MeshFlags::SHADOW_RECEIVER }; - if visibility_range.is_some_and(|visibility_range| visibility_range.use_aabb) { - mesh_flags |= MeshFlags::AABB_BASED_VISIBILITY_RANGE; - } if no_frustum_culling { mesh_flags |= MeshFlags::NO_FRUSTUM_CULLING; } @@ -1774,7 +1764,7 @@ pub fn extract_meshes_for_cpu_building( Has, Has, Has, - Option<&VisibilityRange>, + Has, Option<&RenderLayers>, )>, >, @@ -1802,14 +1792,13 @@ pub fn extract_meshes_for_cpu_building( } let mut lod_index = None; - if visibility_range.is_some() { + if visibility_range { lod_index = render_visibility_ranges.lod_index_for_entity(entity.into()); } let mesh_flags = MeshFlags::from_components( transform, lod_index, - visibility_range, no_frustum_culling, not_shadow_receiver, transmitted_receiver, @@ -1885,8 +1874,8 @@ type GpuMeshExtractionQuery = ( Has, Has, Has, + Has, ), - Option>, Option>, ); @@ -1920,8 +1909,8 @@ pub fn extract_meshes_for_gpu_building( Changed, Changed, Changed, + Changed, )>, - Changed, Changed, )>, >, @@ -2098,8 +2087,8 @@ fn extract_mesh_for_gpu_building( not_shadow_caster, no_automatic_batching, no_cpu_culling, + has_visibility_range, ), - visibility_range, render_layers, ): ::Item<'_, '_>, render_visibility_ranges: &RenderVisibilityRanges, @@ -2115,7 +2104,7 @@ fn extract_mesh_for_gpu_building( // If the entity has a visibility range, determine its LOD index. let mut lod_index = None; - if visibility_range.is_some() { + if has_visibility_range { lod_index = render_visibility_ranges.lod_index_for_entity(entity.into()); } @@ -2123,7 +2112,6 @@ fn extract_mesh_for_gpu_building( let mesh_flags = MeshFlags::from_components( transform, lod_index, - visibility_range, no_frustum_culling, not_shadow_receiver, transmitted_receiver, diff --git a/crates/bevy_pbr/src/render/mesh_preprocess.wgsl b/crates/bevy_pbr/src/render/mesh_preprocess.wgsl index 496cd6b6f84ab..f31399fb4c9d7 100644 --- a/crates/bevy_pbr/src/render/mesh_preprocess.wgsl +++ b/crates/bevy_pbr/src/render/mesh_preprocess.wgsl @@ -17,10 +17,7 @@ #import bevy_pbr::mesh_preprocess_types::{ IndirectParametersCpuMetadata, IndirectParametersGpuMetadata, MeshInput, PreprocessWorkItem } -#import bevy_pbr::mesh_types::{ - Mesh, MESH_FLAGS_AABB_BASED_VISIBILITY_RANGE_BIT, MESH_FLAGS_NO_FRUSTUM_CULLING_BIT, - MESH_FLAGS_VISIBILITY_RANGE_INDEX_BITS -} +#import bevy_pbr::mesh_types::{Mesh, MESH_FLAGS_NO_FRUSTUM_CULLING_BIT} #import bevy_pbr::mesh_view_bindings::view #import bevy_pbr::occlusion_culling #import bevy_pbr::prepass_bindings::previous_view_uniforms @@ -96,23 +93,21 @@ struct Immediates { // // At the moment, this consists only of AABBs. @group(0) @binding(9) var mesh_culling_data: array; - -@group(0) @binding(10) var visibility_ranges: array>; #endif // FRUSTUM_CULLING #ifdef OCCLUSION_CULLING -@group(0) @binding(11) var depth_pyramid: texture_2d; +@group(0) @binding(10) var depth_pyramid: texture_2d; #ifdef EARLY_PHASE -@group(0) @binding(12) var late_preprocess_work_items: +@group(0) @binding(11) var late_preprocess_work_items: array; -@group(0) @binding(13) var late_preprocess_work_item_indirect_parameters: +@group(0) @binding(12) var late_preprocess_work_item_indirect_parameters: array; #endif // EARLY_PHASE #ifdef LATE_PHASE -@group(0) @binding(13) var late_preprocess_work_item_indirect_parameters: +@group(0) @binding(12) var late_preprocess_work_item_indirect_parameters: array; #endif // LATE_PHASE @@ -194,8 +189,8 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3) { let world_from_local_affine_transpose = current_input[input_index].world_from_local; let world_from_local = maths::affine3_to_square(world_from_local_affine_transpose); -#ifdef FRUSTUM_CULLING // Frustum cull if necessary. +#ifdef FRUSTUM_CULLING if ((current_input[input_index].flags & MESH_FLAGS_NO_FRUSTUM_CULLING_BIT) == 0u) { let aabb_center = mesh_culling_data[input_index].aabb_center.xyz; let aabb_half_extents = mesh_culling_data[input_index].aabb_half_extents.xyz; @@ -206,31 +201,7 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3) { return; } } - - // Visibility range cull if necessary. - let visibility_buffer_array_len = arrayLength(&visibility_ranges); - let visibility_buffer_index = - current_input[input_index].flags & MESH_FLAGS_VISIBILITY_RANGE_INDEX_BITS; - if (visibility_buffer_index < visibility_buffer_array_len) { - let lod_range = visibility_ranges[visibility_buffer_index]; - - // If we're using the AABB as the mesh center, determine its world space position. - // Otherwise, just use the center of the transform. - var world_pos: vec3; - if ((current_input[input_index].flags & MESH_FLAGS_AABB_BASED_VISIBILITY_RANGE_BIT) != 0u) { - let aabb_center = mesh_culling_data[input_index].aabb_center.xyz; - world_pos = (world_from_local * vec4(aabb_center, 1.0)).xyz; - } else { - world_pos = world_from_local[3].xyz; - } - - let camera_distance = length(position_world_to_view(world_pos)); - // `x` is the minimum range; `w` is the largest range. - if (camera_distance < lod_range.x || camera_distance >= lod_range.w) { - return; - } - } -#endif // FRUSTUM_CULLING +#endif // See whether the `MeshInputUniform` was updated on this frame. If it // wasn't, then we know the transforms of this mesh must be identical to diff --git a/crates/bevy_pbr/src/render/mesh_types.wgsl b/crates/bevy_pbr/src/render/mesh_types.wgsl index 80b59b6ee11d6..993185d5b35f9 100644 --- a/crates/bevy_pbr/src/render/mesh_types.wgsl +++ b/crates/bevy_pbr/src/render/mesh_types.wgsl @@ -74,7 +74,6 @@ struct MorphAttributes { // [2^0, 2^16) const MESH_FLAGS_VISIBILITY_RANGE_INDEX_BITS: u32 = (1u << 16u) - 1u; -const MESH_FLAGS_AABB_BASED_VISIBILITY_RANGE_BIT: u32 = 1u << 27u; const MESH_FLAGS_NO_FRUSTUM_CULLING_BIT: u32 = 1u << 28u; const MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u << 29u; const MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT: u32 = 1u << 30u; diff --git a/examples/3d/visibility_range.rs b/examples/3d/visibility_range.rs index 2ce0d221eb9c8..5ea3d32e5ac0b 100644 --- a/examples/3d/visibility_range.rs +++ b/examples/3d/visibility_range.rs @@ -3,7 +3,7 @@ use std::f32::consts::PI; use bevy::{ - camera::visibility::{NoCpuCulling, VisibilityRange}, + camera::visibility::VisibilityRange, core_pipeline::prepass::{DepthPrepass, NormalPrepass}, input::mouse::MouseWheel, light::{light_consts::lux::FULL_DAYLIGHT, CascadeShadowConfigBuilder}, @@ -11,8 +11,6 @@ use bevy::{ prelude::*, }; -use argh::FromArgs; - // Where the camera is focused. const CAMERA_FOCAL_POINT: Vec3 = vec3(0.0, 0.3, 0.0); // Speed in units per frame. @@ -70,20 +68,8 @@ struct AppStatus { prepass: bool, } -/// Demonstrates visibility ranges, also known as HLODs -#[derive(FromArgs, Resource)] -struct Args { - /// whether to use GPU culling only - #[argh(switch)] - no_cpu_culling: bool, -} - +// Sets up the app. fn main() { - #[cfg(not(target_arch = "wasm32"))] - let args: Args = argh::from_env(); - #[cfg(target_arch = "wasm32")] - let args = Args::from_args(&[], &[]).unwrap(); - App::new() .add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { @@ -93,7 +79,6 @@ fn main() { ..default() })) .init_resource::() - .insert_resource(args) .add_systems(Startup, setup) .add_systems( Update, @@ -191,7 +176,6 @@ fn set_visibility_ranges( mut commands: Commands, mut new_meshes: Query>, children: Query<(Option<&ChildOf>, Option<&MainModel>)>, - args: Res, ) { // Loop over each newly-added mesh. for new_mesh in new_meshes.iter_mut() { @@ -211,22 +195,16 @@ fn set_visibility_ranges( // Add the `VisibilityRange` component. match main_model { Some(MainModel::HighPoly) => { - let mut entity_commands = commands.entity(new_mesh); - entity_commands + commands + .entity(new_mesh) .insert(NORMAL_VISIBILITY_RANGE_HIGH_POLY.clone()) .insert(MainModel::HighPoly); - if args.no_cpu_culling { - entity_commands.insert(NoCpuCulling); - } } Some(MainModel::LowPoly) => { - let mut entity_commands = commands.entity(new_mesh); - entity_commands + commands + .entity(new_mesh) .insert(NORMAL_VISIBILITY_RANGE_LOW_POLY.clone()) .insert(MainModel::LowPoly); - if args.no_cpu_culling { - entity_commands.insert(NoCpuCulling); - } } None => {} } From c2d8b9cea8394a3ce1a07cb37c9193083cbe4c03 Mon Sep 17 00:00:00 2001 From: Kevin Chen Date: Mon, 11 May 2026 21:40:15 -0400 Subject: [PATCH 2/3] fmt --- crates/bevy_pbr/src/render/gpu_preprocess.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/bevy_pbr/src/render/gpu_preprocess.rs b/crates/bevy_pbr/src/render/gpu_preprocess.rs index 63b87fc482694..7e64bebb567c3 100644 --- a/crates/bevy_pbr/src/render/gpu_preprocess.rs +++ b/crates/bevy_pbr/src/render/gpu_preprocess.rs @@ -50,16 +50,18 @@ use bevy_render::{ render_resource::{ binding_types::{storage_buffer, storage_buffer_read_only, texture_2d, uniform_buffer}, BindGroup, BindGroupEntries, BindGroupLayoutDescriptor, BindGroupLayoutEntries, - BindingResource, Buffer, BufferBinding, CachedComputePipelineId, - ComputePassDescriptor, ComputePipelineDescriptor, DynamicBindGroupLayoutEntries, - PartialBufferVec, PipelineCache, RawBufferVec, ShaderStages, ShaderType, - SparseBufferUpdateBindGroups, SparseBufferUpdateJobs, SparseBufferUpdatePipelines, - SpecializedComputePipeline, SpecializedComputePipelines, TextureSampleType, - UninitBufferVec, + BindingResource, Buffer, BufferBinding, CachedComputePipelineId, ComputePassDescriptor, + ComputePipelineDescriptor, DynamicBindGroupLayoutEntries, PartialBufferVec, PipelineCache, + RawBufferVec, ShaderStages, ShaderType, SparseBufferUpdateBindGroups, + SparseBufferUpdateJobs, SparseBufferUpdatePipelines, SpecializedComputePipeline, + SpecializedComputePipelines, TextureSampleType, UninitBufferVec, }, renderer::{RenderContext, RenderDevice, RenderQueue, ViewQuery}, settings::WgpuFeatures, - view::{ExtractedView, NoIndirectDrawing, RetainedViewEntity, ViewUniform, ViewUniformOffset, ViewUniforms}, + view::{ + ExtractedView, NoIndirectDrawing, RetainedViewEntity, ViewUniform, ViewUniformOffset, + ViewUniforms, + }, GpuResourceAppExt, Render, RenderApp, RenderSystems, }; use bevy_shader::Shader; From 497b25bdd66c56239c24a9e4e8bdd43b0788f334 Mon Sep 17 00:00:00 2001 From: Kevin Chen Date: Mon, 11 May 2026 22:03:28 -0400 Subject: [PATCH 3/3] keep comment under ifdef, place visibility_range back in prior place --- crates/bevy_pbr/src/render/mesh.rs | 8 ++++---- crates/bevy_pbr/src/render/mesh_preprocess.wgsl | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 754b937e14a76..9658abc3392b8 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1874,8 +1874,8 @@ type GpuMeshExtractionQuery = ( Has, Has, Has, - Has, ), + Has, Option>, ); @@ -1909,8 +1909,8 @@ pub fn extract_meshes_for_gpu_building( Changed, Changed, Changed, - Changed, )>, + Changed, Changed, )>, >, @@ -2087,8 +2087,8 @@ fn extract_mesh_for_gpu_building( not_shadow_caster, no_automatic_batching, no_cpu_culling, - has_visibility_range, ), + visibility_range, render_layers, ): ::Item<'_, '_>, render_visibility_ranges: &RenderVisibilityRanges, @@ -2104,7 +2104,7 @@ fn extract_mesh_for_gpu_building( // If the entity has a visibility range, determine its LOD index. let mut lod_index = None; - if has_visibility_range { + if visibility_range { lod_index = render_visibility_ranges.lod_index_for_entity(entity.into()); } diff --git a/crates/bevy_pbr/src/render/mesh_preprocess.wgsl b/crates/bevy_pbr/src/render/mesh_preprocess.wgsl index f31399fb4c9d7..4923803ed6339 100644 --- a/crates/bevy_pbr/src/render/mesh_preprocess.wgsl +++ b/crates/bevy_pbr/src/render/mesh_preprocess.wgsl @@ -189,8 +189,8 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3) { let world_from_local_affine_transpose = current_input[input_index].world_from_local; let world_from_local = maths::affine3_to_square(world_from_local_affine_transpose); - // Frustum cull if necessary. #ifdef FRUSTUM_CULLING + // Frustum cull if necessary. if ((current_input[input_index].flags & MESH_FLAGS_NO_FRUSTUM_CULLING_BIT) == 0u) { let aabb_center = mesh_culling_data[input_index].aabb_center.xyz; let aabb_half_extents = mesh_culling_data[input_index].aabb_half_extents.xyz;