mallumo_gls/
compute_program.rs1use super::errors::*;
2
3use std::path::Path;
4use std::fs::File;
5use std::io::Read;
6
7use raw::{attach_shader, compile_shader, create_program, create_shader, delete_program, delete_shader, detach_shader,
8 get_integer_i_v, get_program_info_log, get_shader_info_log, link_program, shader_source, use_program,
9 GetParameterName, ProgramId, ShaderType};
10
11#[derive(Debug)]
12pub struct ComputeProgram {
13 id: ProgramId,
14}
15
16impl ComputeProgram {
17 #[allow(unused_must_use)]
18 pub fn new(sources: &[&str]) -> Result<ComputeProgram> {
19 let program_id: ProgramId;
20 unsafe {
21 let shader_id = create_shader(ShaderType::Compute);
22
23 shader_source(shader_id, sources);
24 compile_shader(shader_id);
25
26 let shader_info_log = get_shader_info_log(shader_id);
27
28 match shader_info_log {
29 Ok(log) => if log.len() > 1 {
30 delete_shader(shader_id);
31 bail!(log);
32 },
33 Err(_) => {
34 delete_shader(shader_id);
35 shader_info_log.chain_err(|| "Could not get shader compilation log")?;
36 }
37 }
38
39 program_id = create_program();
40 let attach_status = attach_shader(program_id, shader_id);
41 if attach_status.is_err() {
42 delete_program(program_id);
43 delete_shader(shader_id);
44 attach_status.chain_err(|| "Could not attach shader")?;
45 }
46
47 let link_status = link_program(program_id);
48 if link_status.is_err() {
49 let program_info_log = get_program_info_log(program_id);
50 match program_info_log {
51 Ok(log) => if log.len() > 1 {
52 delete_program(program_id);
53 delete_shader(shader_id);
54 bail!(log);
55 },
56 Err(_) => {
57 delete_program(program_id);
58 delete_shader(shader_id);
59 program_info_log.chain_err(|| "Could not get program link log")?;
60 }
61 }
62 }
63
64 detach_shader(program_id, shader_id);
68
69 delete_shader(shader_id);
70 }
71 Ok(ComputeProgram { id: program_id })
72 }
73
74 pub fn from_file(filepath: &Path) -> Result<ComputeProgram> {
75 let mut file = match File::open(&filepath) {
76 Ok(file) => file,
77 Err(e) => return Err(format!("Could not open shader file : {}", e).into()),
78 };
79
80 let mut source = String::new();
81 match file.read_to_string(&mut source) {
82 Ok(_) => {}
83 Err(e) => return Err(format!("Could not read shader file! : {}", e).into()),
84 };
85
86 ComputeProgram::new(&[source.as_str()])
87 }
88
89 pub fn bind(&self) -> Result<()> {
90 unsafe { use_program(self.id).chain_err(|| "Could not bind compute program") }
91 }
92
93 pub fn get_id(&self) -> ProgramId {
94 self.id
95 }
96
97 pub fn max_group_count() -> (u32, u32, u32) {
98 unsafe {
99 let x = get_integer_i_v(GetParameterName::MaxComputeWorkGroupCount, 0).unwrap() as u32;
100 let y = get_integer_i_v(GetParameterName::MaxComputeWorkGroupCount, 1).unwrap() as u32;
101 let z = get_integer_i_v(GetParameterName::MaxComputeWorkGroupCount, 2).unwrap() as u32;
102
103 (x, y, z)
104 }
105 }
106
107 pub fn max_group_size() -> (u32, u32, u32) {
108 unsafe {
109 let x = get_integer_i_v(GetParameterName::MaxComputeWorkGroupSize, 0).unwrap() as u32;
110 let y = get_integer_i_v(GetParameterName::MaxComputeWorkGroupSize, 1).unwrap() as u32;
111 let z = get_integer_i_v(GetParameterName::MaxComputeWorkGroupSize, 2).unwrap() as u32;
112
113 (x, y, z)
114 }
115 }
116
117 pub fn max_group_invocations() -> u32 {
118 unsafe { get_integer_i_v(GetParameterName::MaxComputeWorkGroupInvocations, 0).unwrap() as u32 }
119 }
120}
121
122impl Drop for ComputeProgram {
123 fn drop(&mut self) {
124 unsafe {
125 delete_program(self.id);
126 }
127 }
128}