use quote::format_ident;
use syn::Ident;
use crate::qs::{quote, Index, TokenStream};
use crate::FastIndexMap;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum BindResourceType {
Buffer,
Sampler,
Texture,
}
#[derive(Clone)]
pub struct BindingGenerator {
pub bind_group_layout: BindGroupLayoutGenerator,
pub pipeline_layout: PipelineLayoutGenerator,
}
impl std::fmt::Debug for BindingGenerator {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct BindGroupLayoutGenerator {
pub name_prefix: String,
pub uses_lifetime: bool,
pub entry_struct_type: TokenStream,
pub entry_constructor: fn(usize, TokenStream, BindResourceType) -> TokenStream,
pub binding_type_map: FastIndexMap<BindResourceType, TokenStream>,
}
impl BindGroupLayoutGenerator {
pub(crate) fn bind_group_name_ident(&self, group_index: u32) -> Ident {
format_ident!("{}{}", self.name_prefix, group_index)
}
pub(crate) fn bind_group_entry_collection_struct_name_ident(
&self,
group_index: u32,
) -> Ident {
format_ident!("{}{}{}", self.name_prefix, group_index, "EntryCollection")
}
}
#[derive(Clone, Debug)]
pub struct PipelineLayoutGenerator {
pub layout_name: String,
pub bind_group_layout_type: TokenStream,
}
pub trait GetBindingsGeneratorConfig {
fn get_generator_config(self) -> BindingGenerator;
}
impl GetBindingsGeneratorConfig for BindingGenerator {
fn get_generator_config(self) -> BindingGenerator {
self
}
}
impl Default for BindingGenerator {
fn default() -> BindingGenerator {
WgpuGetBindingsGeneratorConfig.get_generator_config()
}
}
pub struct WgpuGetBindingsGeneratorConfig;
impl WgpuGetBindingsGeneratorConfig {
fn get_bind_group_layout_generator_config() -> BindGroupLayoutGenerator {
let binding_type_map = vec![
(BindResourceType::Buffer, quote! { wgpu::BufferBinding<'a> }),
(BindResourceType::Sampler, quote! { &'a wgpu::Sampler }),
(BindResourceType::Texture, quote! { &'a wgpu::TextureView }),
]
.into_iter()
.collect::<FastIndexMap<_, _>>();
fn entry_constructor(
binding: usize,
binding_var: TokenStream,
resource_type: BindResourceType,
) -> TokenStream {
let resource = match resource_type {
BindResourceType::Buffer => {
quote!(wgpu::BindingResource::Buffer(#binding_var))
}
BindResourceType::Sampler => {
quote!(wgpu::BindingResource::Sampler(#binding_var))
}
BindResourceType::Texture => {
quote!(wgpu::BindingResource::TextureView(#binding_var))
}
};
let binding = Index::from(binding);
quote! {
wgpu::BindGroupEntry {
binding: #binding,
resource: #resource,
}
}
}
BindGroupLayoutGenerator {
name_prefix: "WgpuBindGroup".into(),
uses_lifetime: true,
entry_struct_type: quote!(wgpu::BindGroupEntry<'a>),
entry_constructor,
binding_type_map,
}
}
fn get_pipeline_layout_generator() -> PipelineLayoutGenerator {
PipelineLayoutGenerator {
layout_name: "WgpuPipelineLayout".into(),
bind_group_layout_type: quote!(wgpu::BindGroupLayout),
}
}
}
impl GetBindingsGeneratorConfig for WgpuGetBindingsGeneratorConfig {
fn get_generator_config(self) -> BindingGenerator {
let bind_group_layout = Self::get_bind_group_layout_generator_config();
let pipeline_layout = Self::get_pipeline_layout_generator();
BindingGenerator {
bind_group_layout,
pipeline_layout,
}
}
}