use std::path::Path; use anyhow::{anyhow, Result}; use vulkanalia::prelude::v1_0::*; use vulkanalia::Device; const COMPILE_SHADERS_PATH: &str = "lib"; pub(crate) unsafe fn create_shader_module( device: &Device, name: String, ) -> Result { let path = format!("{}/{}.spv", COMPILE_SHADERS_PATH, name); let file_content = std::fs::read(path)?; let bytecode = Vec::::from(file_content); let (prefix, code, suffix) = bytecode.align_to::(); if !prefix.is_empty() || !suffix.is_empty() { return Err(anyhow!("Shader bytecode is not properly aligned.")); } let info = vk::ShaderModuleCreateInfo::builder() .code_size(bytecode.len()) .code(code); Ok(device.create_shader_module(&info, None)?) } pub(crate) fn compile_shaders() -> Result<()> { if Path::new(COMPILE_SHADERS_PATH).exists() { let files = std::fs::read_dir(COMPILE_SHADERS_PATH)?; for file in files { let file = file?; let path = file.path(); if let Some(ext) = path.extension() { if ext == "spv" { std::fs::remove_file(path)?; } } } } else { std::fs::create_dir(COMPILE_SHADERS_PATH)?; } let output_vert = std::process::Command::new("glslc.exe") .arg("assets/shaders/shader.vert") .arg("-o") .arg(format!("{}/vert.spv", COMPILE_SHADERS_PATH)) .output() .expect("Failed to execute glslc.exe for vertex shader"); let output_frag = std::process::Command::new("glslc.exe") .arg("assets/shaders/shader.frag") .arg("-o") .arg(format!("{}/frag.spv", COMPILE_SHADERS_PATH)) .output() .expect("Failed to execute glslc.exe for fragment shader"); if !(output_vert.status.success() && output_frag.status.success()) { Err(anyhow!( "Failed to compile shaders:\n{}\n{}", String::from_utf8_lossy(&output_vert.stderr), String::from_utf8_lossy(&output_frag.stderr) ))?; } Ok(()) }