sierra_proc/
lib.rs

1use std::convert::TryFrom as _;
2
3extern crate proc_macro;
4
5mod binding_flags;
6mod descriptors;
7mod format;
8mod graphics_pipeline;
9mod layout;
10mod pass;
11mod pipeline;
12mod pipeline_stages;
13mod repr;
14mod shader_stage;
15mod swizzle;
16
17#[proc_macro_derive(Descriptors, attributes(sierra))]
18pub fn descriptors(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
19    descriptors::descriptors(item).into()
20}
21
22#[proc_macro_derive(ShaderRepr, attributes(sierra))]
23pub fn shader_repr(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
24    repr::shader_repr(item).into()
25}
26
27#[proc_macro_derive(PipelineInput, attributes(sierra))]
28pub fn pipeline_input(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
29    pipeline::pipeline_input(item).into()
30}
31
32#[proc_macro_derive(Pass, attributes(sierra))]
33pub fn render_pass(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
34    pass::pass(item).into()
35}
36
37#[proc_macro]
38pub fn graphics_pipeline_desc(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
39    graphics_pipeline::graphics_pipeline_desc(item).into()
40}
41
42#[proc_macro]
43pub fn shader_stages(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
44    shader_stage::shader_stages(tokens).into()
45}
46
47#[proc_macro]
48pub fn binding_flags(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
49    binding_flags::binding_flags(tokens).into()
50}
51
52#[proc_macro]
53pub fn pipeline_stages(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
54    pipeline_stages::pipeline_stages(tokens).into()
55}
56
57#[proc_macro]
58pub fn swizzle(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
59    swizzle::swizzle(item).into()
60}
61
62#[proc_macro]
63pub fn format(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
64    format::format(item).into()
65}
66
67fn validate_member(member: &syn::Member, item_struct: &syn::ItemStruct) -> syn::Result<u32> {
68    match (member, &item_struct.fields) {
69        (syn::Member::Named(member_ident), syn::Fields::Named(fields)) => {
70            for (index, field) in fields.named.iter().enumerate() {
71                let field_ident = field.ident.as_ref().unwrap();
72                if *field_ident == *member_ident {
73                    return u32::try_from(index)
74                        .map_err(|_| syn::Error::new_spanned(member, "Too many fields"));
75                }
76            }
77            Err(syn::Error::new_spanned(
78                member,
79                "Member not found in structure",
80            ))
81        }
82        (syn::Member::Unnamed(unnamed), syn::Fields::Unnamed(fields)) => {
83            let valid =
84                usize::try_from(unnamed.index).map_or(false, |index| index < fields.unnamed.len());
85            if !valid {
86                Err(syn::Error::new_spanned(
87                    member,
88                    "Member index is out of bounds",
89                ))
90            } else {
91                Ok(unnamed.index)
92            }
93        }
94        (syn::Member::Named(named), syn::Fields::Unnamed(_)) => Err(syn::Error::new_spanned(
95            named,
96            "Unexpected unnamed member for tuple-struct",
97        )),
98        (syn::Member::Unnamed(unnamed), syn::Fields::Named(_)) => Err(syn::Error::new_spanned(
99            unnamed,
100            "Unexpected named member for struct",
101        )),
102        (member, syn::Fields::Unit) => Err(syn::Error::new_spanned(
103            member,
104            "Unexpected member reference for unit-struct",
105        )),
106    }
107}
108
109// fn parse_attrs_with<T>(
110//     attrs: &[syn::Attribute],
111//     mut f: fn(syn::parse::ParseStream) -> syn::Result<T>,
112// ) -> syn::Result<Punctuated<T, syn::Token![,]>> {
113//     let mut result = Punctuated::new();
114
115//     for attr in attrs {
116//         if attr.path.is_ident("sierra") {
117//             let array = attr.parse_args_with(|stream: syn::parse::ParseStream| {
118//                 stream.parse_terminated::<_, syn::Token![,]>(f)
119//             })?;
120//             result.extend(array.into_pairs());
121//         }
122//     }
123
124//     Ok(result)
125// }
126
127mod kw {
128    proc_easy::easy_token!(acceleration_structure);
129    proc_easy::easy_token!(buffer);
130    proc_easy::easy_token!(image);
131    proc_easy::easy_token!(sampled);
132    proc_easy::easy_token!(sampler);
133    proc_easy::easy_token!(uniform);
134    proc_easy::easy_token!(storage);
135    proc_easy::easy_token!(texel);
136    proc_easy::easy_token!(subpass);
137    proc_easy::easy_token!(color);
138    proc_easy::easy_token!(depth);
139    proc_easy::easy_token!(clear);
140    proc_easy::easy_token!(load);
141    proc_easy::easy_token!(store);
142    proc_easy::easy_token!(capacity);
143    proc_easy::easy_token!(set);
144    proc_easy::easy_token!(push);
145    proc_easy::easy_token!(layout);
146    proc_easy::easy_token!(attachment);
147    proc_easy::easy_token!(top_of_pipe);
148    proc_easy::easy_token!(draw_indirect);
149    proc_easy::easy_token!(vertex_input);
150    proc_easy::easy_token!(vertex_shader);
151    proc_easy::easy_token!(tessellation_control_shader);
152    proc_easy::easy_token!(tessellation_evaluation_shader);
153    proc_easy::easy_token!(geometry_shader);
154    proc_easy::easy_token!(early_fragment_tests);
155    proc_easy::easy_token!(fragment_shader);
156    proc_easy::easy_token!(late_fragment_tests);
157    proc_easy::easy_token!(color_attachment_output);
158    proc_easy::easy_token!(compute_shader);
159    proc_easy::easy_token!(transfer);
160    proc_easy::easy_token!(bottom_of_pipe);
161    proc_easy::easy_token!(host);
162    proc_easy::easy_token!(all_graphics);
163    proc_easy::easy_token!(all_commands);
164    proc_easy::easy_token!(ray_tracing_shader);
165    proc_easy::easy_token!(acceleration_structure_build);
166    proc_easy::easy_token!(dependency);
167    proc_easy::easy_token!(external);
168}