use crate::ra;
#[cfg(doc)]
use crate::writer::Writer;
#[derive(Clone, Copy, Debug)]
pub(crate) enum Indirection {
Place,
Ordinary,
Ref,
}
#[derive(Clone, Copy, Debug)]
pub(crate) enum TypeTranslation {
RustScalar,
ShaderScalar,
Simd,
}
impl From<naga::AddressSpace> for TypeTranslation {
fn from(value: naga::AddressSpace) -> Self {
match value {
naga::AddressSpace::Function | naga::AddressSpace::Private => Self::Simd,
naga::AddressSpace::Uniform
| naga::AddressSpace::Handle
| naga::AddressSpace::WorkGroup
| naga::AddressSpace::Immediate
| naga::AddressSpace::Storage { .. } => Self::ShaderScalar,
naga::AddressSpace::TaskPayload
| naga::AddressSpace::RayPayload
| naga::AddressSpace::IncomingRayPayload => {
unimplemented!("mesh and raytracing shaders are not supported")
}
}
}
}
pub(crate) struct GlobalTranslation {
pub location: GlobalLocation,
pub requires_resource_struct_lifetime: bool,
pub declaration_indirection: Option<ra::PtrKind>,
pub global_expr_indirection: Indirection,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum GlobalLocation {
Variable,
Resource,
}
impl GlobalTranslation {
pub fn get(module: &naga::Module, global: &naga::GlobalVariable) -> Self {
let (declaration_indirection, global_expr_indirection, location): (
Option<ra::PtrKind>,
Indirection,
GlobalLocation,
) = match global.space {
naga::AddressSpace::Private => (None, Indirection::Place, GlobalLocation::Variable),
naga::AddressSpace::WorkGroup => (None, Indirection::Place, GlobalLocation::Variable),
naga::AddressSpace::Uniform => (None, Indirection::Place, GlobalLocation::Resource),
naga::AddressSpace::Handle => (None, Indirection::Ordinary, GlobalLocation::Resource),
naga::AddressSpace::Storage { access } => (
Some(
if access.contains(naga::StorageAccess::STORE)
&& !access.contains(naga::StorageAccess::ATOMIC)
{
ra::PtrKind::Exclusive(Some("g"))
} else {
ra::PtrKind::Shared(Some("g"))
},
),
Indirection::Ref,
GlobalLocation::Resource,
),
naga::AddressSpace::Immediate => todo!(),
naga::AddressSpace::TaskPayload => todo!(),
naga::AddressSpace::RayPayload => todo!(),
naga::AddressSpace::IncomingRayPayload => todo!(),
naga::AddressSpace::Function => unreachable!(),
};
let type_is_image = matches!(module.types[global.ty].inner, naga::TypeInner::Image { .. });
let requires_resource_struct_lifetime = type_is_image || declaration_indirection.is_some();
Self {
location,
requires_resource_struct_lifetime,
declaration_indirection,
global_expr_indirection,
}
}
}
impl GlobalLocation {
pub fn filter(
self,
module: &naga::Module,
) -> impl Iterator<
Item = (
naga::Handle<naga::GlobalVariable>,
&naga::GlobalVariable,
GlobalTranslation,
),
> {
module
.global_variables
.iter()
.filter_map(move |(handle, global)| {
let var_translation = GlobalTranslation::get(module, global);
if var_translation.location == self {
Some((handle, global, var_translation))
} else {
None
}
})
}
}