#![allow(clippy::unreadable_literal)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) enum Kind {
Uniform,
Storage { read_only: bool },
Texture { array: bool, filterable: bool },
Depth { multisampled: bool },
Sampler,
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct Binding {
pub(crate) slot: u32,
pub(crate) kind: Kind,
pub(crate) stages: u32,
pub(crate) dynamic: bool,
}
const VERTEX: u32 = 1;
const FRAGMENT: u32 = 2;
const COMPUTE: u32 = 4;
impl ShaderSource {
pub(crate) fn wgsl(&self) -> String {
let mut out = String::new();
for (i, &piece) in self.pieces.iter().enumerate() {
if i > 0 {
out.push_str("\n\n");
}
let (start, end) = PIECES[piece as usize];
out.push_str(&WGSL[start as usize..end as usize]);
}
out
}
pub(crate) fn size(&self) -> usize {
self.pieces
.iter()
.map(|&piece| {
let (start, end) = PIECES[piece as usize];
(end - start) as usize
})
.sum()
}
}
static WGSL: &str = include_str!(concat!(env!("OUT_DIR"), "/shaders.wgsl"));
pub(crate) struct ShaderSource {
pub(crate) label: &'static str,
pieces: &'static [u16],
pub(crate) pass: &'static [Binding],
pub(crate) overrides: &'static [&'static str],
pub(crate) shared: bool,
}
impl Binding {
pub(crate) fn layout_entry(&self) -> wgpu::BindGroupLayoutEntry {
let mut visibility = wgpu::ShaderStages::NONE;
for (bit, stage) in [
(VERTEX, wgpu::ShaderStages::VERTEX),
(FRAGMENT, wgpu::ShaderStages::FRAGMENT),
(COMPUTE, wgpu::ShaderStages::COMPUTE),
] {
if self.stages & bit != 0 {
visibility |= stage;
}
}
let ty = match self.kind {
Kind::Uniform => wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: self.dynamic,
min_binding_size: None,
},
Kind::Storage { read_only } => wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only },
has_dynamic_offset: self.dynamic,
min_binding_size: None,
},
Kind::Texture { array, filterable } => wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float { filterable },
view_dimension: if array {
wgpu::TextureViewDimension::D2Array
} else {
wgpu::TextureViewDimension::D2
},
multisampled: false,
},
Kind::Depth { multisampled } => wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Depth,
view_dimension: wgpu::TextureViewDimension::D2,
multisampled,
},
Kind::Sampler => wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
};
wgpu::BindGroupLayoutEntry { binding: self.slot, visibility, ty, count: None }
}
}
include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
const _: () = assert!(BLOCK_ROWS as usize == crate::data::PAGE_ROWS && 1 << PAGE_BITS == BLOCK_ROWS);