crystal_api/
shader.rs

1use std::{fs::File, io::Read};
2
3use crate::{
4    debug::log,
5    errors::{GraphicsError, GraphicsResult},
6};
7
8#[allow(missing_docs)]
9#[derive(Debug)]
10pub enum ShaderStage {
11    Vertex,
12    Fragment,
13    Geometry,
14    Tesselate,
15    Compute,
16}
17
18#[allow(missing_docs)]
19pub struct Shader {
20    pub(crate) stage: ShaderStage,
21    pub(crate) code: Vec<u32>,
22}
23
24impl Shader {
25    /// Opens shader with path and specified stage
26    /// ```rust
27    /// let shader = Shader::open(
28    ///    "shader.vert.spv",
29    ///    ShaderStage::Vertex,
30    ///).unwrap()
31    /// ```
32    pub fn open(path: &str, stage: ShaderStage) -> GraphicsResult<Self> {
33        let mut file = match File::open(path) {
34            Ok(file) => file,
35            Err(e) => {
36                log!("cannot open file: {}", e);
37                return Err(GraphicsError::ShaderError);
38            }
39        };
40
41        let size = file.metadata().unwrap().len() as usize;
42
43        let mut shader_code_bytes = Vec::<u8>::with_capacity(size);
44
45        match file.read_to_end(&mut shader_code_bytes) {
46            Ok(_) => unsafe {
47                shader_code_bytes.set_len(size);
48            },
49            Err(e) => {
50                log!("cannot read file: {}", e);
51                return Err(GraphicsError::ShaderError);
52            }
53        };
54
55        let shader_code = unsafe {
56            let ptr = std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked(size, 0x10))
57                as *mut u8;
58
59            if ptr.is_null() {
60                panic!("Failed to allocate memory");
61            }
62
63            std::slice::from_raw_parts_mut(ptr, size).copy_from_slice(std::slice::from_raw_parts(
64                shader_code_bytes.as_ptr(),
65                shader_code_bytes.len(),
66            ));
67
68            let len = size / 4;
69
70            Vec::from_raw_parts(ptr as *mut u32, len, len)
71        };
72
73        Ok(Shader {
74            stage,
75            code: shader_code,
76        })
77    }
78}