1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
use super::*; use super::errors::*; use std::ptr; use std::ffi::CString; use std::mem::uninitialized; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct ShaderId(u32); impl From<ShaderId> for u32 { fn from(shader_id: ShaderId) -> Self { shader_id.0 } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ShaderParameter { ShaderType, DeleteStatus, CompileStatus, InfoLogLength, ShaderSourceLength, } impl From<ShaderParameter> for u32 { fn from(shader_parameter: ShaderParameter) -> Self { use self::ShaderParameter::*; match shader_parameter { ShaderType => gl::SHADER_TYPE, DeleteStatus => gl::DELETE_STATUS, CompileStatus => gl::COMPILE_STATUS, InfoLogLength => gl::INFO_LOG_LENGTH, ShaderSourceLength => gl::SHADER_SOURCE_LENGTH, } } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ShaderType { Vertex, Fragment, Geometry, TessellationEvaluation, TessellationControl, Compute, } impl From<ShaderType> for u32 { fn from(shader_type: ShaderType) -> Self { match shader_type { ShaderType::Vertex => gl::VERTEX_SHADER, ShaderType::Fragment => gl::FRAGMENT_SHADER, ShaderType::Geometry => gl::GEOMETRY_SHADER, ShaderType::TessellationEvaluation => gl::TESS_EVALUATION_SHADER, ShaderType::TessellationControl => gl::TESS_CONTROL_SHADER, ShaderType::Compute => gl::COMPUTE_SHADER, } } } pub unsafe fn create_shader(shader_type: ShaderType) -> ShaderId { ShaderId(gl::CreateShader(shader_type.into())) } pub unsafe fn shader_source<T: AsRef<str>>(id: ShaderId, sources: &[T]) { let mut source: String = String::new(); for s in sources { source.push_str(s.as_ref()); } let source_cstr = CString::new(source.as_bytes()).unwrap(); gl::ShaderSource(id.into(), 1, [source_cstr.as_ptr()].as_ptr(), ptr::null()); } pub unsafe fn compile_shader(id: ShaderId) { gl::CompileShader(id.into()); } pub unsafe fn get_shader(id: ShaderId, parameter: ShaderParameter) -> i32 { let mut value: gl::types::GLint = uninitialized(); gl::GetShaderiv(id.into(), parameter.into(), &mut value); value } pub unsafe fn get_shader_info_log(id: ShaderId) -> Result<String> { let mut error_log_size: gl::types::GLint = get_shader(id.into(), ShaderParameter::InfoLogLength); let mut error_log: Vec<u8> = Vec::with_capacity(error_log_size as usize); gl::GetShaderInfoLog( id.into(), error_log_size, &mut error_log_size, error_log.as_mut_ptr() as *mut gl::types::GLchar, ); error_log.set_len(error_log_size as usize); let string = match String::from_utf8(error_log) { Ok(s) => s, Err(_) => bail!("Could not convert log"), }; Ok(string) } pub unsafe fn delete_shader(id: ShaderId) { gl::DeleteShader(id.into()) } pub unsafe fn get_shader_compiled(id: ShaderId) -> bool { get_shader(id.into(), ShaderParameter::CompileStatus) == 1 } pub unsafe fn shader_binary(id: ShaderId, data: &[u8]) -> Result<()> { gl::ShaderBinary( 1, &(id.0) as &u32 as *const u32, gl::SHADER_BINARY_FORMAT_SPIR_V_ARB, data.as_ptr() as *const ::std::os::raw::c_void, data.len() as i32, ); get_error(()) } pub unsafe fn specialize_shader(id: ShaderId) -> Result<()> { let entry_point = ::std::ffi::CString::new("main").unwrap(); gl::SpecializeShaderARB( id.into(), entry_point.as_ptr(), 0, ::std::ptr::null(), ::std::ptr::null(), ); get_error(()) }