luminance_gl/gl33/
shader.rs

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    // ensure the location smells good
102    if location < 0 {
103      return Err(UniformWarning::inactive(name));
104    }
105
106    // ensure the type is correct regarding what we have in the type-system
107    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    // ensure the location smells good
122    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    // get the max length of the returned names
283    let mut max_len = 0;
284    gl::GetProgramiv(program, gl::ACTIVE_UNIFORM_MAX_LENGTH, &mut max_len);
285
286    // get the index of the uniform
287    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    // get its size and type
298    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  // helper macro to check type mismatch for each variant
325  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    // scalars
346    (Int, INT),
347    (UInt, UNSIGNED_INT),
348    (Float, FLOAT),
349    (Double, DOUBLE),
350    (Bool, BOOL),
351    // vectors
352    (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    // matrices
368    (M22, FLOAT_MAT2),
369    (M33, FLOAT_MAT3),
370    (M44, FLOAT_MAT4),
371    (DM22, DOUBLE_MAT2),
372    (DM33, DOUBLE_MAT3),
373    (DM44, DOUBLE_MAT4),
374    // textures
375    (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        // we are not interested in the location as we’re about to change it to what we’ve
408        // decided in the semantics
409        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  // matrix notation
486  (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
657// a cache for implementors needing to switch from [bool; N] to [u32; N]
658static 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}