diff --git a/src/vkprocessor.rs b/src/vkprocessor.rs index 586122bc..b9fa02c6 100644 --- a/src/vkprocessor.rs +++ b/src/vkprocessor.rs @@ -75,66 +75,26 @@ fn window_size_dependent_setup( }).collect::>() } -#[repr(C)] -#[derive(Default, Debug, Clone)] -struct SimpleSpecializationConstants { - first_constant: i32, - second_constant: u32, - third_constant: f32, -} - -unsafe impl SpecializationConstants for SimpleSpecializationConstants { - fn descriptors() -> &'static [SpecializationMapEntry] { - static DESCRIPTORS: [SpecializationMapEntry; 3] = [ - SpecializationMapEntry { - constant_id: 0, - offset: 0, - size: 4, - }, - SpecializationMapEntry { - constant_id: 1, - offset: 4, - size: 4, - }, - SpecializationMapEntry { - constant_id: 2, - offset: 8, - size: 4, - }, - ]; - - &DESCRIPTORS - } -} - pub struct VkProcessor<'a> { - pub shader_kernels: Option, - pub compute_kernel: Option, - pub vertex_shader_path: PathBuf, - pub fragment_shader_path: PathBuf, + + // Vulkan state fields pub instance: Arc, pub physical: PhysicalDevice<'a>, - pub graphics_pipeline: Option>, - pub compute_pipeline: Option>>>, pub device: Arc, pub queues: QueuesIter, pub queue: Arc, - pub compute_set: Option>>, ((((), PersistentDescriptorSetBuf>>), PersistentDescriptorSetBuf>>), PersistentDescriptorSetBuf>>)>>>, - pub img_set: Option, ((((), PersistentDescriptorSetImg>>), PersistentDescriptorSetSampler), PersistentDescriptorSetImg>)>>>, - pub graphics_image_buffer: Option>>, - pub image_buffer: Vec, - pub compute_image_buffers: Vec>>, - pub settings_buffer: Option>>, - - pub xy: (u32, u32), - pub vertex_buffer: Option>, - pub vertex_buffer2: Option>, pub dynamic_state: DynamicState, - pub graphics_image_swap_buffer: Option>, + // TODO: This will need to handle multiple of each type + pub shader_kernels: Option, + pub compute_kernel: Option, + + // TODO: Move this into canvas + pub vertex_buffer: Option>, + pub vertex_buffer2: Option>, pub textures: Vec>>, - pub image_buffer_store : Vec>, + pub compute_image: Option, pub swapchain: Option>>, @@ -164,35 +124,18 @@ impl<'a> VkProcessor<'a> { let queue = queues.next().unwrap(); VkProcessor { - shader_kernels: Option::None, - compute_kernel: Option::None, - vertex_shader_path: Default::default(), - fragment_shader_path: Default::default(), instance: instance.clone(), physical: physical.clone(), - graphics_pipeline: Option::None, - compute_pipeline: Option::None, device: device.clone(), queue: queue, queues: queues, - compute_set: Option::None, - img_set: Option::None, - graphics_image_buffer: None, - image_buffer: Vec::new(), - compute_image_buffers: Vec::new(), - settings_buffer: Option::None, - xy: (0, 0), - - vertex_buffer: Option::None, - vertex_buffer2: None, - dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None }, - graphics_image_swap_buffer: None, - + shader_kernels: None, + compute_kernel: None, + vertex_buffer: None, + vertex_buffer2: None, textures: vec![], - image_buffer_store: vec![], compute_image: None, - swapchain: None, swapchain_images: None } @@ -201,7 +144,6 @@ impl<'a> VkProcessor<'a> { pub fn compile_kernel(&mut self, filename: String) { self.compute_kernel = Some(ComputeKernel::new(filename, self.device.clone())); - self.compute_pipeline = Some(self.compute_kernel.clone().unwrap().get_pipeline()); } pub fn compile_shaders(&mut self, filename: String, surface: &'a Arc>) { @@ -323,40 +265,6 @@ impl<'a> VkProcessor<'a> { { self.load_compute_image(image_filename.clone()); - 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/images/")); - compute_path.push(PathBuf::from(image_filename.clone())); - - let img = image::open(compute_path).expect("Couldn't find image"); - - self.xy = img.dimensions(); - - let data_length = self.xy.0 * self.xy.1 * 4; - let pixel_count = img.raw_pixels().len(); - println!("Pixel count {}", pixel_count); - - if pixel_count != data_length as usize { - println!("Creating apha channel..."); - for i in img.raw_pixels().iter() { - if (self.image_buffer.len() + 1) % 4 == 0 { - self.image_buffer.push(255); - } - self.image_buffer.push(*i); - } - self.image_buffer.push(255); - } else { - self.image_buffer = img.raw_pixels(); - } - - println!("Buffer length {}", self.image_buffer.len()); - println!("Size {:?}", self.xy); - - println!("Allocating Buffers..."); - let color = [1.,0.,0.,0.]; let vertex_buffer = { @@ -399,7 +307,7 @@ impl<'a> VkProcessor<'a> { let o : Box = Box::new( PersistentDescriptorSet::start( - self.shader_kernels.clone().unwrap().graphics_pipeline.clone().unwrap().clone(), 0 + self.shader_kernels.clone().unwrap().get_pipeline(), 0 ) .add_sampled_image(self.textures.get(0).unwrap().clone(), sampler.clone()).unwrap() .add_image(self.compute_image.clone().unwrap().clone().get_swap_buffer().clone()).unwrap() @@ -416,7 +324,7 @@ impl<'a> VkProcessor<'a> { let o : Box = Box::new( PersistentDescriptorSet::start( - self.shader_kernels.clone().unwrap().graphics_pipeline.clone().unwrap().clone(), 0 + self.shader_kernels.clone().unwrap().get_pipeline(), 0 ) .add_sampled_image(self.textures.get(1).unwrap().clone(), sampler.clone()).unwrap() .add_image(self.compute_image.clone().unwrap().clone().get_swap_buffer().clone()).unwrap() @@ -473,14 +381,16 @@ impl<'a> VkProcessor<'a> { let mut v2 = Vec::new(); v2.push(self.vertex_buffer2.clone().unwrap().clone()); + let xy = self.compute_image.clone().unwrap().get_size(); + let command_buffer = AutoCommandBufferBuilder::primary_one_time_submit(self.device.clone(), self.queue.family()) .unwrap() - .dispatch([self.xy.0, self.xy.1, 1], - self.compute_pipeline.clone().unwrap().clone(), - self.compute_image.clone().unwrap().clone().get_descriptor_set(self.compute_pipeline.clone().unwrap().clone()).clone(), ()).unwrap() - //self.compute_set.clone().unwrap().clone(), ()).unwrap() + .dispatch([xy.0, xy.1, 1], + self.compute_kernel.clone().unwrap().clone().get_pipeline(), + self.compute_image.clone().unwrap().clone() + .get_descriptor_set(self.compute_kernel.clone().unwrap().clone().get_pipeline()).clone(), ()).unwrap() .copy_buffer_to_image(self.compute_image.clone().unwrap().clone().rw_buffers.get(0).unwrap().clone(), self.compute_image.clone().unwrap().clone().get_swap_buffer().clone()).unwrap() @@ -488,12 +398,12 @@ impl<'a> VkProcessor<'a> { .begin_render_pass(framebuffers[image_num].clone(), false, clear_values) .unwrap() - .draw(self.shader_kernels.clone().unwrap().graphics_pipeline.clone().unwrap().clone(), + .draw(self.shader_kernels.clone().unwrap().get_pipeline(), &self.dynamic_state.clone(), v, vec![self.get_image_set()], ()) .unwrap() - .draw(self.shader_kernels.clone().unwrap().graphics_pipeline.clone().unwrap().clone(), + .draw(self.shader_kernels.clone().unwrap().get_pipeline(), &self.dynamic_state.clone(), v2, vec![self.get_gui_image_set()], ()) .unwrap() diff --git a/src/vkprocessor/compute_image.rs b/src/vkprocessor/compute_image.rs index 9f4d3366..be22dde0 100644 --- a/src/vkprocessor/compute_image.rs +++ b/src/vkprocessor/compute_image.rs @@ -37,9 +37,19 @@ use vulkano::format::Format; use vulkano::sampler::{Sampler, Filter, MipmapMode, SamplerAddressMode}; use image::flat::NormalForm::ColumnMajorPacked; use image::Rgba; -use crate::vkprocessor::SimpleSpecializationConstants; use crate::vertex_2d::ColoredVertex2D; +/* + +Compute Image holds read write swap and settings buffers for the kernel + +This is a pretty specific use case. One in for settings. One in for data, two for the transfer. + +multiple data inputs might be nice? + + +*/ + #[derive(Clone)] pub struct ComputeImage { @@ -47,10 +57,6 @@ pub struct ComputeImage { compute_graphics_swap_buffer: std::sync::Arc, - image_buffer: Vec, - - xy: (u32, u32), - pub rw_buffers: Vec>>, pub settings_buffer: Arc>, } @@ -142,8 +148,7 @@ impl ComputeImage { ComputeImage{ device: device.clone(), compute_graphics_swap_buffer: compute_graphics_swap_buffer.unwrap(), - image_buffer: image_buffer, - xy: xy, + rw_buffers: vec![write_buffer, read_buffer], settings_buffer: settings_buffer } @@ -153,14 +158,21 @@ impl ComputeImage { self.compute_graphics_swap_buffer.clone() } + pub fn get_size(&self) -> (u32, u32) { + let xy = self.compute_graphics_swap_buffer.dimensions(); + (xy[0], xy[1]) + } + pub fn read_read_buffer(&self) -> ImageBuffer, Vec>{ + let xy = self.get_size(); + let data_buffer_content = self.rw_buffers.get(0).unwrap().read().unwrap(); - 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; - let b = data_buffer_content[((self.xy.0 * y + x) * 4 + 2) as usize] as u8; - let a = data_buffer_content[((self.xy.0 * y + x) * 4 + 3) as usize] as u8; + ImageBuffer::from_fn(xy.0, xy.1, |x, y| { + let r = data_buffer_content[((xy.0 * y + x) * 4 + 0) as usize] as u8; + let g = data_buffer_content[((xy.0 * y + x) * 4 + 1) as usize] as u8; + let b = data_buffer_content[((xy.0 * y + x) * 4 + 2) as usize] as u8; + let a = data_buffer_content[((xy.0 * y + x) * 4 + 3) as usize] as u8; image::Rgba([r, g, b, a]) }) diff --git a/src/vkprocessor/compute_kernel.rs b/src/vkprocessor/compute_kernel.rs index 120e8dea..ed3b0bd3 100644 --- a/src/vkprocessor/compute_kernel.rs +++ b/src/vkprocessor/compute_kernel.rs @@ -36,7 +36,7 @@ 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 { @@ -48,7 +48,7 @@ pub struct ComputeKernel { entry: Entry, shader_module: Arc, device: Arc, - specialization_constants: SimpleSpecializationConstants, + specialization_constants: ComputeSpecializationConstants, } impl ComputeKernel { @@ -90,7 +90,7 @@ impl ComputeKernel { compute_kernel_path: compute_path, entry: entry, shader_module: shader_module, - specialization_constants: SimpleSpecializationConstants { + specialization_constants: ComputeSpecializationConstants { first_constant: 0, second_constant: 0, third_constant: 0.0 @@ -141,3 +141,35 @@ impl ComputeKernel { } } + +#[repr(C)] +#[derive(Default, Debug, Clone)] +struct ComputeSpecializationConstants { + first_constant: i32, + second_constant: u32, + third_constant: f32, +} + +unsafe impl SpecializationConstants for ComputeSpecializationConstants { + fn descriptors() -> &'static [SpecializationMapEntry] { + static DESCRIPTORS: [SpecializationMapEntry; 3] = [ + SpecializationMapEntry { + constant_id: 0, + offset: 0, + size: 4, + }, + SpecializationMapEntry { + constant_id: 1, + offset: 4, + size: 4, + }, + SpecializationMapEntry { + constant_id: 2, + offset: 8, + size: 4, + }, + ]; + + &DESCRIPTORS + } +} diff --git a/src/vkprocessor/shader_kernels.rs b/src/vkprocessor/shader_kernels.rs index c998c112..4a674a39 100644 --- a/src/vkprocessor/shader_kernels.rs +++ b/src/vkprocessor/shader_kernels.rs @@ -36,27 +36,21 @@ 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; use crate::vertex_2d::ColoredVertex2D; -struct EntryPoint<'a> { - compiled_shaders: CompiledShaders, - frag_entry_point: Option>, - vertex_entry_point: Option>, - vertex_shader_module: Arc, - fragment_shader_module: Arc, -} +/* + +Shaderkernel holds the pipeline and render pass for the inputted shader source + +*/ #[derive(Clone)] pub struct ShaderKernels { -// pub swapchain : Arc>, -// pub swapchain_images: Vec>>, // Surface which is drawn to pub render_pass: Arc, - pub graphics_pipeline: Option>, + graphics_pipeline: Option>, device: Arc, - } impl ShaderKernels { @@ -82,74 +76,15 @@ impl ShaderKernels { } pub fn get_pipeline(&mut self) -> Arc { - - match self.graphics_pipeline.clone() { - Some(t) => t, - None => { - // TODO: Create new graphics pipeline - self.graphics_pipeline.clone().unwrap() - } - } + self.graphics_pipeline.clone().unwrap() } - // On resizes we have to recreate the swapchain -// pub fn recreate_swapchain(mut self, surface: &Arc>) -> Self { -// let dimensions = if let Some(dimensions) = surface.window().get_inner_size() { -// let dimensions: (u32, u32) = dimensions.to_physical(surface.window().get_hidpi_factor()).into(); -// [dimensions.0, dimensions.1] -// } else { -// return self; -// }; -// -// let (new_swapchain, new_images) = match self.swapchain.clone().recreate_with_dimension(dimensions) { -// Ok(r) => r, -// // This error tends to happen when the user is manually resizing the window. -// // Simply restarting the loop is the easiest way to fix this issue. -// Err(SwapchainCreationError::UnsupportedDimensions) => panic!("Uh oh"), -// Err(err) => panic!("{:?}", err) -// }; -// -// self.swapchain = new_swapchain; -// self.swapchain_images = new_images; -// self -// } - pub fn new(filename: String, surface: &Arc>, queue: Arc, physical: PhysicalDevice, device: Arc) -> ShaderKernels { -// let (mut swapchain, images) = { -// let capabilities = surface.capabilities(physical).unwrap(); -// let usage = capabilities.supported_usage_flags; -// let alpha = capabilities.supported_composite_alpha.iter().next().unwrap(); -// // Choosing the internal format that the images will have. -// let format = capabilities.supported_formats[0].0; -// -// // Set the swapchains window dimensions -// let initial_dimensions = if let Some(dimensions) = surface.window().get_inner_size() { -// // convert to physical pixels -// let dimensions: (u32, u32) = dimensions.to_physical(surface.window().get_hidpi_factor()).into(); -// [dimensions.0, dimensions.1] -// } else { -// // The window no longer exists so exit the application. -// panic!("window closed"); -// }; -// -// Swapchain::new(device.clone(), -// surface.clone(), -// capabilities.min_image_count, -// format, -// initial_dimensions, -// 1, // Layers -// usage, -// &queue, -// SurfaceTransform::Identity, -// alpha, -// PresentMode::Fifo, true, None).unwrap() -// }; - let capabilities = surface.capabilities(physical).unwrap(); let format = capabilities.supported_formats[0].0; @@ -225,33 +160,23 @@ impl ShaderKernels { ).unwrap()); - ShaderKernels { -// swapchain: swapchain, -// swapchain_images: images, - //physical: physical, - //options: CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap(), graphics_pipeline: Some(Arc::new(GraphicsPipeline::start() - // We need to indicate the layout of the vertices. - // The type `SingleBufferDefinition` actually contains a template parameter corresponding - // to the type of each vertex. But in this code it is automatically inferred. + .vertex_input_single_buffer::() - // 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(vertex_entry_point.clone().unwrap(), SimpleSpecializationConstants { + .vertex_shader(vertex_entry_point.clone().unwrap(), ShaderSpecializationConstants { 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.clone().unwrap(), SimpleSpecializationConstants { + + .fragment_shader(frag_entry_point.clone().unwrap(), ShaderSpecializationConstants { first_constant: 0, second_constant: 0, third_constant: 0.0, @@ -259,7 +184,7 @@ impl ShaderKernels { // 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. .render_pass(Subpass::from(render_pass.clone(), 0).unwrap()) - // Now that our builder is filled, we call `build()` to obtain an actual pipeline. + .build(device.clone()) .unwrap())), @@ -268,4 +193,37 @@ impl ShaderKernels { } } +} + +#[repr(C)] +#[derive(Default, Debug, Clone)] +// TODO: This needs to be duplicated and moved into their respective containers shaderkenrels copute +struct ShaderSpecializationConstants { + first_constant: i32, + second_constant: u32, + third_constant: f32, +} + +unsafe impl SpecializationConstants for ShaderSpecializationConstants { + fn descriptors() -> &'static [SpecializationMapEntry] { + static DESCRIPTORS: [SpecializationMapEntry; 3] = [ + SpecializationMapEntry { + constant_id: 0, + offset: 0, + size: 4, + }, + SpecializationMapEntry { + constant_id: 1, + offset: 4, + size: 4, + }, + SpecializationMapEntry { + constant_id: 2, + offset: 8, + size: 4, + }, + ]; + + &DESCRIPTORS + } } \ No newline at end of file