Skip to content

Commit 1a261dd

Browse files
committed
Merge remote-tracking branch 'pcwalton/shared-memory-mesh-collection' into shared-memory-mesh-collection
2 parents 5627b0f + 06ccab7 commit 1a261dd

File tree

3 files changed

+61
-5
lines changed

3 files changed

+61
-5
lines changed

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,7 +1413,7 @@ impl RenderMeshInstanceGpuPrepared {
14131413
entity: MainEntity,
14141414
render_mesh_instances: &mut MainEntityHashMap<RenderMeshInstanceGpu>,
14151415
current_input_buffer: &mut InstanceInputUniformBuffer<MeshInputUniform>,
1416-
previous_input_buffer: &mut InstanceInputUniformBuffer<MeshInputUniform>,
1416+
previous_input_buffer: &InstanceInputUniformBuffer<MeshInputUniform>,
14171417
) -> Option<u32> {
14181418
// Did the last frame contain this entity as well?
14191419
let current_uniform_index;
@@ -1431,7 +1431,7 @@ impl RenderMeshInstanceGpuPrepared {
14311431
// shader will need it to compute motion vectors.
14321432
let previous_mesh_input_uniform =
14331433
current_input_buffer.get_unchecked(current_uniform_index);
1434-
let previous_input_index = previous_input_buffer.add(previous_mesh_input_uniform);
1434+
let previous_input_index = previous_input_buffer.push(previous_mesh_input_uniform);
14351435
self.mesh_input_uniform.previous_input_index = previous_input_index;
14361436

14371437
// Write in the new mesh input uniform.
@@ -1986,6 +1986,9 @@ pub fn collect_meshes_for_gpu_building(
19861986
mesh_culling_data_buffer.grow(current_input_buffer.len() as u32);
19871987
}
19881988

1989+
// Pre-allocate the previous input buffer for concurrent pushes.
1990+
previous_input_buffer.reserve(current_input_buffer.len() as u32);
1991+
19891992
// Channels used by parallel workers to send data to the single consumer.
19901993
let (prepared_tx, prepared_rx) = mpsc::channel();
19911994
let (reextract_tx, reextract_rx) = mpsc::channel();
@@ -2001,6 +2004,7 @@ pub fn collect_meshes_for_gpu_building(
20012004
let frame_count = *frame_count;
20022005
let render_mesh_instances = &*render_mesh_instances;
20032006
let current_input_buffer = &*current_input_buffer;
2007+
let previous_input_buffer = &*previous_input_buffer;
20042008
let mesh_culling_data_buffer = &*mesh_culling_data_buffer;
20052009

20062010
// Spawn workers on the taskpool to prepare and update meshes in parallel.
@@ -2069,7 +2073,7 @@ pub fn collect_meshes_for_gpu_building(
20692073
skin_uniforms,
20702074
frame_count,
20712075
) {
2072-
Some(prepared) => {
2076+
Some(mut prepared) => {
20732077
if let Some(render_mesh_instance) =
20742078
render_mesh_instances.get(&entity)
20752079
&& prepared.render_layers
@@ -2090,6 +2094,15 @@ pub fn collect_meshes_for_gpu_building(
20902094
let current_uniform_index = render_mesh_instance
20912095
.gpu_specific
20922096
.current_uniform_index();
2097+
2098+
let previous_mesh_input_uniform =
2099+
current_input_buffer
2100+
.get_unchecked(current_uniform_index);
2101+
let previous_input_index = previous_input_buffer
2102+
.push(previous_mesh_input_uniform);
2103+
prepared.mesh_input_uniform.previous_input_index =
2104+
previous_input_index;
2105+
20932106
current_input_buffer.set(
20942107
current_uniform_index,
20952108
prepared.mesh_input_uniform,
@@ -2153,6 +2166,7 @@ pub fn collect_meshes_for_gpu_building(
21532166
let entity = batch;
21542167
meshes_to_reextract_next_frame.insert(entity);
21552168
}
2169+
previous_input_buffer.truncate();
21562170
// Buffers can't be empty. Make sure there's something in the previous input buffer.
21572171
previous_input_buffer.ensure_nonempty();
21582172
}

crates/bevy_render/src/batching/gpu_preprocessing.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Batching functionality when GPU preprocessing is in use.
22
3-
use core::{any::TypeId, marker::PhantomData, mem};
3+
use core::{
4+
any::TypeId,
5+
marker::PhantomData,
6+
mem,
7+
sync::atomic::{AtomicU32, Ordering},
8+
};
49

510
use bevy_app::{App, Plugin};
611
use bevy_derive::{Deref, DerefMut};
@@ -285,6 +290,9 @@ where
285290
/// When adding data, we preferentially overwrite these slots first before
286291
/// growing the buffer itself.
287292
free_uniform_indices: Vec<u32>,
293+
294+
/// The number of elements pushed since the last [`Self::reserve`].
295+
atomic_len: AtomicU32,
288296
}
289297

290298
impl<BDI> InstanceInputUniformBuffer<BDI>
@@ -296,13 +304,15 @@ where
296304
InstanceInputUniformBuffer {
297305
buffer: AtomicRawBufferVec::new(BufferUsages::STORAGE),
298306
free_uniform_indices: vec![],
307+
atomic_len: AtomicU32::new(0),
299308
}
300309
}
301310

302311
/// Clears the buffer and entity list out.
303312
pub fn clear(&mut self) {
304313
self.buffer.clear();
305314
self.free_uniform_indices.clear();
315+
*self.atomic_len.get_mut() = 0;
306316
}
307317

308318
/// Returns the [`RawBufferVec`] corresponding to this input uniform buffer.
@@ -359,6 +369,31 @@ where
359369
self.buffer.set(uniform_index, element);
360370
}
361371

372+
/// Pre-allocates capacity for concurrent [`Self::push`] calls.
373+
pub fn reserve(&mut self, capacity: u32) {
374+
self.buffer.grow(capacity);
375+
*self.atomic_len.get_mut() = 0;
376+
}
377+
378+
/// Appends a value and returns its index. Thread-safe.
379+
///
380+
/// [`Self::reserve`] must have been called first with sufficient capacity.
381+
pub fn push(&self, value: BDI) -> u32 {
382+
let index = self.atomic_len.fetch_add(1, Ordering::Relaxed);
383+
debug_assert!(
384+
(index as usize) < self.buffer.len() as usize,
385+
"push exceeded pre-allocated capacity"
386+
);
387+
self.buffer.set(index, value);
388+
index
389+
}
390+
391+
/// Trims the buffer to the number of elements pushed since the last
392+
/// [`Self::reserve`].
393+
pub fn truncate(&mut self) {
394+
self.buffer.truncate(*self.atomic_len.get_mut());
395+
}
396+
362397
// Ensures that the buffers are nonempty, which the GPU requires before an
363398
// upload can take place.
364399
pub fn ensure_nonempty(&mut self) {

crates/bevy_render/src/render_resource/buffer_vec.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ where
407407
self.buffer.as_ref()
408408
}
409409

410-
/// Grows to the buffer by adding default values so that it's at least the
410+
/// Grows the buffer by adding default values so that it's at least the
411411
/// given size.
412412
///
413413
/// If the buffer is already large enough, this method does nothing.
@@ -416,6 +416,13 @@ where
416416
self.values.resize_with(new_len as usize, T::Blob::default);
417417
}
418418
}
419+
420+
/// Truncates the buffer to the given length.
421+
///
422+
/// If the buffer is already shorter, this method does nothing.
423+
pub fn truncate(&mut self, len: u32) {
424+
self.values.truncate(len as usize);
425+
}
419426
}
420427

421428
/// Like [`RawBufferVec`], but doesn't require that the data type `T` be

0 commit comments

Comments
 (0)