globject_rs/
glshader.rs

1
2#![allow(non_upper_case_globals)]
3
4use crate::prelude::*;
5use std::{
6	collections::BTreeMap,
7	ffi::CString,
8	fmt::{self, Debug, Display, Formatter},
9	mem::{transmute, size_of},
10	path::Path,
11	ptr::null_mut,
12	rc::Rc,
13	string::FromUtf8Error,
14};
15use bincode::{Encode, Decode};
16
17/// Error produced from the shader
18#[derive(Clone)]
19pub enum ShaderError {
20	/// Vertex Shader error
21	VSError(String),
22
23	/// Geometry Shader error
24	GSError(String),
25
26	/// Fragment Shader error
27	FSError(String),
28	
29	/// Compute Shader error
30	CSError(String),
31
32	/// Shader program linkage error
33	LinkageError(String),
34}
35
36/// Error produced from the shader
37#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq)]
38pub enum ShaderType {
39	Draw,
40	Compute,
41}
42
43/// The OpenGL shader object
44pub struct Shader {
45	glcore: Rc<GLCore>,
46	program: u32,
47	shader_type: ShaderType,
48}
49
50/// The struct for monitoring using the shader
51#[derive(Debug)]
52pub struct ShaderUse<'a> {
53	pub shader: &'a Shader,
54}
55
56/// The pre-compiled OpenGL shader binary
57#[derive(Encode, Decode, Debug, Clone)]
58pub struct ShaderBinary {
59	format: u32,
60	shader_type: ShaderType,
61	binary: Vec<u8>,
62}
63
64/// The error info of loading the shader binary
65#[derive(Debug)]
66pub enum ShaderBinaryLoadError {
67	IOError(std::io::Error),
68	DecodeError(bincode::error::DecodeError),
69}
70
71/// The error info of storing the shader binary
72#[derive(Debug)]
73pub enum ShaderBinarySaveError {
74	IOError(std::io::Error),
75	EncodeError(bincode::error::EncodeError),
76}
77
78/// The OpenGL attrib types
79#[derive(Clone, Copy)]
80pub enum ShaderInputType {
81	Float = GL_FLOAT as isize,
82	Vec2 = GL_FLOAT_VEC2 as isize,
83	Vec3 = GL_FLOAT_VEC3 as isize,
84	Vec4 = GL_FLOAT_VEC4 as isize,
85	Mat2 = GL_FLOAT_MAT2 as isize,
86	Mat3 = GL_FLOAT_MAT3 as isize,
87	Mat4 = GL_FLOAT_MAT4 as isize,
88	Mat2x3 = GL_FLOAT_MAT2x3 as isize,
89	Mat2x4 = GL_FLOAT_MAT2x4 as isize,
90	Mat3x2 = GL_FLOAT_MAT3x2 as isize,
91	Mat3x4 = GL_FLOAT_MAT3x4 as isize,
92	Mat4x2 = GL_FLOAT_MAT4x2 as isize,
93	Mat4x3 = GL_FLOAT_MAT4x3 as isize,
94	Int = GL_INT as isize,
95	IVec2 = GL_INT_VEC2 as isize,
96	IVec3 = GL_INT_VEC3 as isize,
97	IVec4 = GL_INT_VEC4 as isize,
98	UInt = GL_UNSIGNED_INT as isize,
99	UVec2 = GL_UNSIGNED_INT_VEC2 as isize,
100	UVec3 = GL_UNSIGNED_INT_VEC3 as isize,
101	UVec4 = GL_UNSIGNED_INT_VEC4 as isize,
102	Double = GL_DOUBLE as isize,
103	DVec2 = GL_DOUBLE_VEC2 as isize,
104	DVec3 = GL_DOUBLE_VEC3 as isize,
105	DVec4 = GL_DOUBLE_VEC4 as isize,
106	DMat2 = GL_DOUBLE_MAT2 as isize,
107	DMat3 = GL_DOUBLE_MAT3 as isize,
108	DMat4 = GL_DOUBLE_MAT4 as isize,
109	DMat2x3 = GL_DOUBLE_MAT2x3 as isize,
110	DMat2x4 = GL_DOUBLE_MAT2x4 as isize,
111	DMat3x2 = GL_DOUBLE_MAT3x2 as isize,
112	DMat3x4 = GL_DOUBLE_MAT3x4 as isize,
113	DMat4x2 = GL_DOUBLE_MAT4x2 as isize,
114	DMat4x3 = GL_DOUBLE_MAT4x3 as isize,
115}
116
117/// The OpenGL attrib type with length
118#[derive(Debug, Clone, Copy)]
119pub struct ShaderInputVarType {
120	pub type_: ShaderInputType,
121	pub size: i32,
122}
123
124impl Shader {
125	/// Get the internal name
126	pub fn get_name(&self) -> u32 {
127		self.program
128	}
129
130	/// Compile a shader, returns the compiled shader object or the compiler info log
131	fn compile_shader(glcore: &GLCore, shader_type: u32, shader_source: &str) -> Result<u32, String> {
132		let shader = glcore.glCreateShader(shader_type);
133		let bytes: Vec<i8> = shader_source.bytes().map(|byte| -> i8 {byte as i8}).collect();
134		let ptr_to_bytes = bytes.as_ptr();
135		let length = bytes.len() as i32;
136		glcore.glShaderSource(shader, 1, &ptr_to_bytes as *const *const i8, &length as *const i32);
137		glcore.glCompileShader(shader);
138
139		let mut compiled: i32 = 0;
140		glcore.glGetShaderiv(shader, GL_COMPILE_STATUS, &mut compiled as *mut i32);
141		if compiled != 0 {
142			Ok(shader)
143		} else {
144			let mut output_len: i32 = 0;
145			glcore.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &mut output_len as *mut i32);
146			let mut output =  Vec::<u8>::new();
147			let mut output_len_ret: i32 = 0;
148			output.resize(output_len as usize, 0);
149			glcore.glGetShaderInfoLog(shader, output_len, &mut output_len_ret as *mut i32, output.as_mut_ptr() as *mut i8);
150			glcore.glDeleteShader(shader);
151			let output = String::from_utf8_lossy(&output).to_string();
152			Err(output)
153		}
154	}
155
156	/// Link a shader program, returns compiler/linker info log if linkage isn't successful.
157	fn link_program(glcore: &GLCore, program: u32) -> Result<(), ShaderError> {
158		glcore.glLinkProgram(program);
159		Self::get_linkage_status(glcore, program)
160	}
161
162	/// Get the program linkage status, returns compiler/linker info log if linkage isn't successful.
163	fn get_linkage_status(glcore: &GLCore, program: u32)  -> Result<(), ShaderError> {
164		let mut linked: i32 = 0;
165		glcore.glGetProgramiv(program, GL_LINK_STATUS, &mut linked as *mut i32);
166		if linked != 0 {
167			Ok(())
168		} else {
169			let mut output_len: i32 = 0;
170			glcore.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &mut output_len as *mut i32);
171			let mut output =  Vec::<u8>::new();
172			let mut output_len_ret: i32 = 0;
173			output.resize(output_len as usize, 0);
174			glcore.glGetProgramInfoLog(program, output_len, &mut output_len_ret as *mut i32, output.as_mut_ptr() as *mut i8);
175			glcore.glDeleteProgram(program);
176			let output = String::from_utf8_lossy(&output).to_string();
177			Err(ShaderError::LinkageError(output))
178		}
179	}
180
181	/// Create a new traditional renderer shader program
182	pub fn new(glcore: Rc<GLCore>, vertex_shader: Option<&str>, geometry_shader: Option<&str>, fragment_shader: Option<&str>) -> Result<Self, ShaderError> {
183		let program = glcore.glCreateProgram();
184		if let Some(vertex_shader) = vertex_shader {
185			match Self::compile_shader(glcore.as_ref(), GL_VERTEX_SHADER, vertex_shader) {
186				Ok(shader) => {
187					glcore.glAttachShader(program, shader);
188					glcore.glDeleteShader(shader);
189				}
190				Err(output) => return Err(ShaderError::VSError(output)),
191			};
192		}
193		if let Some(geometry_shader) = geometry_shader {
194			match Self::compile_shader(glcore.as_ref(), GL_GEOMETRY_SHADER, geometry_shader) {
195				Ok(shader) => {
196					glcore.glAttachShader(program, shader);
197					glcore.glDeleteShader(shader);
198				}
199				Err(output) => return Err(ShaderError::GSError(output)),
200			};
201		}
202		if let Some(fragment_shader) = fragment_shader {
203			match Self::compile_shader(glcore.as_ref(), GL_FRAGMENT_SHADER, fragment_shader) {
204				Ok(shader) => {
205					glcore.glAttachShader(program, shader);
206					glcore.glDeleteShader(shader);
207				}
208				Err(output) => return Err(ShaderError::FSError(output)),
209			};
210		}
211		Self::link_program(glcore.as_ref(), program)?;
212		Ok(Self {
213			glcore,
214			program,
215			shader_type: ShaderType::Draw,
216		})
217	}
218
219	/// Create a new compute shader program
220	pub fn new_compute(glcore: Rc<GLCore>, shader_source: &str) -> Result<Self, ShaderError> {
221		let program = glcore.glCreateProgram();
222		match Self::compile_shader(glcore.as_ref(), GL_COMPUTE_SHADER, shader_source) {
223			Ok(shader) => {
224				glcore.glAttachShader(program, shader);
225				glcore.glDeleteShader(shader);
226			}
227			Err(output) => return Err(ShaderError::CSError(output)),
228		};
229		Self::link_program(glcore.as_ref(), program)?;
230		Ok(Self {
231			glcore,
232			program,
233			shader_type: ShaderType::Compute,
234		})
235	}
236
237	/// Get all of the active attributes of the shader
238	pub fn get_active_attribs(&self) -> Result<BTreeMap<String, ShaderInputVarType>, FromUtf8Error> {
239		let mut num_attribs: i32 = 0;
240		let mut max_length: i32 = 0;
241		self.glcore.glGetProgramiv(self.program, GL_ACTIVE_ATTRIBUTES, &mut num_attribs as *mut _);
242		self.glcore.glGetProgramiv(self.program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut max_length as *mut _);
243
244		let mut ret = BTreeMap::<String, ShaderInputVarType>::new();
245		for i in 0..num_attribs {
246			let mut name = vec![0i8; max_length as usize];
247			let mut size: i32 = 0;
248			let mut type_: u32 = 0;
249			self.glcore.glGetActiveAttrib(self.program, i as u32, max_length, null_mut::<i32>(), &mut size as *mut _, &mut type_ as *mut _, name.as_mut_ptr());
250			let name = String::from_utf8(unsafe{transmute::<Vec<i8>, Vec<u8>>(name)})?;
251			let name = name.trim_end_matches('\0').to_string();
252			let type_ = ShaderInputType::from(type_);
253			ret.insert(name, ShaderInputVarType{type_, size});
254		}
255		Ok(ret)
256	}
257
258	/// Get the location of the shader attrib
259	pub fn get_attrib_location(&self, attrib_name: &str) -> i32 {
260		let attrib_name = CString::new(attrib_name).unwrap();
261		self.glcore.glGetAttribLocation(self.program, attrib_name.as_ptr())
262	}
263
264	/// Get all of the active uniforms of the shader
265	pub fn get_active_uniforms(&self) -> Result<BTreeMap<String, ShaderInputVarType>, FromUtf8Error> {
266		let mut num_uniforms: i32 = 0;
267		let mut max_length: i32 = 0;
268		self.glcore.glGetProgramiv(self.program, GL_ACTIVE_UNIFORMS, &mut num_uniforms as *mut _);
269		self.glcore.glGetProgramiv(self.program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &mut max_length as *mut _);
270
271		let mut ret = BTreeMap::<String, ShaderInputVarType>::new();
272		for i in 0..num_uniforms {
273			let mut name = vec![0i8; max_length as usize];
274			let mut size: i32 = 0;
275			let mut type_: u32 = 0;
276			self.glcore.glGetActiveUniform(self.program, i as u32, max_length, null_mut::<i32>(), &mut size as *mut _, &mut type_ as *mut _, name.as_mut_ptr());
277			let name = String::from_utf8(unsafe{transmute::<Vec<i8>, Vec<u8>>(name)})?;
278			let name = name.trim_end_matches('\0').to_string();
279			let type_ = ShaderInputType::from(type_);
280			ret.insert(name, ShaderInputVarType{type_, size});
281		}
282		Ok(ret)
283	}
284
285	/// Get the location of the shader attrib
286	pub fn get_uniform_location(&self, uniform_name: &str) -> i32 {
287		let uniform_name = CString::new(uniform_name).unwrap();
288		self.glcore.glGetUniformLocation(self.program, uniform_name.as_ptr())
289	}
290
291	/// Get the compiled + linked program binary
292	pub fn get_program_binary(&self) -> ShaderBinary {
293		let mut binary_length = 0;
294		let mut binary_format = 0;
295		self.glcore.glGetProgramiv(self.program, GL_PROGRAM_BINARY_LENGTH, &mut binary_length as *mut _);
296		let mut binary = Vec::<u8>::new();
297		binary.resize(binary_length as usize, 0);
298		self.glcore.glGetProgramBinary(self.program, binary_length, null_mut(), &mut binary_format as *mut _, binary.as_mut_ptr() as *mut _);
299		ShaderBinary::new(binary_format, self.shader_type, binary)
300	}
301
302	/// Create a program from pre-compiled binary
303	pub fn from_program_binary(glcore: Rc<GLCore>, binary: &ShaderBinary) -> Result<Self, ShaderError> {
304		let program = glcore.glCreateProgram();
305		glcore.glProgramBinary(program, binary.format, binary.binary.as_ptr() as *const _, binary.binary.len() as i32);
306		match Self::get_linkage_status(&glcore, program) {
307			Ok(_) => Ok(Self {
308				glcore,
309				shader_type: binary.shader_type,
310				program,
311			}),
312			Err(e) => {
313				glcore.glDeleteProgram(program);
314				Err(e)
315			}
316		}
317	}
318
319	/// Set to use the shader
320	pub fn use_program<'a>(&'a self) -> ShaderUse<'a> {
321		ShaderUse::new(self)
322	}
323}
324
325impl<'a> ShaderUse<'a> {
326	/// Create a new `using` state to the `Shader`
327	fn new(shader: &'a Shader) -> Self {
328		shader.glcore.glUseProgram(shader.get_name());
329		Self {
330			shader,
331		}
332	}
333
334	/// Dispatch the compute shader
335	pub fn dispatch_compute(&self, num_groups_x: u32, num_groups_y: u32, num_groups_z: u32) {
336		if self.shader.shader_type != ShaderType::Compute {
337			panic!("Only compute shaders could use the `dispatch_compute()` method.");
338		}
339		self.shader.glcore.glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
340	}
341
342	/// Dispatch the compute shader
343	pub fn dispatch_compute_indirect(&self, buffer: &Buffer, index: usize) {
344		if self.shader.shader_type != ShaderType::Compute {
345			panic!("Only compute shaders could use the `dispatch_compute_indirect()` method.");
346		}
347		let bind = buffer.bind_to(BufferTarget::DispatchIndirectBuffer);
348		self.shader.glcore.glDispatchComputeIndirect(index * size_of::<DispatchIndirectCommand>());
349		bind.unbind();
350	}
351
352	/// Set shader uniform inputs by a material
353	pub fn setup_material_uniforms(&self, material: &dyn Material, prefix: Option<&str>, camel_case: bool) {
354		let glcore = &self.shader.glcore;
355		let shader_uniforms = self.shader.get_active_uniforms().unwrap();
356		let texture_names = material.get_names();
357		let mut active_texture = 0u32;
358		for name in texture_names.iter() {
359			let mut name_mod = String::new();
360			if let Some(prefix) = prefix {
361				name_mod.push_str(prefix);
362			}
363			if camel_case {
364				name_mod.push_str(&to_camel_case(name, prefix.is_some()));
365			} else {
366				name_mod.push_str(&name);
367			}
368			if let Some(_) = shader_uniforms.get(&name_mod) {
369				if let Some(texture) = material.get_by_name(&name) {
370					let location = self.shader.get_uniform_location(&name_mod);
371					if location == -1 {
372						continue;
373					}
374					match texture {
375						MaterialComponent::Texture(texture) => {
376							texture.set_active_unit(active_texture);
377							let bind = texture.bind();
378							glcore.glUniform1i(location, active_texture as i32);
379							bind.unbind();
380							active_texture += 1;
381						}
382						MaterialComponent::Color(color) => {
383							glcore.glUniform4f(location, color.x, color.y, color.z, color.w);
384						}
385						MaterialComponent::Luminance(lum) => {
386							glcore.glUniform1f(location, *lum);
387						}
388					}
389				}
390			}
391		}
392	}
393
394	/// Unuse the program.
395	pub fn unuse(self) {}
396}
397
398impl Drop for ShaderUse<'_> {
399	fn drop(&mut self) {
400		self.shader.glcore.glUseProgram(0)
401	}
402}
403
404impl Drop for Shader {
405	fn drop(&mut self) {
406		self.glcore.glDeleteProgram(self.program)
407	}
408}
409
410impl ShaderBinary {
411	pub fn new(format: u32, shader_type: ShaderType, binary: Vec<u8>) -> Self {
412		Self {
413			format,
414			shader_type,
415			binary,
416		}
417	}
418
419	pub fn load_from_file(path: &Path) -> Result<Self, ShaderBinaryLoadError> {
420		let config = bincode::config::standard()
421			.with_little_endian()
422			.with_fixed_int_encoding();
423		let mut file = std::fs::File::open(path)?;
424		Ok(bincode::decode_from_std_read(&mut file, config)?)
425	}
426
427	pub fn save_to_file(&self, path: &Path) -> Result<(), ShaderBinarySaveError> {
428		let config = bincode::config::standard()
429			.with_little_endian()
430			.with_fixed_int_encoding();
431		let mut file = std::fs::File::open(path)?;
432		bincode::encode_into_std_write(self, &mut file, config)?;
433		Ok(())
434	}
435}
436
437impl ShaderInputType {
438	pub fn is_float(&self) -> bool {
439		matches!(self, Self::Float | Self::Vec2 | Self::Vec3 | Self::Vec4 | Self::Mat2 | Self::Mat3 | Self::Mat4 | Self::Mat2x3 | Self::Mat2x4 | Self::Mat3x2 | Self::Mat3x4 | Self::Mat4x2 | Self::Mat4x3)
440	}
441
442	pub fn is_double(&self) -> bool {
443		matches!(self, Self::Double | Self::DVec2 | Self::DVec3 | Self::DVec4 | Self::DMat2 | Self::DMat3 | Self::DMat4 | Self::DMat2x3 | Self::DMat2x4 | Self::DMat3x2 | Self::DMat3x4 | Self::DMat4x2 | Self::DMat4x3)
444	}
445
446	pub fn is_integer(&self) -> bool {
447		matches!(self, Self::Int | Self::IVec2 | Self::IVec3 | Self::IVec4 | Self::UInt | Self::UVec2 | Self::UVec3 | Self::UVec4)
448	}
449
450	pub fn get_size_and_rows(&self) -> (u32, u32) {
451		match self {
452			Self::Float | Self::Double | Self::Int | Self::UInt => (1, 1),
453			Self::Vec2 | Self::DVec2 | Self::IVec2 | Self::UVec2 => (2, 1),
454			Self::Vec3 | Self::DVec3 | Self::IVec3 | Self::UVec3 => (3, 1),
455			Self::Vec4 | Self::DVec4 | Self::IVec4 | Self::UVec4 => (4, 1),
456			Self::Mat2 | Self::DMat2 => (2, 2),
457			Self::Mat3 | Self::DMat3 => (3, 3),
458			Self::Mat4 | Self::DMat4 => (4, 4),
459			Self::Mat2x3 | Self::DMat2x3 => (2, 3),
460			Self::Mat2x4 | Self::DMat2x4 => (2, 4),
461			Self::Mat3x2 | Self::DMat3x2 => (3, 2),
462			Self::Mat3x4 | Self::DMat3x4 => (3, 4),
463			Self::Mat4x2 | Self::DMat4x2 => (4, 2),
464			Self::Mat4x3 | Self::DMat4x3 => (4, 3),
465		}
466	}
467
468	pub fn get_base_type(&self) -> ShaderInputType {
469		match self {
470			Self::Float | Self::Vec2 | Self::Vec3 | Self::Vec4 | Self::Mat2 | Self::Mat3 | Self::Mat4 | Self::Mat2x3 | Self::Mat2x4 | Self::Mat3x2 | Self::Mat3x4 | Self::Mat4x2 | Self::Mat4x3 => Self::Float,
471			Self::Double | Self::DVec2 | Self::DVec3 | Self::DVec4 | Self::DMat2 | Self::DMat3 | Self::DMat4 | Self::DMat2x3 | Self::DMat2x4 | Self::DMat3x2 | Self::DMat3x4 | Self::DMat4x2 | Self::DMat4x3 => Self::Double,
472			Self::Int | Self::IVec2 | Self::IVec3 | Self::IVec4 => Self::Int,
473			Self::UInt | Self::UVec2 | Self::UVec3 | Self::UVec4 => Self::UInt,
474		}
475	}
476}
477
478impl ShaderInputVarType {
479	pub fn is_float(&self) -> bool {
480		self.type_.is_float()
481	}
482
483	pub fn is_double(&self) -> bool {
484		self.type_.is_double()
485	}
486
487	pub fn is_integer(&self) -> bool {
488		self.type_.is_integer()
489	}
490
491	pub fn get_size_and_rows(&self) -> (u32, u32) {
492		self.type_.get_size_and_rows()
493	}
494
495	pub fn get_type(&self) -> ShaderInputType {
496		self.type_
497	}
498
499	pub fn get_base_type(&self) -> ShaderInputType {
500		self.type_.get_base_type()
501	}
502}
503
504impl Debug for Shader {
505	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
506		f.debug_struct("Shader")
507		.field("program", &self.program)
508		.finish()
509	}
510}
511
512impl Debug for ShaderError {
513	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
514		match self {
515			Self::VSError(infolog) => write!(f, "Vertex Shader Error:\n{infolog}"),
516			Self::GSError(infolog) => write!(f, "Geometry Shader Error:\n{infolog}"),
517			Self::FSError(infolog) => write!(f, "Fragment Shader Error:\n{infolog}"),
518			Self::CSError(infolog) => write!(f, "Compute Shader Error:\n{infolog}"),
519			Self::LinkageError(infolog) => write!(f, "Shader Linkage Error:\n{infolog}"),
520		}
521	}
522}
523
524impl From<u32> for ShaderInputType {
525	fn from(val: u32) -> Self {
526		match val {
527			GL_FLOAT => Self::Float,
528			GL_FLOAT_VEC2 => Self::Vec2,
529			GL_FLOAT_VEC3 => Self::Vec3,
530			GL_FLOAT_VEC4 => Self::Vec4,
531			GL_FLOAT_MAT2 => Self::Mat2,
532			GL_FLOAT_MAT3 => Self::Mat3,
533			GL_FLOAT_MAT4 => Self::Mat4,
534			GL_FLOAT_MAT2x3 => Self::Mat2x3,
535			GL_FLOAT_MAT2x4 => Self::Mat2x4,
536			GL_FLOAT_MAT3x2 => Self::Mat3x2,
537			GL_FLOAT_MAT3x4 => Self::Mat3x4,
538			GL_FLOAT_MAT4x2 => Self::Mat4x2,
539			GL_FLOAT_MAT4x3 => Self::Mat4x3,
540			GL_INT => Self::Int,
541			GL_INT_VEC2 => Self::IVec2,
542			GL_INT_VEC3 => Self::IVec3,
543			GL_INT_VEC4 => Self::IVec4,
544			GL_UNSIGNED_INT => Self::UInt,
545			GL_UNSIGNED_INT_VEC2 => Self::UVec2,
546			GL_UNSIGNED_INT_VEC3 => Self::UVec3,
547			GL_UNSIGNED_INT_VEC4 => Self::UVec4,
548			GL_DOUBLE => Self::Double,
549			GL_DOUBLE_VEC2 => Self::DVec2,
550			GL_DOUBLE_VEC3 => Self::DVec3,
551			GL_DOUBLE_VEC4 => Self::DVec4,
552			GL_DOUBLE_MAT2 => Self::DMat2,
553			GL_DOUBLE_MAT3 => Self::DMat3,
554			GL_DOUBLE_MAT4 => Self::DMat4,
555			GL_DOUBLE_MAT2x3 => Self::DMat2x3,
556			GL_DOUBLE_MAT2x4 => Self::DMat2x4,
557			GL_DOUBLE_MAT3x2 => Self::DMat3x2,
558			GL_DOUBLE_MAT3x4 => Self::DMat3x4,
559			GL_DOUBLE_MAT4x2 => Self::DMat4x2,
560			GL_DOUBLE_MAT4x3 => Self::DMat4x3,
561			_ => panic!("Invalid value {val} of `ShaderInputType`"),
562		}
563	}
564}
565
566impl Debug for ShaderInputType {
567	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
568		match self {
569			Self::Float => write!(f, "float"),
570			Self::Vec2 => write!(f, "vec2"),
571			Self::Vec3 => write!(f, "vec3"),
572			Self::Vec4 => write!(f, "vec4"),
573			Self::Mat2 => write!(f, "mat2"),
574			Self::Mat3 => write!(f, "mat3"),
575			Self::Mat4 => write!(f, "mat4"),
576			Self::Mat2x3 => write!(f, "mat2x3"),
577			Self::Mat2x4 => write!(f, "mat2x4"),
578			Self::Mat3x2 => write!(f, "mat3x2"),
579			Self::Mat3x4 => write!(f, "mat3x4"),
580			Self::Mat4x2 => write!(f, "mat4x2"),
581			Self::Mat4x3 => write!(f, "mat4x3"),
582			Self::Int => write!(f, "int"),
583			Self::IVec2 => write!(f, "ivec2"),
584			Self::IVec3 => write!(f, "ivec3"),
585			Self::IVec4 => write!(f, "ivec4"),
586			Self::UInt => write!(f, "uint"),
587			Self::UVec2 => write!(f, "uvec2"),
588			Self::UVec3 => write!(f, "uvec3"),
589			Self::UVec4 => write!(f, "uvec4"),
590			Self::Double => write!(f, "double"),
591			Self::DVec2 => write!(f, "dvec2"),
592			Self::DVec3 => write!(f, "dvec3"),
593			Self::DVec4 => write!(f, "dvec4"),
594			Self::DMat2 => write!(f, "dmat2"),
595			Self::DMat3 => write!(f, "dmat3"),
596			Self::DMat4 => write!(f, "dmat4"),
597			Self::DMat2x3 => write!(f, "dmat2x3"),
598			Self::DMat2x4 => write!(f, "dmat2x4"),
599			Self::DMat3x2 => write!(f, "dmat3x2"),
600			Self::DMat3x4 => write!(f, "dmat3x4"),
601			Self::DMat4x2 => write!(f, "dmat4x2"),
602			Self::DMat4x3 => write!(f, "dmat4x3"),
603		}
604	}
605}
606
607impl Display for ShaderInputType {
608	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
609		<Self as Debug>::fmt(self, f)
610	}
611}
612
613impl From<std::io::Error> for ShaderBinaryLoadError {
614	fn from(err: std::io::Error) -> Self {
615		Self::IOError(err)
616	}
617}
618
619impl From<bincode::error::DecodeError> for ShaderBinaryLoadError {
620	fn from(err: bincode::error::DecodeError) -> Self {
621		Self::DecodeError(err)
622	}
623}
624
625impl From<std::io::Error> for ShaderBinarySaveError {
626	fn from(err: std::io::Error) -> Self {
627		Self::IOError(err)
628	}
629}
630
631impl From<bincode::error::EncodeError> for ShaderBinarySaveError {
632	fn from(err: bincode::error::EncodeError) -> Self {
633		Self::EncodeError(err)
634	}
635}