1use super::buffer::Buffer;
2use crate::gl33::GL33;
3use gl::{self, types::*};
4use luminance::{
5 backend::shader::{Shader, ShaderData, Uniformable},
6 pipeline::{ShaderDataBinding, TextureBinding},
7 pixel::{SamplerType, Type as PixelType},
8 shader::{
9 types::{Arr, Mat22, Mat33, Mat44, Vec2, Vec3, Vec4},
10 ProgramError, ShaderDataError, StageError, StageType, TessellationStages, Uniform, UniformType,
11 UniformWarning, VertexAttribWarning,
12 },
13 texture::{Dim, Dimensionable},
14 vertex::Semantics,
15};
16use luminance_std140::{ArrElem, Std140};
17use std::{
18 ffi::CString,
19 mem,
20 ptr::{null, null_mut},
21};
22
23#[derive(Debug)]
24pub struct Stage {
25 handle: GLuint,
26}
27
28impl Drop for Stage {
29 fn drop(&mut self) {
30 unsafe {
31 gl::DeleteShader(self.handle);
32 }
33 }
34}
35
36#[derive(Debug)]
37pub struct Program {
38 pub(crate) handle: GLuint,
39}
40
41impl Drop for Program {
42 fn drop(&mut self) {
43 unsafe {
44 gl::DeleteProgram(self.handle);
45 }
46 }
47}
48
49impl Program {
50 fn link(&self) -> Result<(), ProgramError> {
51 let handle = self.handle;
52
53 unsafe {
54 gl::LinkProgram(handle);
55
56 let mut linked: GLint = gl::FALSE.into();
57 gl::GetProgramiv(handle, gl::LINK_STATUS, &mut linked);
58
59 if linked == gl::TRUE.into() {
60 Ok(())
61 } else {
62 let mut log_len: GLint = 0;
63 gl::GetProgramiv(handle, gl::INFO_LOG_LENGTH, &mut log_len);
64
65 let mut log: Vec<u8> = Vec::with_capacity(log_len as usize);
66 gl::GetProgramInfoLog(handle, log_len, null_mut(), log.as_mut_ptr() as *mut GLchar);
67
68 log.set_len(log_len as usize);
69
70 Err(ProgramError::link_failed(String::from_utf8(log).unwrap()))
71 }
72 }
73 }
74}
75
76pub struct UniformBuilder {
77 handle: GLuint,
78}
79
80impl UniformBuilder {
81 fn new(program: &Program) -> Self {
82 UniformBuilder {
83 handle: program.handle,
84 }
85 }
86
87 fn ask_uniform<T>(
88 &self,
89 name: &str,
90 ty: UniformType,
91 size: usize,
92 ) -> Result<Uniform<T>, UniformWarning>
93 where
94 GL33: for<'u> Uniformable<'u, T>,
95 {
96 let location = {
97 let c_name = CString::new(name.as_bytes()).unwrap();
98 unsafe { gl::GetUniformLocation(self.handle, c_name.as_ptr() as *const GLchar) }
99 };
100
101 if location < 0 {
103 return Err(UniformWarning::inactive(name));
104 }
105
106 uniform_type_match(self.handle, name, ty, size)?;
108
109 Ok(unsafe { Uniform::new(location) })
110 }
111
112 fn ask_uniform_block<T>(&self, name: &str) -> Result<Uniform<T>, UniformWarning>
113 where
114 GL33: for<'u> Uniformable<'u, T>,
115 {
116 let location = {
117 let c_name = CString::new(name.as_bytes()).unwrap();
118 unsafe { gl::GetUniformBlockIndex(self.handle, c_name.as_ptr() as *const GLchar) }
119 };
120
121 if location == gl::INVALID_INDEX {
123 return Err(UniformWarning::inactive(name));
124 }
125
126 Ok(unsafe { Uniform::new(location as _) })
127 }
128}
129
130unsafe impl Shader for GL33 {
131 type StageRepr = Stage;
132
133 type ProgramRepr = Program;
134
135 type UniformBuilderRepr = UniformBuilder;
136
137 unsafe fn new_stage(&mut self, ty: StageType, src: &str) -> Result<Self::StageRepr, StageError> {
138 let handle = gl::CreateShader(opengl_shader_type(ty));
139
140 if handle == 0 {
141 return Err(StageError::compilation_failed(
142 ty,
143 "unable to create shader stage",
144 ));
145 }
146
147 let c_src = CString::new(glsl_pragma_src(src).as_bytes()).unwrap();
148 gl::ShaderSource(handle, 1, [c_src.as_ptr()].as_ptr(), null());
149 gl::CompileShader(handle);
150
151 let mut compiled: GLint = gl::FALSE.into();
152 gl::GetShaderiv(handle, gl::COMPILE_STATUS, &mut compiled);
153
154 if compiled == gl::TRUE.into() {
155 Ok(Stage { handle })
156 } else {
157 let mut log_len: GLint = 0;
158 gl::GetShaderiv(handle, gl::INFO_LOG_LENGTH, &mut log_len);
159
160 let mut log: Vec<u8> = Vec::with_capacity(log_len as usize);
161 gl::GetShaderInfoLog(handle, log_len, null_mut(), log.as_mut_ptr() as *mut GLchar);
162
163 gl::DeleteShader(handle);
164
165 log.set_len(log_len as usize);
166
167 Err(StageError::compilation_failed(
168 ty,
169 String::from_utf8(log).unwrap(),
170 ))
171 }
172 }
173
174 unsafe fn new_program(
175 &mut self,
176 vertex: &Self::StageRepr,
177 tess: Option<TessellationStages<Self::StageRepr>>,
178 geometry: Option<&Self::StageRepr>,
179 fragment: &Self::StageRepr,
180 ) -> Result<Self::ProgramRepr, ProgramError> {
181 let handle = gl::CreateProgram();
182
183 if let Some(TessellationStages {
184 control,
185 evaluation,
186 }) = tess
187 {
188 gl::AttachShader(handle, control.handle);
189 gl::AttachShader(handle, evaluation.handle);
190 }
191
192 gl::AttachShader(handle, vertex.handle);
193
194 if let Some(geometry) = geometry {
195 gl::AttachShader(handle, geometry.handle);
196 }
197
198 gl::AttachShader(handle, fragment.handle);
199
200 let program = Program { handle };
201 program.link().map(move |_| program)
202 }
203
204 unsafe fn apply_semantics<Sem>(
205 program: &mut Self::ProgramRepr,
206 ) -> Result<Vec<VertexAttribWarning>, ProgramError>
207 where
208 Sem: Semantics,
209 {
210 let warnings = bind_vertex_attribs_locations::<Sem>(program);
211
212 program.link()?;
213
214 Ok(warnings)
215 }
216
217 unsafe fn new_uniform_builder(
218 program: &mut Self::ProgramRepr,
219 ) -> Result<Self::UniformBuilderRepr, ProgramError> {
220 Ok(UniformBuilder::new(&program))
221 }
222
223 unsafe fn ask_uniform<T>(
224 uniform_builder: &mut Self::UniformBuilderRepr,
225 name: &str,
226 ) -> Result<Uniform<T>, UniformWarning>
227 where
228 Self: for<'u> Uniformable<'u, T>,
229 {
230 let uniform = match Self::ty() {
231 UniformType::ShaderDataBinding => uniform_builder.ask_uniform_block(name)?,
232 _ => uniform_builder.ask_uniform(name, Self::ty(), Self::SIZE)?,
233 };
234
235 Ok(uniform)
236 }
237
238 unsafe fn unbound<T>(_: &mut Self::UniformBuilderRepr) -> Uniform<T>
239 where
240 Self: for<'u> Uniformable<'u, T>,
241 {
242 Uniform::new(-1)
243 }
244}
245
246fn opengl_shader_type(t: StageType) -> GLenum {
247 match t {
248 StageType::TessellationControlShader => gl::TESS_CONTROL_SHADER,
249 StageType::TessellationEvaluationShader => gl::TESS_EVALUATION_SHADER,
250 StageType::VertexShader => gl::VERTEX_SHADER,
251 StageType::GeometryShader => gl::GEOMETRY_SHADER,
252 StageType::FragmentShader => gl::FRAGMENT_SHADER,
253 }
254}
255
256#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
257const GLSL_PRAGMA: &str = "#version 330 core\n\
258 #extension GL_ARB_separate_shader_objects : require\n
259 #extension GL_ARB_gpu_shader_fp64 : require\n\
260 layout(std140) uniform;\n";
261#[cfg(not(feature = "GL_ARB_gpu_shader_fp64"))]
262const GLSL_PRAGMA: &str = "#version 330 core\n\
263 #extension GL_ARB_separate_shader_objects : require\n\
264 layout(std140) uniform;\n";
265
266fn glsl_pragma_src(src: &str) -> String {
267 let mut pragma = String::from(GLSL_PRAGMA);
268 pragma.push_str(src);
269 pragma
270}
271
272fn uniform_type_match(
273 program: GLuint,
274 name: &str,
275 ty: UniformType,
276 size: usize,
277) -> Result<(), UniformWarning> {
278 let mut glty: GLuint = 0;
279 let mut found_size: GLint = 0;
280
281 unsafe {
282 let mut max_len = 0;
284 gl::GetProgramiv(program, gl::ACTIVE_UNIFORM_MAX_LENGTH, &mut max_len);
285
286 let mut index = 0;
288
289 let c_name = CString::new(name.as_bytes()).unwrap();
290 gl::GetUniformIndices(
291 program,
292 1,
293 [c_name.as_ptr() as *const GLchar].as_ptr(),
294 &mut index,
295 );
296
297 let mut name_ = Vec::<GLchar>::with_capacity(max_len as usize);
299 gl::GetActiveUniform(
300 program,
301 index,
302 max_len,
303 null_mut(),
304 &mut found_size,
305 &mut glty,
306 name_.as_mut_ptr(),
307 );
308 }
309
310 let found_size = found_size as usize;
311 if size > 0 && found_size != size {
312 return Err(UniformWarning::size_mismatch(name, size, found_size));
313 }
314
315 check_uniform_type_match(name, ty, glty)
316}
317
318#[allow(clippy::cognitive_complexity)]
319fn check_uniform_type_match(
320 name: &str,
321 ty: UniformType,
322 glty: GLuint,
323) -> Result<(), UniformWarning> {
324 macro_rules! milkcheck {
326 ($ty:expr, $( ( $v:tt, $t:tt ) ),* $(,)?) => {
327 match $ty {
328 $(
329 UniformType::$v => {
330 if glty == gl::$t {
331 Ok(())
332 } else {
333 Err(UniformWarning::type_mismatch(name, ty))
334 }
335 }
336 )*
337
338 _ => Err(UniformWarning::unsupported_type(name, ty))
339 }
340 }
341 }
342
343 milkcheck!(
344 ty,
345 (Int, INT),
347 (UInt, UNSIGNED_INT),
348 (Float, FLOAT),
349 (Double, DOUBLE),
350 (Bool, BOOL),
351 (IVec2, INT_VEC2),
353 (IVec3, INT_VEC3),
354 (IVec4, INT_VEC4),
355 (UIVec2, UNSIGNED_INT_VEC2),
356 (UIVec3, UNSIGNED_INT_VEC3),
357 (UIVec4, UNSIGNED_INT_VEC4),
358 (Vec2, FLOAT_VEC2),
359 (Vec3, FLOAT_VEC3),
360 (Vec4, FLOAT_VEC4),
361 (DVec2, DOUBLE_VEC2),
362 (DVec3, DOUBLE_VEC3),
363 (DVec4, DOUBLE_VEC4),
364 (BVec2, BOOL_VEC2),
365 (BVec3, BOOL_VEC3),
366 (BVec4, BOOL_VEC4),
367 (M22, FLOAT_MAT2),
369 (M33, FLOAT_MAT3),
370 (M44, FLOAT_MAT4),
371 (DM22, DOUBLE_MAT2),
372 (DM33, DOUBLE_MAT3),
373 (DM44, DOUBLE_MAT4),
374 (ISampler1D, INT_SAMPLER_1D),
376 (ISampler2D, INT_SAMPLER_2D),
377 (ISampler3D, INT_SAMPLER_3D),
378 (ISampler1DArray, INT_SAMPLER_1D_ARRAY),
379 (ISampler2DArray, INT_SAMPLER_2D_ARRAY),
380 (UISampler1D, UNSIGNED_INT_SAMPLER_1D),
381 (UISampler2D, UNSIGNED_INT_SAMPLER_2D),
382 (UISampler3D, UNSIGNED_INT_SAMPLER_3D),
383 (UISampler1DArray, UNSIGNED_INT_SAMPLER_1D_ARRAY),
384 (UISampler2DArray, UNSIGNED_INT_SAMPLER_2D_ARRAY),
385 (Sampler1D, SAMPLER_1D),
386 (Sampler2D, SAMPLER_2D),
387 (Sampler3D, SAMPLER_3D),
388 (Sampler1DArray, SAMPLER_1D_ARRAY),
389 (Sampler2DArray, SAMPLER_2D_ARRAY),
390 (ICubemap, INT_SAMPLER_CUBE),
391 (UICubemap, UNSIGNED_INT_SAMPLER_CUBE),
392 (Cubemap, SAMPLER_CUBE),
393 )
394}
395
396fn bind_vertex_attribs_locations<Sem>(program: &Program) -> Vec<VertexAttribWarning>
397where
398 Sem: Semantics,
399{
400 let mut warnings = Vec::new();
401
402 for desc in Sem::semantics_set() {
403 match get_vertex_attrib_location(program, &desc.name) {
404 Ok(_) => {
405 let index = desc.index as GLuint;
406
407 let c_name = CString::new(desc.name.as_bytes()).unwrap();
410 unsafe { gl::BindAttribLocation(program.handle, index, c_name.as_ptr() as *const GLchar) };
411 }
412
413 Err(warning) => warnings.push(warning),
414 }
415 }
416
417 warnings
418}
419
420fn get_vertex_attrib_location(
421 program: &Program,
422 name: &str,
423) -> Result<GLuint, VertexAttribWarning> {
424 let location = {
425 let c_name = CString::new(name.as_bytes()).unwrap();
426 unsafe { gl::GetAttribLocation(program.handle, c_name.as_ptr() as *const GLchar) }
427 };
428
429 if location < 0 {
430 Err(VertexAttribWarning::inactive(name))
431 } else {
432 Ok(location as _)
433 }
434}
435
436macro_rules! impl_Uniformable {
437 (Arr<$t:ty>, $uty:tt, $f:tt) => {
438 unsafe impl<'a, const N: usize> Uniformable<'a, Arr<$t, N>> for GL33 {
439 type Target = &'a [$t; N];
440
441 const SIZE: usize = N;
442
443 unsafe fn ty() -> UniformType {
444 UniformType::$uty
445 }
446
447 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Arr<$t, N>>, value: Self::Target) {
448 gl::$f(uniform.index(), N as GLsizei, value.as_ptr() as _);
449 }
450 }
451 };
452
453 (vec $t:ty, $uty:tt, $f:tt) => {
454 unsafe impl<'a> Uniformable<'a, $t> for GL33 {
455 type Target = $t;
456
457 const SIZE: usize = 1;
458
459 unsafe fn ty() -> UniformType {
460 UniformType::$uty
461 }
462
463 unsafe fn update(_: &mut Program, uniform: &'a Uniform<$t>, value: Self::Target) {
464 gl::$f(uniform.index(), 1, value.as_ptr());
465 }
466 }
467 };
468
469 ($t:ty, $uty:tt, $f:tt) => {
470 unsafe impl<'a> Uniformable<'a, $t> for GL33 {
471 type Target = $t;
472
473 const SIZE: usize = 1;
474
475 unsafe fn ty() -> UniformType {
476 UniformType::$uty
477 }
478
479 unsafe fn update(_: &mut Program, uniform: &'a Uniform<$t>, value: Self::Target) {
480 gl::$f(uniform.index(), value);
481 }
482 }
483 };
484
485 (mat Arr<$t:ty>, $uty:tt, $f:tt) => {
487 unsafe impl<'a, const N: usize> Uniformable<'a, Arr<$t, N>> for GL33 {
488 type Target = &'a [$t; N];
489
490 const SIZE: usize = N;
491
492 unsafe fn ty() -> UniformType {
493 UniformType::$uty
494 }
495
496 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Arr<$t, N>>, value: Self::Target) {
497 gl::$f(
498 uniform.index(),
499 N as GLsizei,
500 gl::FALSE,
501 value.as_ptr() as _,
502 );
503 }
504 }
505 };
506
507 (mat $t:ty, $uty:tt, $f:tt) => {
508 unsafe impl<'a> Uniformable<'a, $t> for GL33 {
509 type Target = $t;
510
511 const SIZE: usize = 1;
512
513 unsafe fn ty() -> UniformType {
514 UniformType::$uty
515 }
516
517 unsafe fn update(_: &mut Program, uniform: &'a Uniform<$t>, value: Self::Target) {
518 gl::$f(uniform.index(), 1, gl::FALSE, value.as_ptr() as _);
519 }
520 }
521 };
522}
523
524impl_Uniformable!(i32, Int, Uniform1i);
525impl_Uniformable!(vec Vec2<i32>, IVec2, Uniform2iv);
526impl_Uniformable!(vec Vec3<i32>, IVec3, Uniform3iv);
527impl_Uniformable!(vec Vec4<i32>, IVec4, Uniform4iv);
528
529impl_Uniformable!(Arr<i32>, Int, Uniform1iv);
530impl_Uniformable!(Arr<Vec2<i32>>, IVec2, Uniform2iv);
531impl_Uniformable!(Arr<Vec3<i32>>, IVec3, Uniform3iv);
532impl_Uniformable!(Arr<Vec4<i32>>, IVec4, Uniform4iv);
533
534impl_Uniformable!(u32, UInt, Uniform1ui);
535impl_Uniformable!(vec Vec2<u32>, UIVec2, Uniform2uiv);
536impl_Uniformable!(vec Vec3<u32>, UIVec3, Uniform3uiv);
537impl_Uniformable!(vec Vec4<u32>, UIVec4, Uniform4uiv);
538impl_Uniformable!(Arr<u32>, UInt, Uniform1uiv);
539impl_Uniformable!(Arr<Vec2<u32>>, UIVec2, Uniform2uiv);
540impl_Uniformable!(Arr<Vec3<u32>>, UIVec3, Uniform3uiv);
541impl_Uniformable!(Arr<Vec4<u32>>, UIVec4, Uniform4uiv);
542
543impl_Uniformable!(f32, Float, Uniform1f);
544impl_Uniformable!(vec Vec2<f32>, Vec2, Uniform2fv);
545impl_Uniformable!(vec Vec3<f32>, Vec3, Uniform3fv);
546impl_Uniformable!(vec Vec4<f32>, Vec4, Uniform4fv);
547impl_Uniformable!(Arr<f32>, Float, Uniform1fv);
548impl_Uniformable!(Arr<Vec2<f32>>, Vec2, Uniform2fv);
549impl_Uniformable!(Arr<Vec3<f32>>, Vec3, Uniform3fv);
550impl_Uniformable!(Arr<Vec4<f32>>, Vec4, Uniform4fv);
551
552#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
553impl_Uniformable!(f64, Double, Uniform1d);
554#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
555impl_Uniformable!(vec Vec2<f64>, DVec2, Uniform2dv);
556#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
557impl_Uniformable!(vec Vec3<f64>, DVec3, Uniform3dv);
558#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
559impl_Uniformable!(vec Vec4<f64>, DVec4, Uniform4dv);
560#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
561impl_Uniformable!(Arr<f64>, Double, Uniform1dv);
562#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
563impl_Uniformable!(Arr<Vec2<f64>>, DVec2, Uniform2dv);
564#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
565impl_Uniformable!(Arr<Vec3<f64>>, DVec3, Uniform3dv);
566#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
567impl_Uniformable!(Arr<Vec4<f64>>, DVec4, Uniform4dv);
568
569impl_Uniformable!(mat Mat22<f32>, M22, UniformMatrix2fv);
570impl_Uniformable!(mat Arr<Mat22<f32>>, M22, UniformMatrix2fv);
571
572impl_Uniformable!(mat Mat33<f32>, M33, UniformMatrix3fv);
573impl_Uniformable!(mat Arr<Mat33<f32>>, M33, UniformMatrix3fv);
574
575impl_Uniformable!(mat Mat44<f32>, M44, UniformMatrix4fv);
576impl_Uniformable!(mat Arr<Mat44<f32>>, M44, UniformMatrix4fv);
577
578#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
579impl_Uniformable!(mat Mat22<f64>, DM22, UniformMatrix2dv);
580#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
581impl_Uniformable!(mat Arr<Mat22<f64>>, DM22, UniformMatrix2dv);
582
583#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
584impl_Uniformable!(mat Mat33<f64>, DM33, UniformMatrix3dv);
585#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
586impl_Uniformable!(mat Arr<Mat33<f64>>, DM33, UniformMatrix3dv);
587
588#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
589impl_Uniformable!(mat Mat44<f64>, DM44, UniformMatrix4dv);
590#[cfg(feature = "GL_ARB_gpu_shader_fp64")]
591impl_Uniformable!(mat Arr<Mat44<f64>>, DM44, UniformMatrix4dv);
592
593unsafe impl<'a> Uniformable<'a, bool> for GL33 {
594 type Target = bool;
595
596 const SIZE: usize = 1;
597
598 unsafe fn ty() -> UniformType {
599 UniformType::Bool
600 }
601
602 unsafe fn update(_: &mut Program, uniform: &'a Uniform<bool>, value: Self::Target) {
603 gl::Uniform1ui(uniform.index(), value as u32);
604 }
605}
606
607unsafe impl<'a> Uniformable<'a, Vec2<bool>> for GL33 {
608 type Target = Vec2<bool>;
609
610 const SIZE: usize = 1;
611
612 unsafe fn ty() -> UniformType {
613 UniformType::BVec2
614 }
615
616 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Vec2<bool>>, value: Self::Target) {
617 let v = [value[0] as u32, value[1] as u32];
618 gl::Uniform2uiv(uniform.index(), 1, v.as_ptr() as _);
619 }
620}
621
622unsafe impl<'a> Uniformable<'a, Vec3<bool>> for GL33 {
623 type Target = Vec3<bool>;
624
625 const SIZE: usize = 1;
626
627 unsafe fn ty() -> UniformType {
628 UniformType::BVec3
629 }
630
631 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Vec3<bool>>, value: Self::Target) {
632 let v = [value[0] as u32, value[1] as u32, value[2] as u32];
633 gl::Uniform3uiv(uniform.index(), 1, v.as_ptr() as _);
634 }
635}
636
637unsafe impl<'a> Uniformable<'a, Vec4<bool>> for GL33 {
638 type Target = Vec4<bool>;
639
640 const SIZE: usize = 1;
641
642 unsafe fn ty() -> UniformType {
643 UniformType::BVec4
644 }
645
646 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Vec4<bool>>, value: Self::Target) {
647 let v = [
648 value[0] as u32,
649 value[1] as u32,
650 value[2] as u32,
651 value[3] as u32,
652 ];
653 gl::Uniform4uiv(uniform.index(), 1, v.as_ptr() as _);
654 }
655}
656
657static mut BOOL_CACHE: Vec<u32> = Vec::new();
659
660unsafe impl<'a, const N: usize> Uniformable<'a, Arr<bool, N>> for GL33 {
661 type Target = &'a [bool; N];
662
663 const SIZE: usize = N;
664
665 unsafe fn ty() -> UniformType {
666 UniformType::Bool
667 }
668
669 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Arr<bool, N>>, value: Self::Target) {
670 BOOL_CACHE.clear();
671 BOOL_CACHE.extend(value.iter().map(|x| *x as u32));
672
673 gl::Uniform1uiv(uniform.index(), N as GLsizei, BOOL_CACHE.as_ptr() as _);
674 }
675}
676
677unsafe impl<'a, const N: usize> Uniformable<'a, Arr<Vec2<bool>, N>> for GL33 {
678 type Target = &'a [Vec2<bool>; N];
679
680 const SIZE: usize = N;
681
682 unsafe fn ty() -> UniformType {
683 UniformType::BVec2
684 }
685
686 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Arr<Vec2<bool>, N>>, value: Self::Target) {
687 BOOL_CACHE.clear();
688 BOOL_CACHE.extend(value.iter().flat_map(|x| [x[0] as u32, x[1] as u32]));
689
690 gl::Uniform2uiv(uniform.index(), N as GLsizei, BOOL_CACHE.as_ptr() as _);
691 }
692}
693
694unsafe impl<'a, const N: usize> Uniformable<'a, Arr<Vec3<bool>, N>> for GL33 {
695 type Target = &'a [Vec3<bool>; N];
696
697 const SIZE: usize = N;
698
699 unsafe fn ty() -> UniformType {
700 UniformType::BVec3
701 }
702
703 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Arr<Vec3<bool>, N>>, value: Self::Target) {
704 BOOL_CACHE.clear();
705 BOOL_CACHE.extend(
706 value
707 .iter()
708 .flat_map(|x| [x[0] as u32, x[1] as u32, x[2] as u32]),
709 );
710
711 gl::Uniform3uiv(uniform.index(), N as GLsizei, BOOL_CACHE.as_ptr() as _);
712 }
713}
714
715unsafe impl<'a, const N: usize> Uniformable<'a, Arr<Vec4<bool>, N>> for GL33 {
716 type Target = &'a [Vec4<bool>; N];
717
718 const SIZE: usize = N;
719
720 unsafe fn ty() -> UniformType {
721 UniformType::BVec4
722 }
723
724 unsafe fn update(_: &mut Program, uniform: &'a Uniform<Arr<Vec4<bool>, N>>, value: Self::Target) {
725 BOOL_CACHE.clear();
726 BOOL_CACHE.extend(
727 value
728 .iter()
729 .flat_map(|x| [x[0] as u32, x[1] as u32, x[2] as u32, x[3] as u32]),
730 );
731
732 gl::Uniform4uiv(uniform.index(), N as GLsizei, BOOL_CACHE.as_ptr() as _);
733 }
734}
735
736unsafe impl<'a, T> Uniformable<'a, ShaderDataBinding<T>> for GL33
737where
738 T: 'a,
739{
740 type Target = ShaderDataBinding<T>;
741
742 const SIZE: usize = 0;
743
744 unsafe fn ty() -> UniformType {
745 UniformType::ShaderDataBinding
746 }
747
748 unsafe fn update(
749 program: &mut Program,
750 uniform: &'a Uniform<ShaderDataBinding<T>>,
751 value: Self::Target,
752 ) {
753 gl::UniformBlockBinding(
754 program.handle,
755 uniform.index() as GLuint,
756 value.binding() as GLuint,
757 )
758 }
759}
760
761unsafe impl<'a, D, S> Uniformable<'a, TextureBinding<D, S>> for GL33
762where
763 D: 'a + Dimensionable,
764 S: 'a + SamplerType,
765{
766 type Target = TextureBinding<D, S>;
767
768 const SIZE: usize = 0;
769
770 unsafe fn ty() -> UniformType {
771 match (S::sample_type(), D::dim()) {
772 (PixelType::NormIntegral, Dim::Dim1) => UniformType::Sampler1D,
773 (PixelType::NormUnsigned, Dim::Dim1) => UniformType::Sampler1D,
774 (PixelType::Integral, Dim::Dim1) => UniformType::ISampler1D,
775 (PixelType::Unsigned, Dim::Dim1) => UniformType::UISampler1D,
776 (PixelType::Floating, Dim::Dim1) => UniformType::Sampler1D,
777
778 (PixelType::NormIntegral, Dim::Dim2) => UniformType::Sampler2D,
779 (PixelType::NormUnsigned, Dim::Dim2) => UniformType::Sampler2D,
780 (PixelType::Integral, Dim::Dim2) => UniformType::ISampler2D,
781 (PixelType::Unsigned, Dim::Dim2) => UniformType::UISampler2D,
782 (PixelType::Floating, Dim::Dim2) => UniformType::Sampler2D,
783
784 (PixelType::NormIntegral, Dim::Dim3) => UniformType::Sampler3D,
785 (PixelType::NormUnsigned, Dim::Dim3) => UniformType::Sampler3D,
786 (PixelType::Integral, Dim::Dim3) => UniformType::ISampler3D,
787 (PixelType::Unsigned, Dim::Dim3) => UniformType::UISampler3D,
788 (PixelType::Floating, Dim::Dim3) => UniformType::Sampler3D,
789
790 (PixelType::NormIntegral, Dim::Cubemap) => UniformType::Cubemap,
791 (PixelType::NormUnsigned, Dim::Cubemap) => UniformType::Cubemap,
792 (PixelType::Integral, Dim::Cubemap) => UniformType::ICubemap,
793 (PixelType::Unsigned, Dim::Cubemap) => UniformType::UICubemap,
794 (PixelType::Floating, Dim::Cubemap) => UniformType::Cubemap,
795
796 (PixelType::NormIntegral, Dim::Dim1Array) => UniformType::Sampler1DArray,
797 (PixelType::NormUnsigned, Dim::Dim1Array) => UniformType::Sampler1DArray,
798 (PixelType::Integral, Dim::Dim1Array) => UniformType::ISampler1DArray,
799 (PixelType::Unsigned, Dim::Dim1Array) => UniformType::UISampler1DArray,
800 (PixelType::Floating, Dim::Dim1Array) => UniformType::Sampler1DArray,
801
802 (PixelType::NormIntegral, Dim::Dim2Array) => UniformType::Sampler2DArray,
803 (PixelType::NormUnsigned, Dim::Dim2Array) => UniformType::Sampler2DArray,
804 (PixelType::Integral, Dim::Dim2Array) => UniformType::ISampler2DArray,
805 (PixelType::Unsigned, Dim::Dim2Array) => UniformType::UISampler2DArray,
806 (PixelType::Floating, Dim::Dim2Array) => UniformType::Sampler2DArray,
807 }
808 }
809
810 unsafe fn update(
811 _: &mut Program,
812 uniform: &'a Uniform<TextureBinding<D, S>>,
813 value: Self::Target,
814 ) {
815 gl::Uniform1i(uniform.index(), value.binding() as GLint)
816 }
817}
818
819unsafe impl<T> ShaderData<T> for GL33
820where
821 T: Std140,
822{
823 type ShaderDataRepr = Buffer<<ArrElem<T> as Std140>::Encoded>;
824
825 unsafe fn new_shader_data(
826 &mut self,
827 values: impl Iterator<Item = T>,
828 ) -> Result<Self::ShaderDataRepr, ShaderDataError> {
829 Ok(Buffer::from_vec(
830 self,
831 values
832 .into_iter()
833 .map(|x| ArrElem(x).std140_encode())
834 .collect(),
835 ))
836 }
837
838 unsafe fn get_shader_data_at(
839 shader_data: &Self::ShaderDataRepr,
840 i: usize,
841 ) -> Result<T, ShaderDataError> {
842 shader_data
843 .buf
844 .get(i)
845 .map(|&x| <ArrElem<T> as Std140>::std140_decode(x).0)
846 .ok_or_else(|| ShaderDataError::OutOfBounds { index: i })
847 }
848
849 unsafe fn set_shader_data_at(
850 shader_data: &mut Self::ShaderDataRepr,
851 i: usize,
852 x: T,
853 ) -> Result<T, ShaderDataError> {
854 let prev = mem::replace(
855 &mut shader_data
856 .slice_buffer_mut()
857 .map_err(|_| ShaderDataError::CannotSetData { index: i })?[i],
858 ArrElem(x).std140_encode(),
859 );
860
861 Ok(<ArrElem<T> as Std140>::std140_decode(prev).0)
862 }
863
864 unsafe fn set_shader_data_values(
865 shader_data: &mut Self::ShaderDataRepr,
866 values: impl Iterator<Item = T>,
867 ) -> Result<(), ShaderDataError> {
868 let mut slice = shader_data
869 .slice_buffer_mut()
870 .map_err(|_| ShaderDataError::CannotReplaceData)?;
871
872 for (item, value) in slice.iter_mut().zip(values) {
873 *item = ArrElem(value).std140_encode();
874 }
875
876 Ok(())
877 }
878}