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
76422f71cd
commit
553c322d54
@ -27,7 +27,7 @@ use bevy_ecs::{
|
|||||||
world::{FromWorld, World},
|
world::{FromWorld, World},
|
||||||
};
|
};
|
||||||
use bevy_render::batching::gpu_preprocessing::{
|
use bevy_render::batching::gpu_preprocessing::{
|
||||||
IndirectParametersGpuMetadata, UntypedPhaseIndirectParametersBuffers,
|
GpuPreprocessingMode, IndirectParametersGpuMetadata, UntypedPhaseIndirectParametersBuffers,
|
||||||
};
|
};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
batching::gpu_preprocessing::{
|
batching::gpu_preprocessing::{
|
||||||
@ -1173,26 +1173,41 @@ fn run_build_indirect_parameters_node(
|
|||||||
impl PreprocessPipelines {
|
impl PreprocessPipelines {
|
||||||
/// Returns true if the preprocessing and indirect parameters pipelines have
|
/// Returns true if the preprocessing and indirect parameters pipelines have
|
||||||
/// been loaded or false otherwise.
|
/// been loaded or false otherwise.
|
||||||
pub(crate) fn pipelines_are_loaded(&self, pipeline_cache: &PipelineCache) -> bool {
|
pub(crate) fn pipelines_are_loaded(
|
||||||
self.direct_preprocess.is_loaded(pipeline_cache)
|
&self,
|
||||||
&& self
|
pipeline_cache: &PipelineCache,
|
||||||
.gpu_frustum_culling_preprocess
|
preprocessing_support: &GpuPreprocessingSupport,
|
||||||
.is_loaded(pipeline_cache)
|
) -> bool {
|
||||||
&& self
|
match preprocessing_support.max_supported_mode {
|
||||||
.early_gpu_occlusion_culling_preprocess
|
GpuPreprocessingMode::None => false,
|
||||||
.is_loaded(pipeline_cache)
|
GpuPreprocessingMode::PreprocessingOnly => {
|
||||||
&& self
|
self.direct_preprocess.is_loaded(pipeline_cache)
|
||||||
.late_gpu_occlusion_culling_preprocess
|
&& self
|
||||||
.is_loaded(pipeline_cache)
|
.gpu_frustum_culling_preprocess
|
||||||
&& self
|
.is_loaded(pipeline_cache)
|
||||||
.gpu_frustum_culling_build_indexed_indirect_params
|
}
|
||||||
.is_loaded(pipeline_cache)
|
GpuPreprocessingMode::Culling => {
|
||||||
&& self
|
self.direct_preprocess.is_loaded(pipeline_cache)
|
||||||
.gpu_frustum_culling_build_non_indexed_indirect_params
|
&& self
|
||||||
.is_loaded(pipeline_cache)
|
.gpu_frustum_culling_preprocess
|
||||||
&& self.early_phase.is_loaded(pipeline_cache)
|
.is_loaded(pipeline_cache)
|
||||||
&& self.late_phase.is_loaded(pipeline_cache)
|
&& self
|
||||||
&& self.main_phase.is_loaded(pipeline_cache)
|
.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>,
|
SpecializedComputePipelines<BuildIndirectParametersPipeline>,
|
||||||
>,
|
>,
|
||||||
preprocess_pipelines: ResMut<PreprocessPipelines>,
|
preprocess_pipelines: ResMut<PreprocessPipelines>,
|
||||||
|
gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
|
||||||
) {
|
) {
|
||||||
let preprocess_pipelines = preprocess_pipelines.into_inner();
|
let preprocess_pipelines = preprocess_pipelines.into_inner();
|
||||||
|
|
||||||
@ -1508,22 +1524,25 @@ pub fn prepare_preprocess_pipelines(
|
|||||||
&mut specialized_preprocess_pipelines,
|
&mut specialized_preprocess_pipelines,
|
||||||
PreprocessPipelineKey::FRUSTUM_CULLING,
|
PreprocessPipelineKey::FRUSTUM_CULLING,
|
||||||
);
|
);
|
||||||
preprocess_pipelines
|
|
||||||
.early_gpu_occlusion_culling_preprocess
|
if gpu_preprocessing_support.is_culling_supported() {
|
||||||
.prepare(
|
preprocess_pipelines
|
||||||
&pipeline_cache,
|
.early_gpu_occlusion_culling_preprocess
|
||||||
&mut specialized_preprocess_pipelines,
|
.prepare(
|
||||||
PreprocessPipelineKey::FRUSTUM_CULLING
|
&pipeline_cache,
|
||||||
| PreprocessPipelineKey::OCCLUSION_CULLING
|
&mut specialized_preprocess_pipelines,
|
||||||
| PreprocessPipelineKey::EARLY_PHASE,
|
PreprocessPipelineKey::FRUSTUM_CULLING
|
||||||
);
|
| PreprocessPipelineKey::OCCLUSION_CULLING
|
||||||
preprocess_pipelines
|
| PreprocessPipelineKey::EARLY_PHASE,
|
||||||
.late_gpu_occlusion_culling_preprocess
|
);
|
||||||
.prepare(
|
preprocess_pipelines
|
||||||
&pipeline_cache,
|
.late_gpu_occlusion_culling_preprocess
|
||||||
&mut specialized_preprocess_pipelines,
|
.prepare(
|
||||||
PreprocessPipelineKey::FRUSTUM_CULLING | PreprocessPipelineKey::OCCLUSION_CULLING,
|
&pipeline_cache,
|
||||||
);
|
&mut specialized_preprocess_pipelines,
|
||||||
|
PreprocessPipelineKey::FRUSTUM_CULLING | PreprocessPipelineKey::OCCLUSION_CULLING,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let mut build_indirect_parameters_pipeline_key = BuildIndirectParametersPipelineKey::empty();
|
let mut build_indirect_parameters_pipeline_key = BuildIndirectParametersPipelineKey::empty();
|
||||||
|
|
||||||
@ -1553,6 +1572,10 @@ pub fn prepare_preprocess_pipelines(
|
|||||||
build_indirect_parameters_pipeline_key,
|
build_indirect_parameters_pipeline_key,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if !gpu_preprocessing_support.is_culling_supported() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (preprocess_phase_pipelines, build_indirect_parameters_phase_pipeline_key) in [
|
for (preprocess_phase_pipelines, build_indirect_parameters_phase_pipeline_key) in [
|
||||||
(
|
(
|
||||||
&mut preprocess_pipelines.early_phase,
|
&mut preprocess_pipelines.early_phase,
|
||||||
|
@ -3057,6 +3057,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
|
|||||||
SRes<PipelineCache>,
|
SRes<PipelineCache>,
|
||||||
SRes<MeshAllocator>,
|
SRes<MeshAllocator>,
|
||||||
Option<SRes<PreprocessPipelines>>,
|
Option<SRes<PreprocessPipelines>>,
|
||||||
|
SRes<GpuPreprocessingSupport>,
|
||||||
);
|
);
|
||||||
type ViewQuery = Has<PreprocessBindGroups>;
|
type ViewQuery = Has<PreprocessBindGroups>;
|
||||||
type ItemQuery = ();
|
type ItemQuery = ();
|
||||||
@ -3072,6 +3073,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
|
|||||||
pipeline_cache,
|
pipeline_cache,
|
||||||
mesh_allocator,
|
mesh_allocator,
|
||||||
preprocess_pipelines,
|
preprocess_pipelines,
|
||||||
|
preprocessing_support,
|
||||||
): SystemParamItem<'w, '_, Self::Param>,
|
): SystemParamItem<'w, '_, Self::Param>,
|
||||||
pass: &mut TrackedRenderPass<'w>,
|
pass: &mut TrackedRenderPass<'w>,
|
||||||
) -> RenderCommandResult {
|
) -> RenderCommandResult {
|
||||||
@ -3080,7 +3082,8 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
|
|||||||
// it's compiled. Otherwise, our mesh instance data won't be present.
|
// it's compiled. Otherwise, our mesh instance data won't be present.
|
||||||
if let Some(preprocess_pipelines) = preprocess_pipelines {
|
if let Some(preprocess_pipelines) = preprocess_pipelines {
|
||||||
if !has_preprocess_bind_group
|
if !has_preprocess_bind_group
|
||||||
|| !preprocess_pipelines.pipelines_are_loaded(&pipeline_cache)
|
|| !preprocess_pipelines
|
||||||
|
.pipelines_are_loaded(&pipeline_cache, &preprocessing_support)
|
||||||
{
|
{
|
||||||
return RenderCommandResult::Skip;
|
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.
|
/// 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)
|
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::INDIRECT_FIRST_INSTANCE
|
||||||
| Features::MULTI_DRAW_INDIRECT
|
| Features::MULTI_DRAW_INDIRECT
|
||||||
| Features::PUSH_CONSTANTS,
|
| Features::PUSH_CONSTANTS,
|
||||||
@ -1107,12 +1112,11 @@ impl FromWorld for GpuPreprocessingSupport {
|
|||||||
DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW
|
DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW
|
||||||
);
|
);
|
||||||
|
|
||||||
let max_supported_mode = if !feature_support
|
let max_supported_mode = if device.limits().max_compute_workgroup_size_x == 0
|
||||||
|| device.limits().max_compute_workgroup_size_x == 0
|
|
||||||
|| is_non_supported_android_device(adapter)
|
|| is_non_supported_android_device(adapter)
|
||||||
{
|
{
|
||||||
GpuPreprocessingMode::None
|
GpuPreprocessingMode::None
|
||||||
} else if !(feature_support && limit_support && downlevel_support) {
|
} else if !(culling_feature_support && limit_support && downlevel_support) {
|
||||||
GpuPreprocessingMode::PreprocessingOnly
|
GpuPreprocessingMode::PreprocessingOnly
|
||||||
} else {
|
} else {
|
||||||
GpuPreprocessingMode::Culling
|
GpuPreprocessingMode::Culling
|
||||||
|
Loading…
Reference in New Issue
Block a user