use std::borrow::Cow;
use std::sync::atomic::{AtomicBool, Ordering};
use bevy::prelude::*;
use bevy::render::render_resource::{
BindGroupLayoutDescriptor, CachedComputePipelineId, CachedPipelineState, ComputePipeline,
ComputePipelineDescriptor, PipelineCache,
};
use bevy::shader::{ShaderCacheError, ShaderDefVal};
pub(crate) const WG3: u32 = 4;
pub(crate) struct Kernel {
id: CachedComputePipelineId,
pub layout: BindGroupLayoutDescriptor,
entry: &'static str,
reported: AtomicBool,
}
pub(crate) fn queue_kernel(
cache: &PipelineCache,
shader: Handle<Shader>,
entry: &'static str,
layout: BindGroupLayoutDescriptor,
defs: Vec<ShaderDefVal>,
) -> Kernel {
let id = cache.queue_compute_pipeline(ComputePipelineDescriptor {
label: Some(Cow::Borrowed(entry)),
layout: vec![layout.clone()],
shader,
shader_defs: defs,
entry_point: Some(Cow::Borrowed(entry)),
zero_initialize_workgroup_memory: true,
..default()
});
Kernel {
id,
layout,
entry,
reported: AtomicBool::new(false),
}
}
pub(crate) fn ready<'a>(cache: &'a PipelineCache, kernel: &Kernel) -> Option<&'a ComputePipeline> {
match cache.get_compute_pipeline_state(kernel.id) {
CachedPipelineState::Ok(_) => cache.get_compute_pipeline(kernel.id),
CachedPipelineState::Err(
ShaderCacheError::ShaderNotLoaded(_) | ShaderCacheError::ShaderImportNotYetAvailable,
) => None,
CachedPipelineState::Err(error) => {
if !kernel.reported.swap(true, Ordering::Relaxed) {
error!(
"bevy_elements kernel `{}` failed to compile and its domain will stay idle: {error}",
kernel.entry
);
}
None
}
CachedPipelineState::Queued | CachedPipelineState::Creating(_) => None,
}
}
pub(crate) fn groups(cells: u32, edge: u32) -> u32 {
cells.div_ceil(edge)
}