grafix_toolbox/kit/opengl/shader/
uniform.rs1use super::*;
2use crate::math::la;
3
4#[macro_export]
5macro_rules! Uniform {
6 ($bind: ident, ($n: expr, $v: expr)) => {{
7 let id = const { $crate::GL::macro_uses::uniforms_use::id($n) };
8 $bind.tap(|b| b.Uniform(id, $v))
9 }};
10}
11
12#[macro_export]
13macro_rules! Uniforms {
14 ($shd: ident, $(($n: expr, $v: expr)),+) => {{
15 let b = $shd.Bind();
16 $(let b = Uniform!(b, ($n, $v));)+
17 b
18 }};
19}
20
21pub enum ArgsKind {
22 Uniform,
23 Ubo,
24 Ssbo,
25}
26pub trait UniformArgs {
27 fn apply(&self, _: i32, _: UniCache);
28 fn kind(&self) -> ArgsKind {
29 ArgsKind::Uniform
30 }
31}
32
33macro_rules! impl_uniform {
34 ($v: ident, $t: ident, $f: ident) => {
35 impl UniformArgs for $t {
36 fn apply(&self, addr: i32, cached: UniCache) {
37 let apply = || {
38 DEBUG!("Setting GL Uniform {addr} to {self:?} in shader {}", ShaderT::bound_obj());
39 let s = &[*self];
40 $v(gl::$f, addr, s);
41 };
42
43 if let Some(CachedUni::$t(v)) = cached {
44 if v != self {
45 *v = *self;
46 apply();
47 }
48 } else {
49 apply();
50 *cached = Some(CachedUni::$t(*self));
51 }
52 }
53 }
54 };
55}
56fn val<T, S>(f: unsafe fn(i32, i32, *const T), name: i32, slice: &[S]) {
57 GL!(f(name, i32(slice.len()), slice.as_ptr() as *const T));
58}
59fn mat<S>(f: unsafe fn(i32, i32, GLbool, *const f32), name: i32, slice: &[S]) {
60 GL!(f(name, i32(slice.len()), gl::FALSE, slice.as_ptr() as *const f32)); }
62impl_uniform!(val, u32, Uniform1uiv);
63impl_uniform!(val, uVec2, Uniform2uiv);
64impl_uniform!(val, uVec3, Uniform3uiv);
65impl_uniform!(val, uVec4, Uniform4uiv);
66impl_uniform!(val, i32, Uniform1iv);
67impl_uniform!(val, iVec2, Uniform2iv);
68impl_uniform!(val, iVec3, Uniform3iv);
69impl_uniform!(val, iVec4, Uniform4iv);
70impl_uniform!(val, f32, Uniform1fv);
71impl_uniform!(val, Vec2, Uniform2fv);
72impl_uniform!(val, Vec3, Uniform3fv);
73impl_uniform!(val, Vec4, Uniform4fv);
74impl_uniform!(mat, Mat2, UniformMatrix2fv);
75impl_uniform!(mat, Mat3, UniformMatrix3fv);
76impl_uniform!(mat, Mat4, UniformMatrix4fv);
77impl_uniform!(mat, Mat2x3, UniformMatrix2x3fv);
78impl_uniform!(mat, Mat3x2, UniformMatrix3x2fv);
79impl_uniform!(mat, Mat2x4, UniformMatrix2x4fv);
80impl_uniform!(mat, Mat4x2, UniformMatrix4x2fv);
81impl_uniform!(mat, Mat3x4, UniformMatrix3x4fv);
82impl_uniform!(mat, Mat4x3, UniformMatrix4x3fv);
83
84macro_rules! impl_la_adapter {
85 ($t: ident, $lat: ident) => {
86 impl UniformArgs for la::$lat {
87 fn apply(&self, addr: i32, cached: UniCache) {
88 $t(*self).apply(addr, cached)
89 }
90 }
91 impl UniformArgs for &la::$lat {
92 fn apply(&self, addr: i32, cached: UniCache) {
93 (*self).apply(addr, cached)
94 }
95 }
96 };
97}
98impl_la_adapter!(Vec2, V2);
99impl_la_adapter!(Vec3, V3);
100impl_la_adapter!(Vec4, V4);
101impl_la_adapter!(Mat3, M3);
102impl_la_adapter!(Mat4, M4);
103
104impl<T: TexType> UniformArgs for GL::TextureBind<'_, T> {
105 fn apply(&self, addr: i32, cached: UniCache) {
106 let u = i32(self.u);
107 let apply = || {
108 DEBUG!("Binding GL texture {addr} to unit {u} in shader {}", ShaderT::bound_obj());
109 GL!(gl::Uniform1i(addr, u));
110 };
111
112 if let Some(CachedUni::TexUnit(unit)) = cached {
113 if *unit != u {
114 DEBUG!("GL texture {addr} was bound to unit {unit}");
115 apply();
116 *unit = u;
117 }
118 } else {
119 apply();
120 *cached = CachedUni::TexUnit(u).pipe(Some);
121 }
122 }
123}
124
125impl UniformArgs for GL::ShdArrBind<'_, Uniform> {
126 fn apply(&self, addr: i32, cached: UniCache) {
127 let l = i32(self.l);
128 let apply = || {
129 let prog = *ShaderT::bound_obj();
130 let addr = -2 - addr;
131 DEBUG!("Binding GL UBO {addr} to location {l} in shader {prog}");
132 GL!(gl::UniformBlockBinding(prog, u32(addr), u32(l)));
133 };
134
135 if let Some(CachedUni::UboLoc(loc)) = cached {
136 if *loc != l {
137 DEBUG!("GL UBO {addr} was bound to location {loc}");
138 apply();
139 *loc = l;
140 }
141 } else {
142 apply();
143 *cached = CachedUni::UboLoc(l).pipe(Some);
144 }
145 }
146 fn kind(&self) -> ArgsKind {
147 ArgsKind::Ubo
148 }
149}
150
151impl UniformArgs for GL::ShdArrBind<'_, ShdStorage> {
152 fn apply(&self, _: i32, _: UniCache) {
153 unreachable!()
154 }
155 fn kind(&self) -> ArgsKind {
156 ArgsKind::Ssbo
157 }
158}
159
160pub mod uniforms_use {
161 pub const fn id(s: &str) -> (u32, &str) {
162 (super::chksum::const_fnv1(s.as_bytes()), s)
163 }
164}
165
166pub type UniCache<'a> = &'a mut Option<CachedUni>;
167
168#[derive(Debug)]
169pub enum CachedUni {
170 u32(u32),
171 uVec2(uVec2),
172 uVec3(uVec3),
173 uVec4(uVec4),
174 i32(i32),
175 iVec2(iVec2),
176 iVec3(iVec3),
177 iVec4(iVec4),
178 f32(f32),
179 Vec2(Vec2),
180 Vec3(Vec3),
181 Vec4(Vec4),
182 Mat2(Mat2),
183 Mat3(Mat3),
184 Mat4(Mat4),
185 Mat2x3(Mat2x3),
186 Mat3x2(Mat3x2),
187 Mat2x4(Mat2x4),
188 Mat4x2(Mat4x2),
189 Mat3x4(Mat3x4),
190 Mat4x3(Mat4x3),
191 TexUnit(i32),
192 UboLoc(i32),
193}