Set late indirect parameter offsets every frame again. (#17736)
PR #17684 broke occlusion culling because it neglected to set the indirect parameter offsets for the late mesh preprocessing stage if the work item buffers were already set. This PR moves the update of those values to a new function, `init_work_item_buffers`, which is unconditionally called for every phase every frame. Note that there's some complexity in order to handle the case in which occlusion culling was enabled on one frame and disabled on the next, or vice versa. This was necessary in order to make the occlusion culling toggle in the `occlusion_culling` example work again.
This commit is contained in:
parent
9f9373c7d9
commit
556b750782
@ -412,18 +412,12 @@ pub fn get_or_create_work_item_buffer<'a, I>(
|
||||
work_item_buffers: &'a mut HashMap<RetainedViewEntity, TypeIdMap<PreprocessWorkItemBuffers>>,
|
||||
view: RetainedViewEntity,
|
||||
no_indirect_drawing: bool,
|
||||
gpu_occlusion_culling: bool,
|
||||
late_indexed_indirect_parameters_buffer: &'_ mut RawBufferVec<
|
||||
LatePreprocessWorkItemIndirectParameters,
|
||||
>,
|
||||
late_non_indexed_indirect_parameters_buffer: &'_ mut RawBufferVec<
|
||||
LatePreprocessWorkItemIndirectParameters,
|
||||
>,
|
||||
enable_gpu_occlusion_culling: bool,
|
||||
) -> &'a mut PreprocessWorkItemBuffers
|
||||
where
|
||||
I: 'static,
|
||||
{
|
||||
match work_item_buffers
|
||||
let preprocess_work_item_buffers = match work_item_buffers
|
||||
.entry(view)
|
||||
.or_default()
|
||||
.entry(TypeId::of::<I>())
|
||||
@ -438,27 +432,70 @@ where
|
||||
vacant_entry.insert(PreprocessWorkItemBuffers::Indirect {
|
||||
indexed: BufferVec::new(BufferUsages::STORAGE),
|
||||
non_indexed: BufferVec::new(BufferUsages::STORAGE),
|
||||
gpu_occlusion_culling: if gpu_occlusion_culling {
|
||||
let late_indirect_parameters_indexed_offset =
|
||||
late_indexed_indirect_parameters_buffer
|
||||
.push(LatePreprocessWorkItemIndirectParameters::default());
|
||||
let late_indirect_parameters_non_indexed_offset =
|
||||
late_non_indexed_indirect_parameters_buffer
|
||||
.push(LatePreprocessWorkItemIndirectParameters::default());
|
||||
Some(GpuOcclusionCullingWorkItemBuffers {
|
||||
late_indexed: UninitBufferVec::new(BufferUsages::STORAGE),
|
||||
late_non_indexed: UninitBufferVec::new(BufferUsages::STORAGE),
|
||||
late_indirect_parameters_indexed_offset:
|
||||
late_indirect_parameters_indexed_offset as u32,
|
||||
late_indirect_parameters_non_indexed_offset:
|
||||
late_indirect_parameters_non_indexed_offset as u32,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
// We fill this in below if `enable_gpu_occlusion_culling`
|
||||
// is set.
|
||||
gpu_occlusion_culling: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize the GPU occlusion culling buffers if necessary.
|
||||
if let PreprocessWorkItemBuffers::Indirect {
|
||||
ref mut gpu_occlusion_culling,
|
||||
..
|
||||
} = *preprocess_work_item_buffers
|
||||
{
|
||||
match (
|
||||
enable_gpu_occlusion_culling,
|
||||
gpu_occlusion_culling.is_some(),
|
||||
) {
|
||||
(false, false) | (true, true) => {}
|
||||
(false, true) => {
|
||||
*gpu_occlusion_culling = None;
|
||||
}
|
||||
(true, false) => {
|
||||
*gpu_occlusion_culling = Some(GpuOcclusionCullingWorkItemBuffers {
|
||||
late_indexed: UninitBufferVec::new(BufferUsages::STORAGE),
|
||||
late_non_indexed: UninitBufferVec::new(BufferUsages::STORAGE),
|
||||
late_indirect_parameters_indexed_offset: 0,
|
||||
late_indirect_parameters_non_indexed_offset: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preprocess_work_item_buffers
|
||||
}
|
||||
|
||||
/// Initializes work item buffers for a phase in preparation for a new frame.
|
||||
pub fn init_work_item_buffers(
|
||||
work_item_buffers: &mut PreprocessWorkItemBuffers,
|
||||
late_indexed_indirect_parameters_buffer: &'_ mut RawBufferVec<
|
||||
LatePreprocessWorkItemIndirectParameters,
|
||||
>,
|
||||
late_non_indexed_indirect_parameters_buffer: &'_ mut RawBufferVec<
|
||||
LatePreprocessWorkItemIndirectParameters,
|
||||
>,
|
||||
) {
|
||||
// Add the offsets for indirect parameters that the late phase of mesh
|
||||
// preprocessing writes to.
|
||||
if let PreprocessWorkItemBuffers::Indirect {
|
||||
gpu_occlusion_culling:
|
||||
Some(GpuOcclusionCullingWorkItemBuffers {
|
||||
ref mut late_indirect_parameters_indexed_offset,
|
||||
ref mut late_indirect_parameters_non_indexed_offset,
|
||||
..
|
||||
}),
|
||||
..
|
||||
} = *work_item_buffers
|
||||
{
|
||||
*late_indirect_parameters_indexed_offset = late_indexed_indirect_parameters_buffer
|
||||
.push(LatePreprocessWorkItemIndirectParameters::default())
|
||||
as u32;
|
||||
*late_indirect_parameters_non_indexed_offset = late_non_indexed_indirect_parameters_buffer
|
||||
.push(LatePreprocessWorkItemIndirectParameters::default())
|
||||
as u32;
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,6 +548,8 @@ impl PreprocessWorkItemBuffers {
|
||||
if let Some(ref mut gpu_occlusion_culling) = *gpu_occlusion_culling {
|
||||
gpu_occlusion_culling.late_indexed.clear();
|
||||
gpu_occlusion_culling.late_non_indexed.clear();
|
||||
gpu_occlusion_culling.late_indirect_parameters_indexed_offset = 0;
|
||||
gpu_occlusion_culling.late_indirect_parameters_non_indexed_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1153,6 +1192,11 @@ pub fn batch_and_prepare_sorted_render_phase<I, GFBD>(
|
||||
extracted_view.retained_view_entity,
|
||||
no_indirect_drawing,
|
||||
gpu_occlusion_culling,
|
||||
);
|
||||
|
||||
// Initialize those work item buffers in preparation for this new frame.
|
||||
init_work_item_buffers(
|
||||
work_item_buffer,
|
||||
late_indexed_indirect_parameters_buffer,
|
||||
late_non_indexed_indirect_parameters_buffer,
|
||||
);
|
||||
@ -1313,6 +1357,11 @@ pub fn batch_and_prepare_binned_render_phase<BPI, GFBD>(
|
||||
extracted_view.retained_view_entity,
|
||||
no_indirect_drawing,
|
||||
gpu_occlusion_culling,
|
||||
);
|
||||
|
||||
// Initialize those work item buffers in preparation for this new frame.
|
||||
init_work_item_buffers(
|
||||
work_item_buffer,
|
||||
late_indexed_indirect_parameters_buffer,
|
||||
late_non_indexed_indirect_parameters_buffer,
|
||||
);
|
||||
|
@ -325,7 +325,7 @@ fn queue_custom_mesh_pipeline(
|
||||
continue;
|
||||
};
|
||||
|
||||
// Create a *work item buffer* if necessary. Work item buffers store the
|
||||
// Create *work item buffers* if necessary. Work item buffers store the
|
||||
// indices of meshes that are to be rendered when indirect drawing is
|
||||
// enabled.
|
||||
let work_item_buffer = gpu_preprocessing::get_or_create_work_item_buffer::<Opaque3d>(
|
||||
@ -333,6 +333,11 @@ fn queue_custom_mesh_pipeline(
|
||||
view.retained_view_entity,
|
||||
no_indirect_drawing,
|
||||
gpu_occlusion_culling,
|
||||
);
|
||||
|
||||
// Initialize those work item buffers in preparation for this new frame.
|
||||
gpu_preprocessing::init_work_item_buffers(
|
||||
work_item_buffer,
|
||||
late_indexed_indirect_parameters_buffer,
|
||||
late_non_indexed_indirect_parameters_buffer,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user