diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 2fb0cfac437b1..6aee87d2135f5 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -69,7 +69,7 @@ use bevy_render::{ batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport}, mesh::allocator::SlabId, render_phase::PhaseItemBinKey, - view::GpuCulling, + view::NoIndirectDrawing, }; pub use camera_3d::*; pub use main_opaque_pass_3d_node::*; @@ -569,20 +569,20 @@ pub fn extract_core_3d_camera_phases( mut alpha_mask_3d_phases: ResMut>, mut transmissive_3d_phases: ResMut>, mut transparent_3d_phases: ResMut>, - cameras_3d: Extract), With>>, + cameras_3d: Extract), With>>, mut live_entities: Local, gpu_preprocessing_support: Res, ) { live_entities.clear(); - for (entity, camera, has_gpu_culling) in &cameras_3d { + for (entity, camera, no_indirect_drawing) in &cameras_3d { if !camera.is_active { continue; } // If GPU culling is in use, use it (and indirect mode); otherwise, just // preprocess the meshes. - let gpu_preprocessing_mode = gpu_preprocessing_support.min(if has_gpu_culling { + let gpu_preprocessing_mode = gpu_preprocessing_support.min(if !no_indirect_drawing { GpuPreprocessingMode::Culling } else { GpuPreprocessingMode::PreprocessingOnly @@ -616,7 +616,7 @@ pub fn extract_camera_prepass_phase( ( RenderEntity, &Camera, - Has, + Has, Has, Has, Has, @@ -633,7 +633,7 @@ pub fn extract_camera_prepass_phase( for ( entity, camera, - gpu_culling, + no_indirect_drawing, depth_prepass, normal_prepass, motion_vector_prepass, @@ -646,7 +646,7 @@ pub fn extract_camera_prepass_phase( // If GPU culling is in use, use it (and indirect mode); otherwise, just // preprocess the meshes. - let gpu_preprocessing_mode = gpu_preprocessing_support.min(if gpu_culling { + let gpu_preprocessing_mode = gpu_preprocessing_support.min(if !no_indirect_drawing { GpuPreprocessingMode::Culling } else { GpuPreprocessingMode::PreprocessingOnly diff --git a/crates/bevy_pbr/src/render/gpu_preprocess.rs b/crates/bevy_pbr/src/render/gpu_preprocess.rs index dd09438eb706f..434ed64135a2e 100644 --- a/crates/bevy_pbr/src/render/gpu_preprocess.rs +++ b/crates/bevy_pbr/src/render/gpu_preprocess.rs @@ -33,7 +33,7 @@ use bevy_render::{ SpecializedComputePipeline, SpecializedComputePipelines, }, renderer::{RenderContext, RenderDevice, RenderQueue}, - view::{GpuCulling, ViewUniform, ViewUniformOffset, ViewUniforms}, + view::{NoIndirectDrawing, ViewUniform, ViewUniformOffset, ViewUniforms}, Render, RenderApp, RenderSet, }; use bevy_utils::tracing::warn; @@ -70,7 +70,7 @@ pub struct GpuPreprocessNode { Entity, Read, Read, - Has, + Has, ), Without, >, @@ -202,7 +202,7 @@ impl Node for GpuPreprocessNode { }); // Run the compute passes. - for (view, bind_group, view_uniform_offset, gpu_culling) in + for (view, bind_group, view_uniform_offset, no_indirect_drawing) in self.view_query.iter_manual(world) { // Grab the index buffer for this view. @@ -213,7 +213,7 @@ impl Node for GpuPreprocessNode { // Select the right pipeline, depending on whether GPU culling is in // use. - let maybe_pipeline_id = if gpu_culling { + let maybe_pipeline_id = if !no_indirect_drawing { preprocess_pipelines.gpu_culling.pipeline_id } else { preprocess_pipelines.direct.pipeline_id @@ -235,7 +235,7 @@ impl Node for GpuPreprocessNode { compute_pass.set_pipeline(preprocess_pipeline); let mut dynamic_offsets: SmallVec<[u32; 1]> = smallvec![]; - if gpu_culling { + if !no_indirect_drawing { dynamic_offsets.push(view_uniform_offset.offset); } compute_pass.set_bind_group(0, &bind_group.0, &dynamic_offsets); @@ -422,7 +422,7 @@ pub fn prepare_preprocess_bind_groups( ) .ok(); - let bind_group = if index_buffer_vec.gpu_culling { + let bind_group = if !index_buffer_vec.no_indirect_drawing { let ( Some(indirect_parameters_buffer), Some(mesh_culling_data_buffer), diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index e13db2a8bbe18..3705424adfb8b 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -15,7 +15,7 @@ use bevy_render::{ batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport}, camera::SortedCameras, mesh::allocator::MeshAllocator, - view::GpuCulling, + view::NoIndirectDrawing, }; use bevy_render::{ diagnostic::RecordDiagnostics, @@ -687,7 +687,7 @@ pub fn prepare_lights( &ExtractedView, &ExtractedClusterConfig, Option<&RenderLayers>, - Has, + Has, ), With, >, @@ -1096,7 +1096,7 @@ pub fn prepare_lights( let mut live_views = EntityHashSet::with_capacity_and_hasher(views_count, EntityHash); // set up light data for each view - for (entity, extracted_view, clusters, maybe_layers, has_gpu_culling) in sorted_cameras + for (entity, extracted_view, clusters, maybe_layers, no_indirect_drawing) in sorted_cameras .0 .iter() .filter_map(|sorted_camera| views.get(sorted_camera.entity).ok()) @@ -1104,7 +1104,7 @@ pub fn prepare_lights( live_views.insert(entity); let mut view_lights = Vec::new(); - let gpu_preprocessing_mode = gpu_preprocessing_support.min(if has_gpu_culling { + let gpu_preprocessing_mode = gpu_preprocessing_support.min(if !no_indirect_drawing { GpuPreprocessingMode::Culling } else { GpuPreprocessingMode::PreprocessingOnly @@ -1237,8 +1237,8 @@ pub fn prepare_lights( }, )); - if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) { - commands.entity(view_light_entity).insert(GpuCulling); + if !matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) { + commands.entity(view_light_entity).insert(NoIndirectDrawing); } view_lights.push(view_light_entity); @@ -1329,8 +1329,8 @@ pub fn prepare_lights( LightEntity::Spot { light_entity }, )); - if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) { - commands.entity(view_light_entity).insert(GpuCulling); + if !matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) { + commands.entity(view_light_entity).insert(NoIndirectDrawing); } view_lights.push(view_light_entity); @@ -1464,8 +1464,8 @@ pub fn prepare_lights( }, )); - if matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) { - commands.entity(view_light_entity).insert(GpuCulling); + if !matches!(gpu_preprocessing_mode, GpuPreprocessingMode::Culling) { + commands.entity(view_light_entity).insert(NoIndirectDrawing); } view_lights.push(view_light_entity); diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index c0f3db33d5f3e..35edf83b944f8 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -37,8 +37,8 @@ use bevy_render::{ renderer::{RenderDevice, RenderQueue}, texture::DefaultImageSampler, view::{ - prepare_view_targets, GpuCulling, RenderVisibilityRanges, ViewTarget, ViewUniformOffset, - ViewVisibility, VisibilityRange, + prepare_view_targets, NoFrustumCulling, NoIndirectDrawing, RenderVisibilityRanges, + ViewTarget, ViewUniformOffset, ViewVisibility, VisibilityRange, }, Extract, }; @@ -421,6 +421,11 @@ bitflags::bitflags! { /// /// This will be `u16::MAX` if this mesh has no LOD. const LOD_INDEX_MASK = (1 << 16) - 1; + /// Disables frustum culling for this mesh. + /// + /// This corresponds to the + /// [`bevy_render::view::visibility::NoFrustumCulling`] component. + const NO_FRUSTUM_CULLING = 1 << 28; const SHADOW_RECEIVER = 1 << 29; const TRANSMITTED_SHADOW_RECEIVER = 1 << 30; // Indicates the sign of the determinant of the 3x3 model matrix. If the sign is positive, @@ -435,6 +440,7 @@ impl MeshFlags { fn from_components( transform: &GlobalTransform, lod_index: Option, + no_frustum_culling: bool, not_shadow_receiver: bool, transmitted_receiver: bool, ) -> MeshFlags { @@ -443,6 +449,9 @@ impl MeshFlags { } else { MeshFlags::SHADOW_RECEIVER }; + if no_frustum_culling { + mesh_flags |= MeshFlags::NO_FRUSTUM_CULLING; + } if transmitted_receiver { mesh_flags |= MeshFlags::TRANSMITTED_SHADOW_RECEIVER; } @@ -1046,6 +1055,7 @@ pub fn extract_meshes_for_cpu_building( &GlobalTransform, Option<&PreviousGlobalTransform>, &Mesh3d, + Has, Has, Has, Has, @@ -1063,6 +1073,7 @@ pub fn extract_meshes_for_cpu_building( transform, previous_transform, mesh, + no_frustum_culling, not_shadow_receiver, transmitted_receiver, not_shadow_caster, @@ -1084,6 +1095,7 @@ pub fn extract_meshes_for_cpu_building( let mesh_flags = MeshFlags::from_components( transform, lod_index, + no_frustum_culling, not_shadow_receiver, transmitted_receiver, ); @@ -1155,6 +1167,7 @@ pub fn extract_meshes_for_gpu_building( Option<&Lightmap>, Option<&Aabb>, &Mesh3d, + Has, Has, Has, Has, @@ -1168,6 +1181,7 @@ pub fn extract_meshes_for_gpu_building( Changed, Changed, Changed, + Changed, Changed, Changed, Changed, @@ -1179,7 +1193,7 @@ pub fn extract_meshes_for_gpu_building( mut removed_visibilities_query: Extract>, mut removed_global_transforms_query: Extract>, mut removed_meshes_query: Extract>, - cameras_query: Extract, With)>>, + cameras_query: Extract, Without)>>, ) { let any_gpu_culling = !cameras_query.is_empty(); for render_mesh_instance_queue in render_mesh_instance_queues.iter_mut() { @@ -1209,6 +1223,7 @@ pub fn extract_meshes_for_gpu_building( lightmap, aabb, mesh, + no_frustum_culling, not_shadow_receiver, transmitted_receiver, not_shadow_caster, @@ -1231,6 +1246,7 @@ pub fn extract_meshes_for_gpu_building( let mesh_flags = MeshFlags::from_components( transform, lod_index, + 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 3300c4d925d6b..9836077a66614 100644 --- a/crates/bevy_pbr/src/render/mesh_preprocess.wgsl +++ b/crates/bevy_pbr/src/render/mesh_preprocess.wgsl @@ -7,7 +7,7 @@ // mesh's transform on the previous frame and writes it into the `MeshUniform` // so that TAA works. -#import bevy_pbr::mesh_types::Mesh +#import bevy_pbr::mesh_types::{Mesh, MESH_FLAGS_NO_FRUSTUM_CULLING_BIT} #import bevy_render::maths #import bevy_render::view::View @@ -145,13 +145,15 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3) { // Cull if necessary. #ifdef FRUSTUM_CULLING - let aabb_center = mesh_culling_data[input_index].aabb_center.xyz; - let aabb_half_extents = mesh_culling_data[input_index].aabb_half_extents.xyz; - - // Do an OBB-based frustum cull. - let model_center = world_from_local * vec4(aabb_center, 1.0); - if (!view_frustum_intersects_obb(world_from_local, model_center, aabb_half_extents)) { - return; + 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; + + // Do an OBB-based frustum cull. + let model_center = world_from_local * vec4(aabb_center, 1.0); + if (!view_frustum_intersects_obb(world_from_local, model_center, aabb_half_extents)) { + return; + } } #endif diff --git a/crates/bevy_pbr/src/render/mesh_types.wgsl b/crates/bevy_pbr/src/render/mesh_types.wgsl index f94074d813465..9a5e064c825a5 100644 --- a/crates/bevy_pbr/src/render/mesh_types.wgsl +++ b/crates/bevy_pbr/src/render/mesh_types.wgsl @@ -37,6 +37,8 @@ struct MorphWeights { // [2^0, 2^16) const MESH_FLAGS_VISIBILITY_RANGE_INDEX_BITS: u32 = 65535u; +// 2^28 +const MESH_FLAGS_NO_FRUSTUM_CULLING_BIT: u32 = 268435456u; // 2^29 const MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 536870912u; // 2^30 diff --git a/crates/bevy_render/src/batching/gpu_preprocessing.rs b/crates/bevy_render/src/batching/gpu_preprocessing.rs index b619303e04041..07379443a4081 100644 --- a/crates/bevy_render/src/batching/gpu_preprocessing.rs +++ b/crates/bevy_render/src/batching/gpu_preprocessing.rs @@ -24,7 +24,7 @@ use crate::{ }, render_resource::{BufferVec, GpuArrayBufferable, RawBufferVec, UninitBufferVec}, renderer::{RenderAdapter, RenderDevice, RenderQueue}, - view::{ExtractedView, GpuCulling, ViewTarget}, + view::{ExtractedView, NoIndirectDrawing, ViewTarget}, Render, RenderApp, RenderSet, }; @@ -101,12 +101,13 @@ pub enum GpuPreprocessingMode { /// GPU preprocessing is in use, but GPU culling isn't. /// - /// This is used by default. + /// This is used when the [`NoIndirectDrawing`] component is present on the + /// camera. PreprocessingOnly, /// Both GPU preprocessing and GPU culling are in use. /// - /// This is used when the [`GpuCulling`] component is present on the camera. + /// This is used by default. Culling, } @@ -247,8 +248,8 @@ where pub struct PreprocessWorkItemBuffer { /// The buffer of work items. pub buffer: BufferVec, - /// True if we're using GPU culling. - pub gpu_culling: bool, + /// True if we're drawing directly instead of indirectly. + pub no_indirect_drawing: bool, } /// One invocation of the preprocessing shader: i.e. one mesh instance in a @@ -382,7 +383,7 @@ impl FromWorld for GpuPreprocessingSupport { GpuPreprocessingMode::None } else if !device .features() - .contains(Features::INDIRECT_FIRST_INSTANCE) || + .contains(Features::INDIRECT_FIRST_INSTANCE | Features::MULTI_DRAW_INDIRECT) || !adapter.get_downlevel_capabilities().flags.contains( DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW) { @@ -529,7 +530,7 @@ pub fn batch_and_prepare_sorted_render_phase( gpu_array_buffer: ResMut>, mut indirect_parameters_buffer: ResMut, mut sorted_render_phases: ResMut>, - mut views: Query<(Entity, Has), With>, + mut views: Query<(Entity, Has), With>, system_param_item: StaticSystemParam, ) where I: CachedRenderPipelinePhaseItem + SortedPhaseItem, @@ -542,7 +543,7 @@ pub fn batch_and_prepare_sorted_render_phase( .. } = gpu_array_buffer.into_inner(); - for (view, gpu_culling) in &mut views { + for (view, no_indirect_drawing) in &mut views { let Some(phase) = sorted_render_phases.get_mut(&view) else { continue; }; @@ -553,7 +554,7 @@ pub fn batch_and_prepare_sorted_render_phase( .entry(view) .or_insert_with(|| PreprocessWorkItemBuffer { buffer: BufferVec::new(BufferUsages::STORAGE), - gpu_culling, + no_indirect_drawing, }); // Walk through the list of phase items, building up batches as we go. @@ -604,7 +605,7 @@ pub fn batch_and_prepare_sorted_render_phase( } // Start a new batch. - let indirect_parameters_index = if gpu_culling { + let indirect_parameters_index = if !no_indirect_drawing { GFBD::get_batch_indirect_parameters_index( &system_param_item, &mut indirect_parameters_buffer, @@ -647,7 +648,7 @@ pub fn batch_and_prepare_binned_render_phase( gpu_array_buffer: ResMut>, mut indirect_parameters_buffer: ResMut, mut binned_render_phases: ResMut>, - mut views: Query<(Entity, Has), With>, + mut views: Query<(Entity, Has), With>, param: StaticSystemParam, ) where BPI: BinnedPhaseItem, @@ -661,7 +662,7 @@ pub fn batch_and_prepare_binned_render_phase( .. } = gpu_array_buffer.into_inner(); - for (view, gpu_culling) in &mut views { + for (view, no_indirect_drawing) in &mut views { let Some(phase) = binned_render_phases.get_mut(&view) else { continue; }; @@ -673,7 +674,7 @@ pub fn batch_and_prepare_binned_render_phase( .entry(view) .or_insert_with(|| PreprocessWorkItemBuffer { buffer: BufferVec::new(BufferUsages::STORAGE), - gpu_culling, + no_indirect_drawing, }); // Prepare batchables. @@ -697,6 +698,7 @@ pub fn batch_and_prepare_binned_render_phase( match batch { Some(ref mut batch) => { + // Append to the current batch. batch.instance_range.end = output_index + 1; work_item_buffer.buffer.push(PreprocessWorkItem { input_index: input_index.into(), @@ -710,7 +712,8 @@ pub fn batch_and_prepare_binned_render_phase( }); } - None if gpu_culling => { + None if !no_indirect_drawing => { + // Start a new batch, in indirect mode. let indirect_parameters_index = GFBD::get_batch_indirect_parameters_index( &system_param_item, &mut indirect_parameters_buffer, @@ -731,6 +734,7 @@ pub fn batch_and_prepare_binned_render_phase( } None => { + // Start a new batch, in direct mode. work_item_buffer.buffer.push(PreprocessWorkItem { input_index: input_index.into(), output_index, @@ -783,7 +787,9 @@ pub fn batch_and_prepare_binned_render_phase( }; let output_index = data_buffer.add() as u32; - if gpu_culling { + if !no_indirect_drawing { + // We're in indirect mode, so add an indirect parameters + // index. let indirect_parameters_index = GFBD::get_batch_indirect_parameters_index( &system_param_item, &mut indirect_parameters_buffer, diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 3c375d935cd72..849beccc439d7 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -9,7 +9,7 @@ use crate::{ sync_world::{RenderEntity, SyncToRenderWorld}, texture::GpuImage, view::{ - ColorGrading, ExtractedView, ExtractedWindows, GpuCulling, Msaa, RenderLayers, + ColorGrading, ExtractedView, ExtractedWindows, Msaa, NoIndirectDrawing, RenderLayers, RenderVisibleEntities, ViewUniformOffset, Visibility, VisibleEntities, }, Extract, @@ -32,7 +32,7 @@ use bevy_math::{ops, vec2, Dir3, Mat4, Ray3d, Rect, URect, UVec2, UVec4, Vec2, V use bevy_reflect::prelude::*; use bevy_render_macros::ExtractComponent; use bevy_transform::components::{GlobalTransform, Transform}; -use bevy_utils::{tracing::warn, warn_once, HashMap, HashSet}; +use bevy_utils::{tracing::warn, HashMap, HashSet}; use bevy_window::{ NormalizedWindowRef, PrimaryWindow, Window, WindowCreated, WindowRef, WindowResized, WindowScaleFactorChanged, @@ -1033,7 +1033,7 @@ pub fn extract_cameras( Option<&TemporalJitter>, Option<&RenderLayers>, Option<&Projection>, - Has, + Has, )>, >, primary_window: Extract>>, @@ -1053,7 +1053,7 @@ pub fn extract_cameras( temporal_jitter, render_layers, projection, - gpu_culling, + no_indirect_drawing, ) in query.iter() { if !camera.is_active { @@ -1064,7 +1064,7 @@ pub fn extract_cameras( TemporalJitter, RenderLayers, Projection, - GpuCulling, + NoIndirectDrawing, ViewUniformOffset, )>(); continue; @@ -1156,14 +1156,13 @@ pub fn extract_cameras( commands.insert(perspective.clone()); } - if gpu_culling { - if gpu_preprocessing_support.max_supported_mode == GpuPreprocessingMode::Culling { - commands.insert(GpuCulling); - } else { - warn_once!( - "GPU culling isn't supported on this platform; ignoring `GpuCulling`." - ); - } + if no_indirect_drawing + || !matches!( + gpu_preprocessing_support.max_supported_mode, + GpuPreprocessingMode::Culling + ) + { + commands.insert(NoIndirectDrawing); } }; } diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index a626a17d1d592..06e2db79f28df 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -620,8 +620,19 @@ impl From for ColorGradingUniform { } } +/// Add this component to a camera to disable *indirect mode*. +/// +/// Indirect mode, automatically enabled on supported hardware, allows Bevy to +/// offload transform and cull operations to the GPU, reducing CPU overhead. +/// Doing this, however, reduces the amount of control that your app has over +/// instancing decisions. In certain circumstances, you may want to disable +/// indirect drawing so that your app can manually instance meshes as it sees +/// fit. See the `custom_shader_instancing` example. +/// +/// The vast majority of applications will not need to use this component, as it +/// generally reduces rendering performance. #[derive(Component)] -pub struct GpuCulling; +pub struct NoIndirectDrawing; #[derive(Component)] pub struct NoCpuCulling; diff --git a/examples/shader/custom_shader_instancing.rs b/examples/shader/custom_shader_instancing.rs index 385b4875d6e34..2809c7d9944e5 100644 --- a/examples/shader/custom_shader_instancing.rs +++ b/examples/shader/custom_shader_instancing.rs @@ -30,7 +30,7 @@ use bevy::{ render_resource::*, renderer::RenderDevice, sync_world::MainEntity, - view::{ExtractedView, NoFrustumCulling}, + view::{ExtractedView, NoFrustumCulling, NoIndirectDrawing}, Render, RenderApp, RenderSet, }, }; @@ -73,6 +73,10 @@ fn setup(mut commands: Commands, mut meshes: ResMut>) { commands.spawn(( Camera3d::default(), Transform::from_xyz(0.0, 0.0, 15.0).looking_at(Vec3::ZERO, Vec3::Y), + // We need this component because we use `draw_indexed` and `draw` + // instead of `draw_indirect_indexed` and `draw_indirect` in + // `DrawMeshInstanced::render`. + NoIndirectDrawing, )); } diff --git a/examples/stress_tests/many_cubes.rs b/examples/stress_tests/many_cubes.rs index 2853bd5fa0fe0..fe8e8b45074df 100644 --- a/examples/stress_tests/many_cubes.rs +++ b/examples/stress_tests/many_cubes.rs @@ -20,7 +20,7 @@ use bevy::{ batching::NoAutomaticBatching, render_asset::RenderAssetUsages, render_resource::{Extent3d, TextureDimension, TextureFormat}, - view::{GpuCulling, NoCpuCulling, NoFrustumCulling}, + view::{NoCpuCulling, NoFrustumCulling, NoIndirectDrawing}, }, window::{PresentMode, WindowResolution}, winit::{UpdateMode, WinitSettings}, @@ -59,9 +59,9 @@ struct Args { #[argh(switch)] no_automatic_batching: bool, - /// whether to enable GPU culling. + /// whether to disable indirect drawing. #[argh(switch)] - gpu_culling: bool, + no_indirect_drawing: bool, /// whether to disable CPU culling. #[argh(switch)] @@ -176,8 +176,8 @@ fn setup( // camera let mut camera = commands.spawn(Camera3d::default()); - if args.gpu_culling { - camera.insert(GpuCulling); + if args.no_indirect_drawing { + camera.insert(NoIndirectDrawing); } if args.no_cpu_culling { camera.insert(NoCpuCulling);