Skip to content

Commit c397baf

Browse files
committed
Fix sync pattern.
1 parent e29c44c commit c397baf

3 files changed

Lines changed: 59 additions & 3 deletions

File tree

crates/processing_render/src/compute.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ use crate::material::custom::{Shader, apply_reflect_field, shader_value_to_refle
2525
use crate::shader_value::ShaderValue;
2626
use processing_core::error::{ProcessingError, Result};
2727

28+
pub struct ComputePlugin;
29+
30+
impl Plugin for ComputePlugin {
31+
fn build(&self, app: &mut App) {
32+
app.add_systems(Last, invalidate_rw_buffers);
33+
}
34+
}
35+
2836
#[derive(Component)]
2937
pub struct Buffer {
3038
pub handle: Handle<ShaderBuffer>,
@@ -34,6 +42,10 @@ pub struct Buffer {
3442
/// when a pipeline that may write to the buffer runs; the next read or
3543
/// write must readback first.
3644
pub synced: bool,
45+
/// Set permanently once the buffer is bound to any pipeline as read_write
46+
/// storage. When true, any frame tick could have mutated GPU contents via
47+
/// a render pass, so `synced` must be cleared after each `app.update()`.
48+
pub bound_rw: bool,
3749
}
3850

3951
fn readback_buffer(device: &RenderDevice, size: u64) -> WgpuBuffer {
@@ -61,6 +73,7 @@ pub fn create_buffer(
6173
readback_buffer: readback_buffer(&render_device, size),
6274
size,
6375
synced: true,
76+
bound_rw: false,
6477
})
6578
.id()
6679
}
@@ -79,6 +92,7 @@ pub fn create_buffer_with_data(
7992
readback_buffer: readback_buffer(&render_device, size),
8093
size,
8194
synced: true,
95+
bound_rw: false,
8296
})
8397
.id()
8498
}
@@ -139,6 +153,14 @@ pub fn read_buffer_gpu(
139153
Ok(bytes)
140154
}
141155

156+
pub fn invalidate_rw_buffers(mut buffers: Query<&mut Buffer>) {
157+
for mut buf in &mut buffers {
158+
if buf.bound_rw {
159+
buf.synced = false;
160+
}
161+
}
162+
}
163+
142164
pub fn destroy_buffer(In(entity): In<Entity>, mut commands: Commands) -> Result<()> {
143165
commands.entity(entity).despawn();
144166
Ok(())
@@ -267,7 +289,7 @@ pub fn create_compute(app: &mut App, shader_entity: Entity) -> Result<Entity> {
267289
pub fn set_compute_property(
268290
In((entity, name, value)): In<(Entity, String, ShaderValue)>,
269291
mut computes: Query<&mut Compute>,
270-
p_buffers: Query<&Buffer>,
292+
mut p_buffers: Query<&mut Buffer>,
271293
p_images: Query<&PImage>,
272294
) -> Result<()> {
273295
use bevy_naga_reflect::reflect::ParameterCategory;
@@ -285,14 +307,15 @@ pub fn set_compute_property(
285307

286308
match (&value, category) {
287309
(ShaderValue::Buffer(buf_entity), ParameterCategory::Storage { read_only }) => {
288-
let buffer = p_buffers
289-
.get(*buf_entity)
310+
let mut buffer = p_buffers
311+
.get_mut(*buf_entity)
290312
.map_err(|_| ProcessingError::BufferNotFound)?;
291313
compute.shader.insert(&name, buffer.handle.clone());
292314
if read_only {
293315
compute.rw_buffers.remove(&name);
294316
} else {
295317
compute.rw_buffers.insert(name.clone(), *buf_entity);
318+
buffer.bound_rw = true;
296319
}
297320
Ok(())
298321
}

crates/processing_render/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ impl Plugin for ProcessingRenderPlugin {
6363
material::ProcessingMaterialPlugin,
6464
bevy::pbr::wireframe::WireframePlugin::default(),
6565
material::custom::CustomMaterialPlugin,
66+
compute::ComputePlugin,
6667
camera::OrbitCameraPlugin,
6768
bevy::camera_controller::free_camera::FreeCameraPlugin,
6869
bevy::camera_controller::pan_camera::PanCameraPlugin,

crates/processing_render/src/material/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod custom;
22
pub mod pbr;
33

4+
use crate::compute;
45
use crate::render::material::UntypedMaterial;
56
use crate::shader_value::ShaderValue;
67
use bevy::material::descriptor::RenderPipelineDescriptor;
@@ -12,6 +13,7 @@ use bevy::pbr::{
1213
use bevy::prelude::*;
1314
use bevy::render::render_resource::{AsBindGroup, BlendState};
1415
use bevy::shader::ShaderRef;
16+
use bevy_naga_reflect::reflect::ParameterCategory;
1517
use processing_core::error::{self, ProcessingError};
1618

1719
pub struct ProcessingMaterialPlugin;
@@ -59,6 +61,7 @@ pub fn set_property(
5961
material_handles: Query<&UntypedMaterial>,
6062
mut extended_materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, ProcessingMaterial>>>,
6163
mut custom_materials: ResMut<Assets<custom::CustomMaterial>>,
64+
mut p_buffers: Query<&mut compute::Buffer>,
6265
) -> error::Result<()> {
6366
let untyped = material_handles
6467
.get(entity)
@@ -79,6 +82,35 @@ pub fn set_property(
7982
let mut mat = custom_materials
8083
.get_mut(&handle)
8184
.ok_or(ProcessingError::MaterialNotFound)?;
85+
86+
if let ShaderValue::Buffer(buf_entity) = &value {
87+
let mut buffer = p_buffers
88+
.get_mut(*buf_entity)
89+
.map_err(|_| ProcessingError::BufferNotFound)?;
90+
91+
let category = mat
92+
.shader
93+
.reflection()
94+
.parameter(&name)
95+
.map(|p| p.category())
96+
.ok_or_else(|| ProcessingError::UnknownShaderProperty(name.clone()))?;
97+
98+
match category {
99+
ParameterCategory::Storage { read_only } => {
100+
mat.shader.insert(&name, buffer.handle.clone());
101+
if !read_only {
102+
buffer.bound_rw = true;
103+
}
104+
return Ok(());
105+
}
106+
cat => {
107+
return Err(ProcessingError::InvalidArgument(format!(
108+
"property `{name}` expects {cat:?}, got Buffer"
109+
)));
110+
}
111+
}
112+
}
113+
82114
return custom::set_property(&mut mat, &name, &value);
83115
}
84116

0 commit comments

Comments
 (0)