Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/processing_core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub enum ProcessingError {
PipelineCompileError(String),
#[error("Pipeline not ready after {0} frames")]
PipelineNotReady(u32),
#[error("`{0}` isn't on the GPU yet")]
ResourceNotReady(String),
#[error("Particles not found")]
ParticlesNotFound,
#[error("Grid not found")]
Expand Down
12 changes: 12 additions & 0 deletions crates/processing_render/src/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,18 @@ pub fn dispatch(
.clone();

let reflection = shader.reflection();
// a missing GPU resource drops its binding, and wgpu panics on an incomplete bind group
for param in reflection.parameters() {
let Some(name) = param.name() else { continue };
let ready = match (shader.buffer_handle(name), shader.image_handle(name)) {
(Some(handle), _) => gpu_buffers.get(handle).is_some(),
(_, Some(handle)) => gpu_images.get(handle).is_some(),
_ => true,
};
if !ready {
return Err(ProcessingError::ResourceNotReady(name.to_string()));
}
}

let mut bind_groups = Vec::new();
for (group, desc) in &layout_descriptors {
Expand Down
5 changes: 4 additions & 1 deletion crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2553,7 +2553,10 @@ pub(crate) fn compute_dispatch_no_update(
z: u32,
) -> error::Result<()> {
app_mut(|app| match dispatch_inner(app, entity, x, y, z) {
Err(error::ProcessingError::PipelineNotReady(_)) => {
Err(
error::ProcessingError::PipelineNotReady(_)
| error::ProcessingError::ResourceNotReady(_),
) => {
app.update();
dispatch_inner(app, entity, x, y, z)
}
Expand Down
47 changes: 34 additions & 13 deletions crates/processing_render/src/material/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,27 @@ pub(crate) fn apply_reflect_field(
return Ok(());
}

let param_name = find_param_containing_field(shader, name);
if let Some(param_name) = param_name
&& let Some(param) = shader.field_mut(&param_name)
// `struct.field` picks a struct explicitly
let (param_name, field_name) = match name.split_once('.') {
Some((param, field)) => (param.to_string(), field),
None => {
let params = params_containing_field(shader, name);
if params.len() > 1 {
return Err(ProcessingError::InvalidArgument(format!(
"`{name}` is a field of {}; name one, e.g. `{}.{name}`",
params.join(" and "),
params[0],
)));
}
let Some(param) = params.into_iter().next() else {
return Err(ProcessingError::UnknownShaderProperty(name.to_string()));
};
(param, name)
}
};
if let Some(param) = shader.field_mut(&param_name)
&& let ReflectMut::Struct(s) = param.reflect_mut()
&& let Some(field) = s.field_mut(name)
&& let Some(field) = s.field_mut(field_name)
{
apply_field_coerced(field, value);
return Ok(());
Expand Down Expand Up @@ -509,15 +525,20 @@ pub(crate) fn find_param_containing_field(
shader: &DynamicShader,
field_name: &str,
) -> Option<String> {
for i in 0..shader.field_len() {
if let Some(field) = shader.field_at(i)
&& let ReflectRef::Struct(s) = field.reflect_ref()
&& s.field(field_name).is_some()
{
return shader.name_at(i).map(|s: &str| s.to_string());
}
}
None
params_containing_field(shader, field_name)
.into_iter()
.next()
}

fn params_containing_field(shader: &DynamicShader, field_name: &str) -> Vec<String> {
(0..shader.field_len())
.filter(|&i| {
shader.field_at(i).is_some_and(|field| {
matches!(field.reflect_ref(), ReflectRef::Struct(s) if s.field(field_name).is_some())
})
})
.filter_map(|i| shader.name_at(i).map(str::to_string))
.collect()
}

pub struct CustomMaterialPlugin;
Expand Down
12 changes: 6 additions & 6 deletions crates/processing_render/src/particles/algebra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bevy::prelude::Entity;
use processing_core::error::{ProcessingError, Result};

use crate::shader_value::ShaderValue;
use crate::{buffer_size, compute_dispatch, compute_set, shader_create_with_features};
use crate::{buffer_size, compute_dispatch_no_update, compute_set, shader_create_with_features};

const WG: u32 = 64;

Expand Down Expand Up @@ -96,7 +96,7 @@ static MAP: Mutex<Option<(Entity, Entity)>> = Mutex::new(None);

fn dispatch_particles(compute: Entity, floats: u64, components: u32) -> Result<()> {
let n = (floats / components as u64) as u32;
compute_dispatch(compute, n.div_ceil(WG), 1, 1)
compute_dispatch_no_update(compute, n.div_ceil(WG), 1, 1)
}

fn check_components(verb: &str, components: u32) -> Result<()> {
Expand Down Expand Up @@ -373,7 +373,7 @@ pub fn lookup(
compute_set(c, "tex", ShaderValue::Texture(tex))?;
compute_set(c, "samp", ShaderValue::Texture(tex))?;
let n = (buffer_size(dst)? / 16) as u32;
compute_dispatch(c, n.div_ceil(WG), 1, 1)
compute_dispatch_no_update(c, n.div_ceil(WG), 1, 1)
}

pub const REDUCE_LENGTH: u32 = 0;
Expand Down Expand Up @@ -430,7 +430,7 @@ pub fn reduce_components(dst: Entity, src: Entity, components: u32, op: u32) ->
compute_set(c, "components", ShaderValue::UInt(components))?;
compute_set(c, "op", ShaderValue::UInt(op))?;
let n = (buffer_size(dst)? / 4) as u32;
compute_dispatch(c, n.div_ceil(WG), 1, 1)
compute_dispatch_no_update(c, n.div_ceil(WG), 1, 1)
}

const EXTRACT_SRC: &str = r#"
Expand Down Expand Up @@ -465,7 +465,7 @@ pub fn extract(dst: Entity, src: Entity, components: u32, index: u32) -> Result<
compute_set(c, "components", ShaderValue::UInt(components))?;
compute_set(c, "index", ShaderValue::UInt(index))?;
let n = (buffer_size(dst)? / 4) as u32;
compute_dispatch(c, n.div_ceil(WG), 1, 1)
compute_dispatch_no_update(c, n.div_ceil(WG), 1, 1)
}

const PACK_SRC: &str = r#"
Expand Down Expand Up @@ -534,7 +534,7 @@ pub fn pack(dst: Entity, sources: &[Entity]) -> Result<()> {
compute_set(c, "dst", ShaderValue::Buffer(dst))?;
compute_set(c, "components", ShaderValue::UInt(components))?;
let n = (buffer_size(sources[0])? / 4) as u32;
compute_dispatch(c, n.div_ceil(WG), 1, 1)
compute_dispatch_no_update(c, n.div_ceil(WG), 1, 1)
}

pub const GEN_UNIFORM: u32 = 0;
Expand Down
Loading