diff --git a/shaders/compile.bat b/shaders/compile.bat new file mode 100644 index 0000000..2c88e69 --- /dev/null +++ b/shaders/compile.bat @@ -0,0 +1,2 @@ +for %%i in (*.frag) do glslangValidator -V %%i -o %%i.spv +for %%i in (*.vert) do glslangValidator -V %%i -o %%i.spv \ No newline at end of file diff --git a/shaders/compile.ps1 b/shaders/compile.ps1 index 8b758d1..1d22125 100644 --- a/shaders/compile.ps1 +++ b/shaders/compile.ps1 @@ -1,4 +1,33 @@ -glslangValidator -V line.frag -o line_frag.spv -glslangValidator -V line.vert -o line_vert.spv -glslangValidator -V triangle.frag -o triangle_frag.spv -glslangValidator -V triangle.vert -o triangle_vert.spv \ No newline at end of file +$compileHashFile = "compilehashes.xml" + +if (Get-ChildItem -File $compileHashFile -ErrorAction SilentlyContinue) { + $hashes = Import-Clixml $compileHashFile +} else { + $hashes = @{} +} + +function CompileShader($fileName) { + $spvFileName = "$fileName.spv" + $newHash = Get-FileHash -Path $fileName -Algorithm SHA1 + + $spvExists = $false + if (Get-ChildItem -File $spvFileName -ErrorAction SilentlyContinue) { + $spvExists = $true + } + + if ($spvExists -and $hashes.ContainsKey($fileName) -and $hashes[$fileName] -eq $newHash.Hash) { + Write-Output "Skipping $fileName" + } else { + glslangValidator -V $fileName -o $spvFileName + $hashes.$fileName = $newHash.Hash + } +} + +Get-ChildItem -Filter *.vert | ForEach-Object { + CompileShader $_.Name +} +Get-ChildItem -Filter *.frag | ForEach-Object { + CompileShader $_.Name +} + +Export-Clixml -Path $compileHashFile -InputObject $hashes diff --git a/shaders/line_frag.spv b/shaders/line.frag.spv similarity index 100% rename from shaders/line_frag.spv rename to shaders/line.frag.spv diff --git a/shaders/line_vert.spv b/shaders/line.vert.spv similarity index 100% rename from shaders/line_vert.spv rename to shaders/line.vert.spv diff --git a/shaders/triangle.frag b/shaders/triangle.frag index c5c9b41..19b75d0 100644 --- a/shaders/triangle.frag +++ b/shaders/triangle.frag @@ -40,5 +40,4 @@ void main() { vec3 specular_color = specular_value * specular_strength * light_color; out_color = vec4(ambient_color + diffuse_color + specular_color, 1.0) * texture(diffuse_tex, tex_coords); - // out_color = vec4(1, 0, 0, 1); } \ No newline at end of file diff --git a/shaders/triangle_frag.spv b/shaders/triangle.frag.spv similarity index 100% rename from shaders/triangle_frag.spv rename to shaders/triangle.frag.spv diff --git a/shaders/triangle_vert.spv b/shaders/triangle.vert.spv similarity index 100% rename from shaders/triangle_vert.spv rename to shaders/triangle.vert.spv diff --git a/src/vulkan/pipelines.rs b/src/vulkan/pipelines.rs index c34fcd3..361bb8d 100644 --- a/src/vulkan/pipelines.rs +++ b/src/vulkan/pipelines.rs @@ -1,6 +1,6 @@ -use std::sync::Arc; +use std::{convert::TryInto, io::{Read, Write}, sync::Arc}; -use vulkano::{command_buffer::AutoCommandBufferBuilder, descriptor::descriptor_set::PersistentDescriptorSet}; +use vulkano::{command_buffer::AutoCommandBufferBuilder, descriptor::{descriptor::ShaderStages, descriptor_set::PersistentDescriptorSet}}; use vulkano::command_buffer::DynamicState; use vulkano::device::Device; use vulkano::framebuffer::RenderPassAbstract; @@ -52,20 +52,45 @@ impl DefaultShader { fn create_pipeline(device: Arc, render_pass: RP) -> GP { let sub_pass = Subpass::from(render_pass.clone(), 0).unwrap(); let vertex_shader = vs::Shader::load(device.clone()).unwrap(); - let fragment_shader = fs::Shader::load(device.clone()).unwrap(); - - Arc::new(GraphicsPipeline::start() - .vertex_input_single_buffer::() - .vertex_shader(vertex_shader.main_entry_point(), ()) - .triangle_list() - .viewports_dynamic_scissors_irrelevant(1) - .depth_stencil_simple_depth() - .fragment_shader(fragment_shader.main_entry_point(), ()) - .blend_alpha_blending() - .cull_mode_back() - .render_pass(sub_pass.clone()) - .build(device.clone()) - .unwrap()) + + #[cfg(debug_assertions)] + { + println!("Compiling shaders..."); + let output = std::process::Command::new("cmd.exe") + .arg("/c") + .arg("compile.bat") + .current_dir("shaders") + .output().unwrap(); + std::io::stdout().write_all(&output.stdout).unwrap(); + } + + unsafe { + let mut fs_file = std::fs::File::open("shaders/triangle.frag.spv").unwrap(); + let mut fs_buf = vec![]; + fs_file.read_to_end(&mut fs_buf).unwrap(); + let fs_words: Vec = fs_buf.chunks_exact(4).map(|c| u32::from_ne_bytes(c.try_into().unwrap())).collect(); + let fs_module = vulkano::pipeline::shader::ShaderModule::from_words(device.clone(), &fs_words).unwrap(); + let fs_layout = fs::Layout(ShaderStages { + fragment: true, + ..ShaderStages::none() + }); + static FS_NAME: [u8; 5usize] = [109u8, 97u8, 105u8, 110u8, 0]; + let fs_name_c = std::ffi::CStr::from_ptr(FS_NAME.as_ptr() as *const _); + let fs_entry = fs_module.graphics_entry_point(fs_name_c, fs::MainInput, fs::MainOutput, fs_layout, vulkano::pipeline::shader::GraphicsShaderType::Fragment); + + Arc::new(GraphicsPipeline::start() + .vertex_input_single_buffer::() + .vertex_shader(vertex_shader.main_entry_point(), ()) + .triangle_list() + .viewports_dynamic_scissors_irrelevant(1) + .depth_stencil_simple_depth() + .fragment_shader(fs_entry, ()) + .blend_alpha_blending() + .cull_mode_back() + .render_pass(sub_pass.clone()) + .build(device.clone()) + .unwrap()) + } } }