gfx_hal/pso/
specialization.rs1use std::{borrow::Cow, ops::Range, slice};
4
5#[derive(Debug, Clone, Hash, PartialEq)]
7pub struct SpecializationConstant {
8 pub id: u32,
10 pub range: Range<u16>,
12}
13
14#[derive(Debug, Clone)]
26pub struct Specialization<'a> {
27 pub constants: Cow<'a, [SpecializationConstant]>,
29 pub data: Cow<'a, [u8]>,
31}
32
33impl Specialization<'_> {
34 pub const EMPTY: Self = Specialization {
36 constants: Cow::Borrowed(&[]),
37 data: Cow::Borrowed(&[]),
38 };
39}
40
41impl Default for Specialization<'_> {
42 fn default() -> Self {
43 Specialization::EMPTY
44 }
45}
46
47#[doc(hidden)]
48#[derive(Debug, Default)]
49pub struct SpecializationStorage {
50 constants: Vec<SpecializationConstant>,
51 data: Vec<u8>,
52}
53
54#[doc(hidden)]
56pub trait SpecConstList: Sized {
57 fn fold(self, storage: &mut SpecializationStorage);
58}
59
60impl<T> From<T> for Specialization<'_>
61where
62 T: SpecConstList,
63{
64 fn from(list: T) -> Self {
65 let mut storage = SpecializationStorage::default();
66 list.fold(&mut storage);
67 Specialization {
68 data: Cow::Owned(storage.data),
69 constants: Cow::Owned(storage.constants),
70 }
71 }
72}
73
74#[doc(hidden)]
75#[derive(Debug)]
76pub struct SpecConstListNil;
77
78#[doc(hidden)]
79#[derive(Debug)]
80pub struct SpecConstListCons<H, T> {
81 pub head: (u32, H),
82 pub tail: T,
83}
84
85impl SpecConstList for SpecConstListNil {
86 fn fold(self, _storage: &mut SpecializationStorage) {}
87}
88
89impl<H, T> SpecConstList for SpecConstListCons<H, T>
90where
91 T: SpecConstList,
92{
93 fn fold(self, storage: &mut SpecializationStorage) {
94 let size = std::mem::size_of::<H>();
95 assert!(storage.data.len() + size <= u16::MAX as usize);
96 let offset = storage.data.len() as u16;
97 storage.data.extend_from_slice(unsafe {
98 let head_ptr: *const H = &self.head.1;
100 slice::from_raw_parts(head_ptr as *const u8, size)
101 });
102 storage.constants.push(SpecializationConstant {
103 id: self.head.0,
104 range: offset..offset + size as u16,
105 });
106 self.tail.fold(storage)
107 }
108}
109
110#[macro_export]
112macro_rules! spec_const_list {
113 (@ $(,)?) => {
114 $crate::pso::SpecConstListNil
115 };
116
117 (@ $head_id:expr => $head_constant:expr $(,$tail_id:expr => $tail_constant:expr)* $(,)?) => {
118 $crate::pso::SpecConstListCons {
119 head: ($head_id, $head_constant),
120 tail: $crate::spec_const_list!(@ $($tail_id => $tail_constant),*),
121 }
122 };
123
124 ($($id:expr => $constant:expr),* $(,)?) => {
125 $crate::spec_const_list!(@ $($id => $constant),*).into()
126 };
127
128 ($($constant:expr),* $(,)?) => {
129 {
130 let mut counter = 0;
131 $crate::spec_const_list!(@ $({ counter += 1; counter - 1 } => $constant),*).into()
132 }
133 };
134}