Skip to content

Commit a34a91c

Browse files
committed
clean up
1 parent 88d77b3 commit a34a91c

File tree

4 files changed

+62
-58
lines changed

4 files changed

+62
-58
lines changed

crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl ViewNode for MainOpaquePass3dNode {
8484
load: match camera_3d.clear_color {
8585
ClearColorConfig::None => LoadOp::Load,
8686
// TODO clear this earlier?
87-
_ => LoadOp::Clear(EntityTextures::clear_color()),
87+
_ => LoadOp::Clear(EntityTextures::no_entity_color()),
8888
},
8989
store: true,
9090
})));

crates/bevy_core_pipeline/src/entity_index_buffer_copy/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ impl ViewNode for EntityIndexBufferCopyNode {
2424
let Some(buffers) = gpu_picking_camera.buffers.as_ref() else {
2525
return Ok(());
2626
};
27+
2728
// copy entity index texture
2829
buffers.copy_texture_to_buffer(
2930
render_context.command_encoder(),
@@ -38,10 +39,7 @@ impl ViewNode for EntityIndexBufferCopyNode {
3839
pub struct EntityIndexBufferCopyPlugin;
3940
impl Plugin for EntityIndexBufferCopyPlugin {
4041
fn build(&self, app: &mut bevy_app::App) {
41-
let render_app = match app.get_sub_app_mut(RenderApp) {
42-
Ok(render_app) => render_app,
43-
Err(_) => return,
44-
};
42+
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else { return; };
4543

4644
// 3D
4745
use crate::core_3d::graph::node::*;

crates/bevy_render/src/picking.rs

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
camera::ExtractedCamera,
33
extract_component::ExtractComponentPlugin,
4-
render_resource::{Buffer, Texture},
4+
render_resource::{Buffer, BufferSlice, Texture},
55
renderer::RenderDevice,
66
texture::{CachedTexture, TextureFormatPixelInfo},
77
Render, RenderApp, RenderSet,
@@ -50,28 +50,21 @@ fn send_buffer_to_main_world(
5050
return;
5151
};
5252

53-
// sync
54-
if false {
55-
let buffer_slice = buffers.entity_buffer.slice(..);
56-
buffer_slice.map_async(MapMode::Read, move |result| {
57-
if let Err(e) = result {
58-
panic!("MAP ERROR: {e}");
59-
}
60-
});
61-
62-
// WARN This is blocking
63-
render_device.poll(Maintain::Wait);
64-
53+
// Send the data to the main world
54+
fn send(
55+
sender: Sender<GpuPickingData>,
56+
padded_bytes_per_row: usize,
57+
entity_buffer: &Buffer,
58+
buffer_slice: BufferSlice,
59+
) {
6560
let buffer_view = buffer_slice.get_mapped_range();
66-
// we immediately move the data to CPU to avoid holding the mapped view for long
61+
// immediately copy the data to CPU to avoid holding the mapped view for long
6762
let entity_data = Vec::from(&*buffer_view);
6863
drop(buffer_view);
69-
buffers.entity_buffer.unmap();
70-
// drop(entity_buffer);
64+
entity_buffer.unmap();
7165

72-
// Send the buffer to the main world
73-
if let Err(err) = gpu_picking_camera.sender.try_send(GpuPickingData {
74-
padded_bytes_per_row: buffers.buffer_dimensions.padded_bytes_per_row,
66+
if let Err(err) = sender.try_send(GpuPickingData {
67+
padded_bytes_per_row,
7568
entity_data,
7669
}) {
7770
match err {
@@ -81,18 +74,42 @@ fn send_buffer_to_main_world(
8174
}
8275
}
8376
}
77+
78+
// This can only fail if the sender is full or closed
79+
// and we can't do anything if either of those things happen
80+
// let _ = sender.try_send(GpuPickingData {
81+
// padded_bytes_per_row,
82+
// entity_data,
83+
// });
84+
}
85+
86+
if true {
87+
// sync
88+
let buffer_slice = buffers.entity_buffer.slice(..);
89+
buffer_slice.map_async(MapMode::Read, move |result| match result {
90+
Ok(_) => {}
91+
Err(err) => bevy_log::error!("Failed to map entity buffer: {err}"),
92+
});
93+
94+
// WARN This is blocking
95+
render_device.poll(Maintain::Wait);
96+
97+
// Send the buffer to the main world
98+
send(
99+
gpu_picking_camera.sender.clone(),
100+
buffers.buffer_dimensions.padded_bytes_per_row,
101+
&buffers.entity_buffer,
102+
buffer_slice,
103+
);
84104
} else {
105+
// async
85106
let entity_buffer = buffers.entity_buffer.clone();
86107
let sender = gpu_picking_camera.sender.clone();
87108
let padded_bytes_per_row = buffers.buffer_dimensions.padded_bytes_per_row;
88109

89110
// Mapping the buffer is an asynchronous process.
90111
// This means we need to wait until the buffer is mapped before sending it to the main world
91112
let task = async move {
92-
if sender.is_full() {
93-
return;
94-
}
95-
96113
let (tx, rx) = async_channel::bounded(1);
97114

98115
// map entity buffer
@@ -105,46 +122,35 @@ fn send_buffer_to_main_world(
105122
// Buffer is mapped and ready to be sent
106123
rx.recv().await.unwrap();
107124

108-
let buffer_view = buffer_slice.get_mapped_range();
109-
// immediately move the data to CPU to avoid holding the mapped view for long
110-
let entity_data = Vec::from(&*buffer_view);
111-
drop(buffer_view);
112-
entity_buffer.unmap();
113-
drop(entity_buffer);
114-
115125
// Send the buffer to the main world
116-
if let Err(err) = sender.try_send(GpuPickingData {
117-
padded_bytes_per_row,
118-
entity_data,
119-
}) {
120-
match err {
121-
TrySendError::Full(_) => bevy_log::error!("GPU Picking channel is full"),
122-
TrySendError::Closed(_) => {
123-
bevy_log::error!("GPU Picking channel is closed");
124-
}
125-
}
126-
}
126+
send(sender, padded_bytes_per_row, &entity_buffer, buffer_slice);
127127
};
128128
AsyncComputeTaskPool::get().spawn(task).detach();
129129
}
130130
}
131131
}
132132

133+
/// Marker component to indicate that a mesh should be available for gpu picking
133134
#[derive(Component, ExtractComponent, Clone)]
134135
pub struct GpuPickingMesh;
135136

137+
/// Data needed in the render world to manage the entity buffer
136138
#[derive(Component)]
137139
pub struct ExtractedGpuPickingCamera {
138140
pub buffers: Option<GpuPickingCameraBuffers>,
139141
sender: Sender<GpuPickingData>,
140142
}
141143

144+
/// Data sent between the render world and main world
142145
#[derive(Default)]
143146
struct GpuPickingData {
144147
padded_bytes_per_row: usize,
145148
entity_data: Vec<u8>,
146149
}
147150

151+
/// This component is used to indicate if a camera should support gpu picking.
152+
/// Any mesh with the [`GpuPickingMesh`] component that is visible from this camera
153+
/// will be pickable.
148154
#[derive(Component)]
149155
pub struct GpuPickingCamera {
150156
channel: (Sender<GpuPickingData>, Receiver<GpuPickingData>),
@@ -160,7 +166,7 @@ impl Default for GpuPickingCamera {
160166
impl GpuPickingCamera {
161167
pub fn new() -> Self {
162168
Self {
163-
channel: async_channel::bounded(1),
169+
channel: async_channel::unbounded(),
164170
data: GpuPickingData::default(),
165171
}
166172
}
@@ -211,9 +217,10 @@ impl crate::extract_component::ExtractComponent for GpuPickingCamera {
211217
}
212218
}
213219

220+
/// Contains the buffer and it's dimension required for gpu picking
214221
pub struct GpuPickingCameraBuffers {
215222
pub entity_buffer: Buffer,
216-
pub buffer_dimensions: BufferDimensions,
223+
buffer_dimensions: BufferDimensions,
217224
}
218225

219226
impl GpuPickingCameraBuffers {
@@ -223,6 +230,8 @@ impl GpuPickingCameraBuffers {
223230
texture: &Texture,
224231
buffer: &Buffer,
225232
) {
233+
// This can't be in the Node because it needs access to wgpu but
234+
// bevy_core_pipeline doesn't depend on wgpu
226235
encoder.copy_texture_to_buffer(
227236
texture.as_image_copy(),
228237
wgpu::ImageCopyBuffer {
@@ -275,7 +284,7 @@ pub struct EntityTextures {
275284

276285
impl EntityTextures {
277286
/// This is the color that will represent "no entity" in the entity buffer
278-
pub fn clear_color() -> wgpu::Color {
287+
pub fn no_entity_color() -> wgpu::Color {
279288
let v = entity_as_uvec2(Entity::PLACEHOLDER);
280289
// The texture only uses the red and green channel
281290
Color {
@@ -315,16 +324,13 @@ fn prepare_gpu_picking_buffers(
315324
for (entity, camera, mut gpu_picking_camera) in &mut cameras {
316325
let Some(size) = camera.physical_target_size else { continue; };
317326

327+
// TODO create 2 buffers and altenate between each buffer each frame
328+
318329
// Only create a buffer if it doesn't already exist or the size is different
319-
let mut create_buffer = false;
330+
let mut create_buffer = true;
320331
if let Some((buffer_dimensions, _)) = buffer_cache.get(&entity) {
321-
if buffer_dimensions.width != size.x as usize
322-
|| buffer_dimensions.height != size.y as usize
323-
{
324-
create_buffer = true;
325-
}
326-
} else {
327-
create_buffer = true;
332+
create_buffer = buffer_dimensions.width != size.x as usize
333+
|| buffer_dimensions.height != size.y as usize;
328334
}
329335

330336
if create_buffer {

examples/input/gpu_picking.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use bevy_internal::{
1111

1212
fn main() {
1313
App::new()
14-
.insert_resource(Msaa::Off)
14+
// .insert_resource(Msaa::Off)
1515
.add_plugins(DefaultPlugins.set(WindowPlugin {
1616
primary_window: Some(Window {
1717
present_mode: PresentMode::AutoNoVsync,

0 commit comments

Comments
 (0)