Initialize pre-processing pipelines only when culling is enabled. (#18759)
Better fix for #18463 that still allows enabling mesh preprocessing on webgpu. Fixes #18463
This commit is contained in:
parent
065a95e0a1
commit
f75078676b
@ -27,7 +27,7 @@ use bevy_ecs::{
|
||||
world::{FromWorld, World},
|
||||
};
|
||||
use bevy_render::batching::gpu_preprocessing::{
|
||||
IndirectParametersGpuMetadata, UntypedPhaseIndirectParametersBuffers,
|
||||
GpuPreprocessingMode, IndirectParametersGpuMetadata, UntypedPhaseIndirectParametersBuffers,
|
||||
};
|
||||
use bevy_render::{
|
||||
batching::gpu_preprocessing::{
|
||||
@ -1173,26 +1173,41 @@ fn run_build_indirect_parameters_node(
|
||||
impl PreprocessPipelines {
|
||||
/// Returns true if the preprocessing and indirect parameters pipelines have
|
||||
/// been loaded or false otherwise.
|
||||
pub(crate) fn pipelines_are_loaded(&self, pipeline_cache: &PipelineCache) -> bool {
|
||||
self.direct_preprocess.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.gpu_frustum_culling_preprocess
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.early_gpu_occlusion_culling_preprocess
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.late_gpu_occlusion_culling_preprocess
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.gpu_frustum_culling_build_indexed_indirect_params
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.gpu_frustum_culling_build_non_indexed_indirect_params
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self.early_phase.is_loaded(pipeline_cache)
|
||||
&& self.late_phase.is_loaded(pipeline_cache)
|
||||
&& self.main_phase.is_loaded(pipeline_cache)
|
||||
pub(crate) fn pipelines_are_loaded(
|
||||
&self,
|
||||
pipeline_cache: &PipelineCache,
|
||||
preprocessing_support: &GpuPreprocessingSupport,
|
||||
) -> bool {
|
||||
match preprocessing_support.max_supported_mode {
|
||||
GpuPreprocessingMode::None => false,
|
||||
GpuPreprocessingMode::PreprocessingOnly => {
|
||||
self.direct_preprocess.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.gpu_frustum_culling_preprocess
|
||||
.is_loaded(pipeline_cache)
|
||||
}
|
||||
GpuPreprocessingMode::Culling => {
|
||||
self.direct_preprocess.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.gpu_frustum_culling_preprocess
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.early_gpu_occlusion_culling_preprocess
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.late_gpu_occlusion_culling_preprocess
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.gpu_frustum_culling_build_indexed_indirect_params
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self
|
||||
.gpu_frustum_culling_build_non_indexed_indirect_params
|
||||
.is_loaded(pipeline_cache)
|
||||
&& self.early_phase.is_loaded(pipeline_cache)
|
||||
&& self.late_phase.is_loaded(pipeline_cache)
|
||||
&& self.main_phase.is_loaded(pipeline_cache)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1495,6 +1510,7 @@ pub fn prepare_preprocess_pipelines(
|
||||
SpecializedComputePipelines<BuildIndirectParametersPipeline>,
|
||||
>,
|
||||
preprocess_pipelines: ResMut<PreprocessPipelines>,
|
||||
gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
|
||||
) {
|
||||
let preprocess_pipelines = preprocess_pipelines.into_inner();
|
||||
|
||||
@ -1508,22 +1524,25 @@ pub fn prepare_preprocess_pipelines(
|
||||
&mut specialized_preprocess_pipelines,
|
||||
PreprocessPipelineKey::FRUSTUM_CULLING,
|
||||
);
|
||||
preprocess_pipelines
|
||||
.early_gpu_occlusion_culling_preprocess
|
||||
.prepare(
|
||||
&pipeline_cache,
|
||||
&mut specialized_preprocess_pipelines,
|
||||
PreprocessPipelineKey::FRUSTUM_CULLING
|
||||
| PreprocessPipelineKey::OCCLUSION_CULLING
|
||||
| PreprocessPipelineKey::EARLY_PHASE,
|
||||
);
|
||||
preprocess_pipelines
|
||||
.late_gpu_occlusion_culling_preprocess
|
||||
.prepare(
|
||||
&pipeline_cache,
|
||||
&mut specialized_preprocess_pipelines,
|
||||
PreprocessPipelineKey::FRUSTUM_CULLING | PreprocessPipelineKey::OCCLUSION_CULLING,
|
||||
);
|
||||
|
||||
if gpu_preprocessing_support.is_culling_supported() {
|
||||
preprocess_pipelines
|
||||
.early_gpu_occlusion_culling_preprocess
|
||||
.prepare(
|
||||
&pipeline_cache,
|
||||
&mut specialized_preprocess_pipelines,
|
||||
PreprocessPipelineKey::FRUSTUM_CULLING
|
||||
| PreprocessPipelineKey::OCCLUSION_CULLING
|
||||
| PreprocessPipelineKey::EARLY_PHASE,
|
||||
);
|
||||
preprocess_pipelines
|
||||
.late_gpu_occlusion_culling_preprocess
|
||||
.prepare(
|
||||
&pipeline_cache,
|
||||
&mut specialized_preprocess_pipelines,
|
||||
PreprocessPipelineKey::FRUSTUM_CULLING | PreprocessPipelineKey::OCCLUSION_CULLING,
|
||||
);
|
||||
}
|
||||
|
||||
let mut build_indirect_parameters_pipeline_key = BuildIndirectParametersPipelineKey::empty();
|
||||
|
||||
@ -1553,6 +1572,10 @@ pub fn prepare_preprocess_pipelines(
|
||||
build_indirect_parameters_pipeline_key,
|
||||
);
|
||||
|
||||
if !gpu_preprocessing_support.is_culling_supported() {
|
||||
return;
|
||||
}
|
||||
|
||||
for (preprocess_phase_pipelines, build_indirect_parameters_phase_pipeline_key) in [
|
||||
(
|
||||
&mut preprocess_pipelines.early_phase,
|
||||
|
@ -3057,6 +3057,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
|
||||
SRes<PipelineCache>,
|
||||
SRes<MeshAllocator>,
|
||||
Option<SRes<PreprocessPipelines>>,
|
||||
SRes<GpuPreprocessingSupport>,
|
||||
);
|
||||
type ViewQuery = Has<PreprocessBindGroups>;
|
||||
type ItemQuery = ();
|
||||
@ -3072,6 +3073,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
|
||||
pipeline_cache,
|
||||
mesh_allocator,
|
||||
preprocess_pipelines,
|
||||
preprocessing_support,
|
||||
): SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
@ -3080,7 +3082,8 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
|
||||
// it's compiled. Otherwise, our mesh instance data won't be present.
|
||||
if let Some(preprocess_pipelines) = preprocess_pipelines {
|
||||
if !has_preprocess_bind_group
|
||||
|| !preprocess_pipelines.pipelines_are_loaded(&pipeline_cache)
|
||||
|| !preprocess_pipelines
|
||||
.pipelines_are_loaded(&pipeline_cache, &preprocessing_support)
|
||||
{
|
||||
return RenderCommandResult::Skip;
|
||||
}
|
||||
|
@ -111,6 +111,11 @@ impl GpuPreprocessingSupport {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if GPU culling is supported on this platform.
|
||||
pub fn is_culling_supported(&self) -> bool {
|
||||
self.max_supported_mode == GpuPreprocessingMode::Culling
|
||||
}
|
||||
}
|
||||
|
||||
/// The amount of GPU preprocessing (compute and indirect draw) that we do.
|
||||
@ -1096,7 +1101,7 @@ impl FromWorld for GpuPreprocessingSupport {
|
||||
crate::get_adreno_model(adapter).is_some_and(|model| model != 720 && model <= 730)
|
||||
}
|
||||
|
||||
let feature_support = device.features().contains(
|
||||
let culling_feature_support = device.features().contains(
|
||||
Features::INDIRECT_FIRST_INSTANCE
|
||||
| Features::MULTI_DRAW_INDIRECT
|
||||
| Features::PUSH_CONSTANTS,
|
||||
@ -1107,12 +1112,11 @@ impl FromWorld for GpuPreprocessingSupport {
|
||||
DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW
|
||||
);
|
||||
|
||||
let max_supported_mode = if !feature_support
|
||||
|| device.limits().max_compute_workgroup_size_x == 0
|
||||
let max_supported_mode = if device.limits().max_compute_workgroup_size_x == 0
|
||||
|| is_non_supported_android_device(adapter)
|
||||
{
|
||||
GpuPreprocessingMode::None
|
||||
} else if !(feature_support && limit_support && downlevel_support) {
|
||||
} else if !(culling_feature_support && limit_support && downlevel_support) {
|
||||
GpuPreprocessingMode::PreprocessingOnly
|
||||
} else {
|
||||
GpuPreprocessingMode::Culling
|
||||
|
Loading…
Reference in New Issue
Block a user