diff --git a/src/main.rs b/src/main.rs index 81a95d86..e5e94fd8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,7 +56,26 @@ mod util; mod button; mod workpiece; + +//struct Sprite { +// pub texture: +// +// +//} + /* + + +How the F am I going to do sprites? + +I need sprites for the slider and buttons at least + +The background + render of the toolpath can probably just be straight up hand manipulated textures + +Sprite will have 4 verticies and a texture along with position and size attributes + + + */ fn main() { diff --git a/src/vkprocessor.rs b/src/vkprocessor.rs index b200bafd..9c3c63e7 100644 --- a/src/vkprocessor.rs +++ b/src/vkprocessor.rs @@ -15,7 +15,7 @@ use image::{DynamicImage, ImageBuffer}; use image::GenericImageView; use vulkano::descriptor::pipeline_layout::PipelineLayout; use image::GenericImage; -use shade_runner::{ComputeLayout, CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout}; +use shade_runner::{ComputeLayout, CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout, CompiledShaders, Entry}; use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSetImg, PersistentDescriptorSetSampler}; use shaderc::CompileOptions; use vulkano::framebuffer::{Subpass, RenderPass, RenderPassAbstract, Framebuffer, FramebufferAbstract}; @@ -35,6 +35,10 @@ use vulkano::image::attachment::AttachmentImage; use vulkano::image::{Dimensions, ImageUsage}; use vulkano::format::Format; use vulkano::sampler::{Sampler, Filter, MipmapMode, SamplerAddressMode}; +use image::flat::NormalForm::ColumnMajorPacked; + +mod compute_kernel; +use crate::vkprocessor::compute_kernel::ComputeKernel; #[derive(Default, Debug, Clone)] struct tVertex { position: [f32; 2] } @@ -64,13 +68,14 @@ fn window_size_dependent_setup( } #[repr(C)] -struct MySpecConstants { - my_integer_constant: i32, - a_boolean: u32, - floating_point: f32, +#[derive(Clone)] +struct SimpleSpecializationConstants { + first_constant: i32, + second_constant: u32, + third_constant: f32, } -unsafe impl SpecializationConstants for MySpecConstants { +unsafe impl SpecializationConstants for SimpleSpecializationConstants { fn descriptors() -> &'static [SpecializationMapEntry] { static DESCRIPTORS: [SpecializationMapEntry; 3] = [ SpecializationMapEntry { @@ -96,6 +101,9 @@ unsafe impl SpecializationConstants for MySpecConstants { pub struct VkProcessor<'a> { + pub compute_kernel: Option, + pub vertex_shader_path: PathBuf, + pub fragment_shader_path: PathBuf, pub instance: Arc, pub physical: PhysicalDevice<'a>, pub graphics_pipeline: Option>, @@ -107,7 +115,7 @@ pub struct VkProcessor<'a> { pub img_set: Option, ((((), PersistentDescriptorSetImg>>), PersistentDescriptorSetSampler), PersistentDescriptorSetImg>)>>>, pub graphics_image_buffer: Option>>, pub image_buffer: Vec, - pub img_buffers: Vec>>, + pub compute_image_buffers: Vec>>, pub settings_buffer: Option>>, pub swapchain: Option>>, pub images: Option>>>, @@ -115,7 +123,7 @@ pub struct VkProcessor<'a> { pub render_pass: Option>, pub vertex_buffer: Option>, pub dynamic_state: DynamicState, - pub graphics_iamge_swap_buffer: Option>, + pub graphics_image_swap_buffer: Option>, } @@ -140,6 +148,9 @@ impl<'a> VkProcessor<'a> { let queue = queues.next().unwrap(); VkProcessor { + compute_kernel: Option::None, + vertex_shader_path: Default::default(), + fragment_shader_path: Default::default(), instance: instance.clone(), physical: physical.clone(), graphics_pipeline: Option::None, @@ -151,7 +162,7 @@ impl<'a> VkProcessor<'a> { img_set: Option::None, graphics_image_buffer: None, image_buffer: Vec::new(), - img_buffers: Vec::new(), + compute_image_buffers: Vec::new(), settings_buffer: Option::None, swapchain: Option::None, images: Option::None, @@ -159,49 +170,18 @@ impl<'a> VkProcessor<'a> { render_pass: Option::None, vertex_buffer: Option::None, dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None }, - graphics_iamge_swap_buffer: None, + graphics_image_swap_buffer: None, } } - pub fn compile_kernel(&mut self, filename: String) { - let project_root = - std::env::current_dir() - .expect("failed to get root directory"); - - let mut compute_path = project_root.clone(); - compute_path.push(PathBuf::from("resources/shaders/")); - compute_path.push(PathBuf::from(filename)); - - - let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap(); - options.add_macro_definition("SETTING_POS_X", Some("0")); - options.add_macro_definition("SETTING_POS_Y", Some("1")); - options.add_macro_definition("SETTING_BUCKETS_START", Some("2")); - options.add_macro_definition("SETTING_BUCKETS_LEN", Some("2")); - - let shader = - sr::load_compute_with_options(compute_path, options) - .expect("Failed to compile"); - let vulkano_entry = - sr::parse_compute(&shader) - .expect("failed to parse"); + pub fn compile_kernel(&mut self, filename: String) { - let x = unsafe { - vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &shader.compute) - }.unwrap(); + self.compute_kernel = Some(ComputeKernel::new(filename, self.device.clone())); + self.compute_pipeline = Some(self.compute_kernel.clone().unwrap().get_pipeline()); + } - let compute_pipeline = Arc::new({ - unsafe { - ComputePipeline::new(self.device.clone(), &x.compute_entry_point( - CStr::from_bytes_with_nul_unchecked(b"main\0"), - vulkano_entry.compute_layout), &(), - ).unwrap() - } - }); - self.compute_pipeline = Some(compute_pipeline); - } pub fn compile_shaders(&mut self, filename: String, surface: &'a Arc>) { @@ -262,16 +242,9 @@ impl<'a> VkProcessor<'a> { options.add_macro_definition("SETTING_BUCKETS_START", Some("2")); options.add_macro_definition("SETTING_BUCKETS_LEN", Some("2")); - let shader = sr::load(vertex_shader_path, fragment_shader_path).expect(""); -// let shader = match sr::load(vertex_shader_path, fragment_shader_path) { -// Ok(t) => t, -// Err(e) => { -// -// panic!(e); -// } -// }; - - + // TODO: better compile message, run til successful compile + let shader = sr::load(vertex_shader_path, fragment_shader_path) + .expect("Shader didn't compile"); let vulkano_entry = sr::parse(&shader) @@ -285,7 +258,7 @@ impl<'a> VkProcessor<'a> { vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &shader.vertex) }.unwrap(); - let frag_entry_point: GraphicsEntryPoint = unsafe { + let frag_entry_point: GraphicsEntryPoint = unsafe { x1.graphics_entry_point(CStr::from_bytes_with_nul_unchecked(b"main\0"), vulkano_entry.frag_input, vulkano_entry.frag_output, @@ -293,7 +266,7 @@ impl<'a> VkProcessor<'a> { GraphicsShaderType::Fragment) }; - let vert_entry_point: GraphicsEntryPoint = unsafe { + let vert_entry_point: GraphicsEntryPoint = unsafe { x2.graphics_entry_point(CStr::from_bytes_with_nul_unchecked(b"main\0"), vulkano_entry.vert_input, vulkano_entry.vert_output, @@ -345,20 +318,20 @@ impl<'a> VkProcessor<'a> { // A Vulkan shader can in theory contain multiple entry points, so we have to specify // which one. The `main` word of `main_entry_point` actually corresponds to the name of // the entry point. - .vertex_shader(vert_entry_point, MySpecConstants { - my_integer_constant: 0, - a_boolean: 0, - floating_point: 0.0, + .vertex_shader(vert_entry_point, SimpleSpecializationConstants { + first_constant: 0, + second_constant: 0, + third_constant: 0.0, }) // The content of the vertex buffer describes a list of triangles. .triangle_fan() // Use a resizable viewport set to draw over the entire window .viewports_dynamic_scissors_irrelevant(1) // See `vertex_shader`. - .fragment_shader(frag_entry_point, MySpecConstants { - my_integer_constant: 0, - a_boolean: 0, - floating_point: 0.0, + .fragment_shader(frag_entry_point, SimpleSpecializationConstants { + first_constant: 0, + second_constant: 0, + third_constant: 0.0, }) // We have to indicate which subpass of which render pass this pipeline is going to be used // in. The pipeline will only be usable from this particular subpass. @@ -467,8 +440,8 @@ impl<'a> VkProcessor<'a> { self.compute_set = Some(Arc::new(set.build().unwrap())); - self.img_buffers.push(write_buffer); - self.img_buffers.push(read_buffer); + self.compute_image_buffers.push(write_buffer); + self.compute_image_buffers.push(read_buffer); self.settings_buffer = Some(settings_buffer); @@ -493,9 +466,6 @@ impl<'a> VkProcessor<'a> { Dimensions::Dim2d { width: self.xy.0, height: self.xy.1 }, Format::R8G8B8A8Srgb, self.queue.clone() -// self.image_buffer.iter().cloned(), -// Format::R8G8B8A8Uint, - ).unwrap() }; @@ -516,14 +486,13 @@ impl<'a> VkProcessor<'a> { MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(); - self.img_set = Some(Arc::new(PersistentDescriptorSet::start(self.graphics_pipeline.clone().unwrap().clone(), 0) .add_sampled_image(texture.clone(), sampler.clone()).unwrap() .add_image(attachment_image.clone().unwrap().clone()).unwrap() .build().unwrap())); self.graphics_image_buffer = Some(texture.clone()); - self.graphics_iamge_swap_buffer = Some(attachment_image.clone().unwrap()); + self.graphics_image_swap_buffer = Some(attachment_image.clone().unwrap()); } pub fn run(&mut self, surface: &'a Arc>, mut frame_future: Box) -> Box { @@ -585,8 +554,8 @@ impl<'a> VkProcessor<'a> { self.compute_pipeline.clone().unwrap().clone(), self.compute_set.clone().unwrap().clone(), ()).unwrap() - .copy_buffer_to_image(self.img_buffers.get(0).unwrap().clone(), - self.graphics_iamge_swap_buffer.clone().unwrap()).unwrap() + .copy_buffer_to_image(self.compute_image_buffers.get(0).unwrap().clone(), + self.graphics_image_swap_buffer.clone().unwrap()).unwrap() .begin_render_pass(framebuffers[image_num].clone(), false, clear_values) .unwrap() @@ -600,7 +569,7 @@ impl<'a> VkProcessor<'a> { .build().unwrap(); - let mut data_buffer_content = self.img_buffers.get(0).unwrap().read().unwrap(); + let mut data_buffer_content = self.compute_image_buffers.get(0).unwrap().read().unwrap(); let img = ImageBuffer::from_fn(self.xy.0, self.xy.1, |x, y| { let r = data_buffer_content[((self.xy.0 * y + x) * 4 + 0) as usize] as u8; let g = data_buffer_content[((self.xy.0 * y + x) * 4 + 1) as usize] as u8; diff --git a/src/vkprocessor/compute_kernel.rs b/src/vkprocessor/compute_kernel.rs new file mode 100644 index 00000000..63fcabf4 --- /dev/null +++ b/src/vkprocessor/compute_kernel.rs @@ -0,0 +1,143 @@ +use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, DeviceLocalBuffer, ImmutableBuffer, BufferAccess}; +use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState}; +use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet, StdDescriptorPoolAlloc}; +use vulkano::device::{Device, DeviceExtensions, QueuesIter, Queue}; +use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice, QueueFamily}; +use vulkano::pipeline::{ComputePipeline, GraphicsPipeline, GraphicsPipelineAbstract}; +use vulkano::sync::{GpuFuture, FlushError}; +use vulkano::sync; +use std::time::SystemTime; +use std::sync::Arc; +use std::ffi::CStr; +use std::path::PathBuf; +use shade_runner as sr; +use image::{DynamicImage, ImageBuffer}; +use image::GenericImageView; +use vulkano::descriptor::pipeline_layout::PipelineLayout; +use image::GenericImage; +use shade_runner::{ComputeLayout, CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout, CompiledShaders, Entry}; +use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSetImg, PersistentDescriptorSetSampler}; +use shaderc::CompileOptions; +use vulkano::framebuffer::{Subpass, RenderPass, RenderPassAbstract, Framebuffer, FramebufferAbstract}; +use vulkano::pipeline::shader::{GraphicsShaderType, ShaderModule, GraphicsEntryPoint, SpecializationConstants, SpecializationMapEntry}; +use vulkano::swapchain::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError}; +use vulkano::swapchain::acquire_next_image; +use vulkano::image::swapchain::SwapchainImage; +use winit::{EventsLoop, WindowBuilder, Window, Event, WindowEvent}; +use vulkano_win::VkSurfaceBuild; +use vulkano::pipeline::vertex::{SingleBufferDefinition, Vertex}; +use vulkano::descriptor::PipelineLayoutAbstract; +use std::alloc::Layout; +use vulkano::pipeline::viewport::Viewport; +use image::ImageFormat; +use vulkano::image::immutable::ImmutableImage; +use vulkano::image::attachment::AttachmentImage; +use vulkano::image::{Dimensions, ImageUsage}; +use vulkano::format::Format; +use vulkano::sampler::{Sampler, Filter, MipmapMode, SamplerAddressMode}; +use image::flat::NormalForm::ColumnMajorPacked; +use crate::vkprocessor::SimpleSpecializationConstants; + +#[derive(Clone)] +pub struct ComputeKernel { + + compute_pipeline: Option>>>, + compute_kernel_path: PathBuf, + + shader: CompiledShaders, + entry: Entry, + shader_module: Arc, + device: Arc, + specialization_constants: SimpleSpecializationConstants, +} + +impl ComputeKernel { + + fn get_path(filename: String) -> PathBuf { + + let project_root = + std::env::current_dir() + .expect("failed to get root directory"); + + let mut compute_path = project_root.clone(); + compute_path.push(PathBuf::from("resources/shaders/")); + compute_path.push(PathBuf::from(filename)); + + compute_path + } + + pub fn new(filename: String, device: Arc) -> ComputeKernel { + + let compute_path = ComputeKernel::get_path(filename); + + let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap(); + + let shader = sr::load_compute_with_options(compute_path.clone(), options) + .expect("Failed to compile"); + + let entry = sr::parse_compute(&shader) + .expect("Failed to parse"); + + let shader_module = unsafe { + vulkano::pipeline::shader::ShaderModule::from_words(device.clone(), &shader.compute) + }.unwrap(); + + + ComputeKernel { + device: device, + shader: shader, + compute_pipeline: Option::None, + compute_kernel_path: compute_path, + entry: entry, + shader_module: shader_module, + specialization_constants: SimpleSpecializationConstants { + first_constant: 0, + second_constant: 0, + third_constant: 0.0 + } + } + } + + pub fn get_pipeline(&mut self) -> std::sync::Arc>> { + + match self.compute_pipeline.clone() { + Some(t) => t, + None => { + self.compute_pipeline = Some(Arc::new({ + unsafe { + ComputePipeline::new(self.device.clone(), &self.shader_module.compute_entry_point( + CStr::from_bytes_with_nul_unchecked(b"main\0"), + self.entry.compute_layout.clone()), &self.specialization_constants, + ).unwrap() + } + })); + self.compute_pipeline.clone().unwrap() + } + } + } + + pub fn recompile_kernel(&mut self) { + self.compile_kernel(String::from(self.compute_kernel_path.clone().to_str().unwrap())); + } + + pub fn compile_kernel(&mut self, filename: String) -> std::sync::Arc>> { + + let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap(); + self.compute_kernel_path = ComputeKernel::get_path(filename); + + self.shader = + sr::load_compute_with_options(self.compute_kernel_path.clone(), options) + .expect("Failed to compile"); + + self.entry = + sr::parse_compute(&self.shader) + .expect("Failed to parse"); + + self.shader_module = unsafe { + vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &self.shader.compute) + }.unwrap(); + + self.get_pipeline() + } +} +