use crate::backend::{GpuBackend, GpuBackendError, GpuDispatch, ShaderBinding};
pub trait Shader: Sized + 'static {
fn from_backend(b: &GpuBackend) -> Result<Self, GpuBackendError>;
}
pub trait ShaderArgsType {
type For<'a>: ShaderArgs<'a>;
const WORKGROUP_SIZE: [u32; 3] = [1, 1, 1];
}
impl ShaderArgsType for () {
type For<'a> = ();
}
#[derive(thiserror::Error, Debug)]
pub enum ShaderArgsError {
#[error("argument not found: {0}")]
ArgNotFound(String),
}
#[derive(Clone, Debug, Default)]
pub struct BindGroupLayoutInfo {
pub groups: Vec<Vec<ShaderBinding>>,
}
pub trait ShaderArgs<'b> {
const PUSH_CONSTANT_SIZE: u32 = 0;
fn bind_group_layouts() -> BindGroupLayoutInfo {
BindGroupLayoutInfo::default()
}
fn write_arg<'a>(
&'b self,
binding: ShaderBinding,
dispatch: &mut GpuDispatch<'a>,
) -> Result<(), ShaderArgsError>
where
'b: 'a;
}
impl<'b> ShaderArgs<'b> for () {
fn write_arg<'a>(
&'b self,
_binding: ShaderBinding,
_dispatch: &mut GpuDispatch<'a>,
) -> Result<(), ShaderArgsError>
where
'b: 'a,
{
Ok(())
}
}
impl<'b, T: ShaderArgs<'b>> ShaderArgs<'b> for Option<T> {
fn write_arg<'a>(
&'b self,
binding: ShaderBinding,
dispatch: &mut GpuDispatch<'a>,
) -> Result<(), ShaderArgsError>
where
'b: 'a,
{
match self {
Some(arg) => arg.write_arg(binding, dispatch),
None => Ok(()),
}
}
}
impl<'b, T: ShaderArgs<'b>> ShaderArgs<'b> for &'b T {
fn write_arg<'a>(
&'b self,
binding: ShaderBinding,
dispatch: &mut GpuDispatch<'a>,
) -> Result<(), ShaderArgsError>
where
'b: 'a,
{
(*self).write_arg(binding, dispatch)
}
}