From 1737319fc572b77dddccd8fbf101534d5000c592 Mon Sep 17 00:00:00 2001 From: mitchellhansen Date: Thu, 29 Aug 2019 21:40:24 -0700 Subject: [PATCH] lots of refactoring --- Cargo.toml | 3 +- src/canvas.rs | 268 ++++++--------- src/canvas_frame.rs | 62 ++++ src/compu_buffer.rs | 99 ++++++ src/compu_frame.rs | 56 ++++ .../compute_kernel.rs => compu_kernel.rs} | 21 +- src/compu_sprite.rs | 64 ++++ src/compu_state.rs | 141 ++++++++ src/compu_wip.rs | 315 ------------------ src/main.rs | 41 ++- src/util/compute_image.rs | 172 ---------- src/util/mod.rs | 46 ++- src/vkprocessor.rs | 33 +- 13 files changed, 627 insertions(+), 694 deletions(-) create mode 100644 src/canvas_frame.rs create mode 100644 src/compu_buffer.rs create mode 100644 src/compu_frame.rs rename src/{util/compute_kernel.rs => compu_kernel.rs} (90%) create mode 100644 src/compu_sprite.rs create mode 100644 src/compu_state.rs delete mode 100644 src/compu_wip.rs delete mode 100644 src/util/compute_image.rs diff --git a/Cargo.toml b/Cargo.toml index cd39eecb..b810d908 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,5 +19,4 @@ time = "0.1.38" shaderc = "0.5.0" #shade_runner = {version = "0.1.1", git = "https://github.com/MitchellHansen/shade_runner"} shade_runner = {path = "../shade_runner"} - -winit = "0.19.1" \ No newline at end of file +winit = "0.19.1" diff --git a/src/canvas.rs b/src/canvas.rs index c9374073..d4782368 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -15,11 +15,12 @@ use vulkano::descriptor::DescriptorSet; use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; use std::path::PathBuf; use image::GenericImageView; -use crate::util::compute_image::ComputeImage; use std::iter::FromIterator; use vulkano::swapchain::Capabilities; use winit::Window; use vulkano::pipeline::viewport::Viewport; +use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer; +use crate::canvas_frame::CanvasFrame; // Canvas is the accumulator of Sprites for drawing @@ -85,87 +86,73 @@ pub enum ShaderType { IMAGE = 2, } -pub struct CanvasFrame { - colored_drawables: Vec, - textured_drawables: HashMap, Vec>>, - image_drawables: HashMap, Vec>>, + +#[derive(Clone)] +pub struct TextureHandle { + handle: u32 } -impl CanvasFrame { +#[derive(Clone)] +pub struct ImageHandle { + handle: u32 +} - pub fn new() -> CanvasFrame { - CanvasFrame { - colored_drawables: vec![], - textured_drawables: Default::default(), - image_drawables: Default::default() - } - } +#[derive(Clone)] +pub struct ShaderHandle { + handle: u32 +} - // Accumulates the drawables vertices and colors - pub fn draw(&mut self, drawable: &dyn Drawable) { - - match drawable.get_texture_handle() { - Some(handle) => { - self.textured_drawables - .entry(handle.clone()) - .or_insert(Vec::new()) - .push(drawable.get_vertices().iter().map(|n| - Vertex2D { - position: [n.0, n.1], - } - ).collect::>()); - } - None => { - - match drawable.get_image_handle() { - - Some(handle) => { - self.image_drawables - .entry(handle.clone()) - .or_insert(Vec::new()) - .push(drawable.get_vertices().iter().map(|n| - Vertex2D { - position: [n.0, n.1], - } - ).collect()); - } - None => { - let colors = drawable.get_color(); - - self.colored_drawables.extend( - drawable.get_vertices().iter().map(|n| - ColoredVertex2D { - position: [n.0, n.1], - color: [colors.0, colors.1, colors.2, colors.3], - } - ) - ); - } - } - } - } - } +#[derive(Clone)] +pub struct CanvasTexture { + handle: Arc, + buffer: Arc>, + name: String, + size: (u32, u32), } +impl CanvasTexture { + fn get_descriptor_set(&mut self, + shader: Arc, + sampler: Arc) -> Box { + let o: Box = Box::new( + PersistentDescriptorSet::start( + shader.clone().get_pipeline().clone(), 0, + ) + .add_sampled_image(self.buffer.clone(), sampler.clone()).unwrap() + .build().unwrap()); + o + } +} #[derive(Clone)] -pub struct Canvas { - shader_kernels: HashMap, +pub struct CanvasImage { + handle: Arc, + buffer: Arc, + size: (u32, u32), +} - texture_store: HashMap>>, +impl CanvasImage { + fn get_descriptor_set(&mut self, shader: Arc) + -> Box { + let o: Box = Box::new( + PersistentDescriptorSet::start( + shader.clone().get_pipeline().clone(), 0, + ) + .add_image(self.buffer.clone()).unwrap() + .build().unwrap()); + o + } +} +#[derive(Clone)] +pub struct CanvasState { dynamic_state: DynamicState, sampler: Arc, // hold the image, texture, and shader buffers the same was as we do CompuState - image_buffers: Vec>, - image_buffer_handles: Vec>, - - texture_buffers: Vec>>, - texture_buffer_handles: Vec>, - - shader_buffers: HashMap, - shader_buffer_handles: Vec>, + image_buffers: Vec>, + texture_buffers: Vec>, + shader_buffers: HashMap, // Hold onto the vertices we get from the Compu and Canvas Frames // When the run comes around, push the vertices to the GPU @@ -184,11 +171,10 @@ pub struct Canvas { } -impl Canvas { - +impl CanvasState { // This method is called once during initialization, then again whenever the window is resized pub fn window_size_dependent_setup(&mut self, images: &[Arc>]) - -> Vec> { + -> Vec> { let dimensions = images[0].dimensions(); self.dynamic_state.viewports = @@ -200,7 +186,7 @@ impl Canvas { images.iter().map(|image| { Arc::new( - Framebuffer::start(self.shader_kernels.get(&ShaderType::SOLID).unwrap().render_pass.clone()) + Framebuffer::start(self.shader_kernels.get(String::from("color-passthrough")).unwrap().render_pass.clone()) .add(image.clone()).unwrap() .build().unwrap() ) as Arc @@ -211,31 +197,24 @@ impl Canvas { pub fn new(queue: Arc, device: Arc, physical: PhysicalDevice, - capabilities: Capabilities) -> Canvas { - + capabilities: Capabilities) -> CanvasState { let solid_color_kernel = String::from("color-passthrough"); let texture_kernel = String::from("simple_texture"); - let shader_kernels : HashMap = HashMap::from_iter(vec![ + let shader_kernels: HashMap = HashMap::from_iter(vec![ (ShaderType::SOLID, ShaderKernels::new(solid_color_kernel, capabilities.clone(), queue.clone(), physical.clone(), device.clone())), (ShaderType::TEXTURED, ShaderKernels::new(texture_kernel, capabilities.clone(), queue.clone(), physical.clone(), device.clone())) ]); - Canvas { - shader_kernels: Default::default(), - texture_store: Default::default(), - + CanvasState { dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None }, sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear, MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(), image_buffers: vec![], - image_buffer_handles: vec![], texture_buffers: vec![], - texture_buffer_handles: vec![], shader_buffers: Default::default(), - shader_buffer_handles: vec![], colored_drawables: vec![], colored_vertex_buffer: vec![], @@ -249,20 +228,24 @@ impl Canvas { } } - pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc { - self.image_buffers.push( - AttachmentImage::with_usage( + pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc { + let image = CanvasImage { + handle: Arc::new(ImageHandle { handle: self.image_buffers.len() as u32 + 1 }), + buffer: AttachmentImage::with_usage( self.device.clone(), [dimensions.0, dimensions.1], Format::R8G8B8A8Uint, - usage).unwrap()); - let id = Arc::new(self.image_buffers.len() as u32); - self.image_buffer_handles.push(id.clone()); - id + usage).unwrap(), + size: dimensions, + }; + let handle = image.handle.clone(); + self.image_buffers.push(Arc::new(image)); + handle } - pub fn get_image(&self, image_handle: Arc) -> std::sync::Arc { - self.image_buffers.get((*image_handle).clone() as usize).unwrap().clone() + pub fn get_image(&self, image_handle: Arc) -> Arc { + self.image_buffers.get((*image_handle).clone() as usize).unwrap() + .clone().buffer.clone() } // TODO Handle file not found gracefully @@ -307,25 +290,24 @@ impl Canvas { texture } - pub fn load_texture_from_filename(&mut self, filename: String) -> Arc> { - if self.texture_store.contains_key(&filename.clone()) { - println!("{} Already exists, not going to replace it.", filename.clone()); - self.texture_store.get(&filename.clone()).unwrap().clone() - } else { - let texture = self.get_texture_from_file(filename.clone()); - self.texture_store.insert(filename, texture.clone()); - texture - } - } - - pub fn load_texture(&mut self, filename: String) -> Option> { + pub fn load_texture(&mut self, filename: String) -> Option> { let texture_buffer = self.get_texture_from_file(filename.clone()); - self.texture_buffers.push(texture_buffer.clone()); - let id = Arc::new(self.texture_buffers.len() as u32); - self.texture_buffer_handles.push(id.clone()); - Some(id) - } + let handle = Arc::new(TextureHandle { + handle: self.texture_buffers.len() as u32 + 1 + }); + + let texture = Arc::new(CanvasTexture { + handle: handle.clone(), + buffer: self.get_texture_from_file(filename.clone()), + name: "".to_string(), + size: (0, 0), + }); + + self.texture_buffers.push(texture); + + Some(handle) + } // After done using this, need to call allocated vertex buffers pub fn draw(&mut self, canvas_frame: CanvasFrame) { @@ -336,26 +318,20 @@ impl Canvas { self.allocate_vertex_buffers(self.device.clone()); } - fn get_texture(&self, texture_id: String) -> Arc> { - if let Some(i) = self.texture_store.get(&texture_id) { - return i.clone(); - } else { - panic!("{} : Texture not loaded", texture_id); - } - } - - pub fn allocate_vertex_buffers(&mut self, device: Arc) { + fn allocate_vertex_buffers(&mut self, device: Arc) { self.colored_vertex_buffer.clear(); self.textured_vertex_buffer.clear(); self.image_vertex_buffer.clear(); - //TODO should probably use cpu accessible buffer instead of recreating immutes each frame -// CpuAccessibleBuffer::from_iter( -// device.clone(), -// BufferUsage::vertex_buffer(), -// self.colored_drawables.iter().cloned(), -// ).unwrap().0; + /* + CpuAccessibleBuffer::from_iter( + + device.clone(), + BufferUsage::vertex_buffer(), + self.colored_drawables.iter().cloned(), + ).unwrap().0; + */ self.colored_vertex_buffer.push( ImmutableBuffer::from_iter( @@ -377,43 +353,21 @@ impl Canvas { } } - fn get_solid_color_descriptor_set(&self) -> Box { - println!("{}", self.shader_kernels.get(&ShaderType::SOLID).unwrap().clone().get_pipeline().clone().num_sets()); - - let o: Box = Box::new( - PersistentDescriptorSet::start( - self.shader_kernels.get(&ShaderType::SOLID).unwrap().clone().get_pipeline().clone(), 0, - ).build().unwrap()); - o + fn get_texture(&self, texture_id: String) -> Arc> { + if let Some(i) = self.texture_store.get(&texture_id) { + return i.clone(); + } else { + panic!("{} : Texture not loaded", texture_id); + } } - fn get_textured_descriptor_set(&self, texture_id: String) - -> Box { - let o: Box = Box::new( - PersistentDescriptorSet::start( - self.shader_kernels.get(&ShaderType::TEXTURED).unwrap().clone().get_pipeline().clone(), 0, - ) - .add_sampled_image(self.get_texture(texture_id), self.sampler.clone()).unwrap() - .build().unwrap()); - o - } - // This is the image which is written to by the write compute buffer - // I suppose I could just have a general image set maker instead of compue... they are - // somewhat similar - fn get_compute_swap_descriptor_set(&mut self, - device: Arc, - compute_image: &ComputeImage) -> Box { - let sampler = Sampler::new(device.clone(), Filter::Linear, Filter::Linear, - MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, - SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(); + fn get_solid_color_descriptor_set(&self, kernel: Arc) -> Box { let o: Box = Box::new( PersistentDescriptorSet::start( - self.shader_kernels.get(&ShaderType::IMAGE).clone().unwrap().clone().get_pipeline(), 0, - ) - .add_image(compute_image.clone().get_swap_buffer().clone()).unwrap() - .build().unwrap()); + kernel.clone().get_pipeline().clone(), 0, + ).build().unwrap()); o } @@ -447,9 +401,7 @@ impl Canvas { // vec![self.get_textured_descriptor_set(String::from("funky-bird.jpg"))], () // ).unwrap(); } - ShaderType::IMAGE => { - - } + ShaderType::IMAGE => {} } } @@ -457,8 +409,6 @@ impl Canvas { .end_render_pass() .unwrap() } - - } diff --git a/src/canvas_frame.rs b/src/canvas_frame.rs new file mode 100644 index 00000000..7fae78f1 --- /dev/null +++ b/src/canvas_frame.rs @@ -0,0 +1,62 @@ +use crate::vertex_2d::{ColoredVertex2D, Vertex2D}; +use std::sync::Arc; +use std::collections::HashMap; +use crate::canvas::Drawable; + +pub struct CanvasFrame { + pub colored_drawables: Vec, + pub textured_drawables: HashMap, Vec>>, + pub image_drawables: HashMap, Vec>>, +} + +impl CanvasFrame { + pub fn new() -> CanvasFrame { + CanvasFrame { + colored_drawables: vec![], + textured_drawables: Default::default(), + image_drawables: Default::default(), + } + } + + // Accumulates the drawables vertices and colors + pub fn draw(&mut self, drawable: &dyn Drawable) { + match drawable.get_texture_handle() { + Some(handle) => { + self.textured_drawables + .entry(handle.clone()) + .or_insert(Vec::new()) + .push(drawable.get_vertices().iter().map(|n| + Vertex2D { + position: [n.0, n.1], + } + ).collect::>()); + } + None => { + match drawable.get_image_handle() { + Some(handle) => { + self.image_drawables + .entry(handle.clone()) + .or_insert(Vec::new()) + .push(drawable.get_vertices().iter().map(|n| + Vertex2D { + position: [n.0, n.1], + } + ).collect()); + } + None => { + let colors = drawable.get_color(); + + self.colored_drawables.extend( + drawable.get_vertices().iter().map(|n| + ColoredVertex2D { + position: [n.0, n.1], + color: [colors.0, colors.1, colors.2, colors.3], + } + ) + ); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/compu_buffer.rs b/src/compu_buffer.rs new file mode 100644 index 00000000..cba128c1 --- /dev/null +++ b/src/compu_buffer.rs @@ -0,0 +1,99 @@ +use std::sync::Arc; +use vulkano::device::Device; +use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage}; +use vulkano::pipeline::ComputePipeline; +use vulkano::descriptor::pipeline_layout::PipelineLayout; +use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; +use image::ImageBuffer; + +#[derive(Clone)] +pub struct CompuBuffers { + dimensions: (u32, u32), + device: Arc, + handle: Arc, + + io_buffers: Vec>>, + settings_buffer: Arc>, +} + +impl CompuBuffers { + pub fn new(device: Arc, data: Vec, + dimensions: (u32, u32), stride: u32, + handle: Arc) -> CompuBuffers { + + let data_length = dimensions.0 * dimensions.1 * stride; + + let input_buffer = { + let mut buff = data.iter(); + let data_iter = (0..data_length).map(|n| *(buff.next().unwrap())); + CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() + }; + + let output_buffer = { + let mut buff = data.iter(); + let data_iter = (0..data_length).map(|n| *(buff.next().unwrap())); + CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() + }; + + // Settings buffer which holds i32's + // Compile macros into the kernel eventually to index them + let settings_buffer = { + let vec = vec![dimensions.0, dimensions.1]; + let mut buff = vec.iter(); + let data_iter = + (0..2).map(|n| *(buff.next().unwrap())); + CpuAccessibleBuffer::from_iter(device.clone(), + BufferUsage::all(), + data_iter).unwrap() + }; + + CompuBuffers { + dimensions: dimensions, + device: device.clone(), + + handle: handle, + io_buffers: vec![input_buffer, output_buffer], + settings_buffer: settings_buffer, + } + } + + pub fn get_size(&self) -> (u32, u32) { + self.dimensions + } + + pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc>>) + -> Arc>>, ((((), + PersistentDescriptorSetBuf>>), + PersistentDescriptorSetBuf>>), + PersistentDescriptorSetBuf>>)>> { + Arc::new(PersistentDescriptorSet::start(compute_pipeline.clone(), 0) + .add_buffer(self.io_buffers.get(0).unwrap().clone()).unwrap() + .add_buffer(self.io_buffers.get(1).unwrap().clone()).unwrap() + .add_buffer(self.settings_buffer.clone()).unwrap() + .build().unwrap()) + } + + pub fn read_output_buffer(&self) -> ImageBuffer, Vec> { + let xy = self.get_size(); + + self.io_buffers.get(1).unwrap().write().unwrap().map(|x| x); + let data_buffer_content = self.io_buffers.get(1).unwrap().read().unwrap(); + 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]) + }) + } +} + +#[derive(Clone)] +pub struct CompuBufferHandle { + handle: u32, +} +#[derive(Clone)] +pub struct CompuKernelHandle { + handle: u32, +} \ No newline at end of file diff --git a/src/compu_frame.rs b/src/compu_frame.rs new file mode 100644 index 00000000..6dd74fa8 --- /dev/null +++ b/src/compu_frame.rs @@ -0,0 +1,56 @@ +use crate::canvas::ImageHandle; +use std::sync::Arc; +use crate::compu_sprite::CompuSprite; +use crate::compu_buffer::{CompuBufferHandle, CompuKernelHandle}; + +pub struct CompuFrame { + // Vec<(Buffer, Kernel)> + pure_compute: Vec<( + Arc, + Arc)>, + + // Vec<(Buffer, Image, Kernel)> + swapped_to_image: Vec<( + Arc, + Arc, + Arc)>, + + // Vec<(Input Buffer, Output Buffer, Kernel)> + swapped_to_buffer: Vec<( + Arc, + Arc, + Arc)>, +} + +impl CompuFrame { + pub fn new() -> CompuFrame { + CompuFrame { + pure_compute: vec![], + swapped_to_image: vec![], + swapped_to_buffer: vec![], + } + } + + pub fn add(&mut self, buffer: Arc, kernel: Arc) { + self.pure_compute.push((buffer, kernel)); + } + + /* + INPUT_BUFFER -> input -> kernel -> output + v------------------^ + OUTPUT_BUFFER -> input X kernel X output + */ + pub fn add_chained(&mut self, + input_buffer: Arc, + output_buffer: Arc, + kernel: Arc) { + self.swapped_to_buffer.push((input_buffer, output_buffer, kernel)); + } + + pub fn add_with_image_swap(&mut self, + buffer: Arc, + kernel: Arc, + sprite: &CompuSprite) { + self.swapped_to_image.push((buffer, sprite.get_image_handle().clone(), kernel)) + } +} \ No newline at end of file diff --git a/src/util/compute_kernel.rs b/src/compu_kernel.rs similarity index 90% rename from src/util/compute_kernel.rs rename to src/compu_kernel.rs index f2c5d4d8..16f8ae1c 100644 --- a/src/util/compute_kernel.rs +++ b/src/compu_kernel.rs @@ -8,9 +8,13 @@ use vulkano::descriptor::pipeline_layout::PipelineLayout; use shade_runner::{CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout, CompiledShaders, Entry}; use shaderc::CompileOptions; use vulkano::pipeline::shader::{ShaderModule, GraphicsEntryPoint, SpecializationConstants, SpecializationMapEntry}; +use crate::compu_buffer::CompuKernelHandle; + #[derive(Clone)] -pub struct ComputeKernel { +pub struct CompuKernel { + + handle: Arc, compute_pipeline: Option>>>, compute_kernel_path: PathBuf, @@ -22,7 +26,7 @@ pub struct ComputeKernel { specialization_constants: ComputeSpecializationConstants, } -impl ComputeKernel { +impl CompuKernel { fn get_path(filename: String) -> PathBuf { @@ -37,9 +41,10 @@ impl ComputeKernel { compute_path } - pub fn new(filename: String, device: Arc) -> ComputeKernel { + pub fn new(filename: String, device: Arc, + handle: Arc) -> CompuKernel { - let compute_path = ComputeKernel::get_path(filename); + let compute_path = CompuKernel::get_path(filename); let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap(); @@ -54,7 +59,8 @@ impl ComputeKernel { }.unwrap(); - ComputeKernel { + CompuKernel { + handle: handle, device: device, shader: shader, compute_pipeline: Option::None, @@ -94,7 +100,7 @@ impl ComputeKernel { 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.compute_kernel_path = CompuKernel::get_path(filename); self.shader = sr::load_compute_with_options(self.compute_kernel_path.clone(), options) @@ -112,10 +118,9 @@ impl ComputeKernel { } } - #[repr(C)] #[derive(Default, Debug, Clone)] -struct ComputeSpecializationConstants { +pub struct ComputeSpecializationConstants { first_constant: i32, second_constant: u32, third_constant: f32, diff --git a/src/compu_sprite.rs b/src/compu_sprite.rs new file mode 100644 index 00000000..7ab7ef98 --- /dev/null +++ b/src/compu_sprite.rs @@ -0,0 +1,64 @@ +use crate::canvas::{ImageHandle, Drawable, TextureHandle}; +use std::sync::Arc; + +pub struct CompuSprite { + vertices: [(f32, f32); 6], + position: (f32, f32), + size: (f32, f32), + color: (f32, f32, f32, f32), + image_handle: Arc, +} + +impl Drawable for CompuSprite { + fn get_vertices(&self) -> Vec<(f32, f32)> { + self.vertices.to_vec() + } + + fn get_color(&self) -> (f32, f32, f32, f32) { + self.color + } + + fn get_texture_handle(&self) -> Option> { + None + } + + fn get_image_handle(&self) -> Option> { + Some(self.image_handle.clone()) + } +} + +impl CompuSprite { + pub fn new(position: (f32, f32), + size: (f32, f32), + image_handle: Arc) -> CompuSprite { + let fsize = (size.0 as f32, size.1 as f32); + + CompuSprite { + vertices: [ + (position.0, position.1), // top left + (position.0, position.1 + fsize.1), // bottom left + (position.0 + fsize.0, position.1 + fsize.1), // bottom right + (position.0, position.1), // top left + (position.0 + fsize.0, position.1 + fsize.1), // bottom right + (position.0 + fsize.0, position.1), // top right + ], + + position: position, + size: size, + color: (0.0, 0.0, 0.0, 0.0), + image_handle: image_handle.clone(), + } + } + + fn get_vertices(&self) -> Vec<(f32, f32)> { + self.vertices.to_vec() + } + + fn get_color(&self) -> (f32, f32, f32, f32) { + self.color.clone() + } + + fn get_image_handle(&self) -> Arc { + self.image_handle.clone() + } +} \ No newline at end of file diff --git a/src/compu_state.rs b/src/compu_state.rs new file mode 100644 index 00000000..ffd32268 --- /dev/null +++ b/src/compu_state.rs @@ -0,0 +1,141 @@ +use std::ffi::CStr; +use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage}; +use std::sync::Arc; +use crate::canvas::{Drawable, CanvasState, ImageHandle, CanvasImage, TextureHandle}; +use vulkano::framebuffer::RenderPassAbstract; +use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline}; +use vulkano::device::Device; +use image::ImageBuffer; +use image::GenericImageView; +use vulkano::image::{ImageUsage, AttachmentImage}; +use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSet}; +use vulkano::format::Format; +use vulkano::descriptor::pipeline_layout::PipelineLayout; +use std::borrow::Borrow; +use image::Rgba; +use vulkano::command_buffer::AutoCommandBufferBuilder; +use std::path::PathBuf; +use shade_runner::{CompiledShaders, Entry, CompileError}; +use vulkano::pipeline::shader::ShaderModule; +use shaderc::CompileOptions; +use crate::compu_kernel::CompuKernel; +use crate::compu_buffer::{CompuBuffers, CompuBufferHandle, CompuKernelHandle}; +use crate::compu_frame::CompuFrame; + + +// Canvas analog +pub struct CompuState { + compute_buffers: Vec, + kernels: Vec, +} + +impl CompuState { + pub fn new() -> CompuState { + CompuState { + compute_buffers: vec![], + kernels: vec![], + } + } + + pub fn new_compute_buffer(&mut self, + data: Vec, + dimensions: (u32, u32), + stride: u32, + device: Arc) -> Arc { + + let handle = Arc::new(CompuBufferHandle { + handle: self.compute_buffers.len() as u32 + 1 + }); + + self.compute_buffers.push( + CompuBuffers::new(device.clone(), data, dimensions, stride, handle.clone())); + + handle + } + + pub fn read_compute_buffer(&mut self, handle: Arc) -> Vec { + // This is way more difficult than it should be + //let compute_buffer : CompuBuffers = self.compute_buffers.get(handle.into()).unwrap(); + //compute_buffer.read_output_buffer().to_vec() + Vec::new() + } + pub fn write_compute_buffer(&self, handle: Arc, data: Vec) {} + + pub fn new_kernel(&mut self, + filename: String, + device: &Arc) -> Arc { + + let handle = Arc::new(CompuKernelHandle { + handle: self.kernels.len() as u32 + 1 + }); + + self.kernels.push(CompuKernel::new(filename, device.clone(), handle.clone())); + + handle + } + + pub fn compute_commands(&mut self, + compute_frame: CompuFrame, + mut command_buffer: AutoCommandBufferBuilder, + canvas: &CanvasState) + -> AutoCommandBufferBuilder { + + // i = (Buffer, Kernel) + for i in compute_frame.pure_compute { + let buffer_id = (*i.0).clone() as usize; + let kernel_id = (*i.1).clone() as usize; + + let buffer = self.compute_buffers.get(buffer_id).unwrap(); + let kernel = self.kernels.get(buffer_id).unwrap(); + + let p = kernel.clone().get_pipeline(); + let d = buffer.get_descriptor_set(kernel.clone().get_pipeline()); + + command_buffer = command_buffer + .dispatch([100,100,1], p, d, ()).unwrap() + } + + // i = (Buffer, Image, Kernel) + for i in compute_frame.swapped_to_image { + let buffer_id = (*i.0).clone() as usize; + let image_id = i.1.clone(); + let kernel_id = (*i.2).clone() as usize; + + let buffer = self.compute_buffers.get(buffer_id).unwrap(); + let image = canvas.get_image(image_id); + let kernel = self.kernels.get(buffer_id).unwrap(); + + let p = kernel.clone().get_pipeline(); + let d = buffer.get_descriptor_set(kernel.clone().get_pipeline()); + + command_buffer = command_buffer + .dispatch([100,100,1], p, d, ()).unwrap() + .copy_buffer_to_image(buffer.io_buffers.get(0).unwrap().clone(), image).unwrap(); + } + + + // i = (Input Buffer, Output Buffer, Kernel) + // Input buffer -> Kernel -> Output buffer + for i in compute_frame.swapped_to_buffer { + let input_buffer_id = (*i.0).clone() as usize; + let output_buffer_id = (*i.1).clone() as usize; + let kernel_id = (*i.2).clone() as usize; + + let input_buffer = self.compute_buffers.get(input_buffer_id).unwrap(); + let output_buffer = self.compute_buffers.get(output_buffer_id).unwrap(); + let kernel = self.kernels.get(kernel_id).unwrap(); + + let pipeline = kernel.clone().get_pipeline(); + let descriptor_set = input_buffer.get_descriptor_set(kernel.clone().get_pipeline()); + + command_buffer = command_buffer + .dispatch([100,100,1], pipeline, descriptor_set, ()).unwrap() + .copy_buffer( + input_buffer.io_buffers.get(1).unwrap().clone(), + output_buffer.io_buffers.get(0).unwrap().clone()).unwrap(); + } + + command_buffer + } +} + diff --git a/src/compu_wip.rs b/src/compu_wip.rs deleted file mode 100644 index 5c3db7e9..00000000 --- a/src/compu_wip.rs +++ /dev/null @@ -1,315 +0,0 @@ -use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage}; -use std::sync::Arc; -use crate::canvas::{Drawable, Canvas}; -use vulkano::framebuffer::RenderPassAbstract; -use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline}; -use vulkano::device::Device; -use crate::util::compute_kernel::ComputeKernel; -use image::ImageBuffer; -use image::GenericImageView; -use crate::util::compute_image::ComputeImage; -use vulkano::image::{ImageUsage, AttachmentImage}; -use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSet}; -use vulkano::format::Format; -use vulkano::descriptor::pipeline_layout::PipelineLayout; -use std::borrow::Borrow; -use image::Rgba; -use vulkano::command_buffer::AutoCommandBufferBuilder; - -pub struct CompuSprite { - vertices: [(f32, f32); 6], - position: (f32, f32), - size: (f32, f32), - color: (f32, f32, f32, f32), - image_handle: Arc, -} - -impl Drawable for CompuSprite { - fn get_vertices(&self) -> Vec<(f32, f32)> { - self.vertices.to_vec() - } - - fn get_color(&self) -> (f32, f32, f32, f32) { - self.color - } - - fn get_texture_handle(&self) -> Option> { - None - } - - fn get_image_handle(&self) -> Option> { - Some(self.image_handle.clone()) - } -} - -impl CompuSprite { - pub fn new(position: (f32, f32), - size: (f32, f32), - image_handle: Arc) -> CompuSprite { - let fsize = (size.0 as f32, size.1 as f32); - - CompuSprite { - vertices: [ - (position.0, position.1), // top left - (position.0, position.1 + fsize.1), // bottom left - (position.0 + fsize.0, position.1 + fsize.1), // bottom right - (position.0, position.1), // top left - (position.0 + fsize.0, position.1 + fsize.1), // bottom right - (position.0 + fsize.0, position.1), // top right - ], - - position: position, - size: size, - color: (0.0, 0.0, 0.0, 0.0), - image_handle: image_handle.clone(), - } - } - - fn get_vertices(&self) -> Vec<(f32, f32)> { - self.vertices.to_vec() - } - - fn get_color(&self) -> (f32, f32, f32, f32) { - self.color.clone() - } - - fn get_image_handle(&self) -> Arc { - self.image_handle.clone() - } -} - -#[derive(Clone)] -pub struct CompuBuffers { - dimensions: (u32, u32), - device: Arc, - - io_buffers: Vec>>, - settings_buffer: Arc>, -} - -impl CompuBuffers { - pub fn new(device: Arc, data: Vec, dimensions: (u32, u32), stride: u32) -> CompuBuffers { - let data_length = dimensions.0 * dimensions.1 * stride; - - let input_buffer = { - let mut buff = data.iter(); - let data_iter = (0..data_length).map(|n| *(buff.next().unwrap())); - CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() - }; - - let output_buffer = { - let mut buff = data.iter(); - let data_iter = (0..data_length).map(|n| *(buff.next().unwrap())); - CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() - }; - - // Settings buffer which holds i32's - // Compile macros into the kernel eventually to index them - let settings_buffer = { - let vec = vec![dimensions.0, dimensions.1]; - let mut buff = vec.iter(); - let data_iter = - (0..2).map(|n| *(buff.next().unwrap())); - CpuAccessibleBuffer::from_iter(device.clone(), - BufferUsage::all(), - data_iter).unwrap() - }; - - CompuBuffers { - dimensions: dimensions, - device: device.clone(), - - io_buffers: vec![input_buffer, output_buffer], - settings_buffer: settings_buffer, - } - } - - pub fn get_size(&self) -> (u32, u32) { - self.dimensions - } - - pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc>>) - -> Arc>>, ((((), - PersistentDescriptorSetBuf>>), - PersistentDescriptorSetBuf>>), - PersistentDescriptorSetBuf>>)>> { - Arc::new(PersistentDescriptorSet::start(compute_pipeline.clone(), 0) - .add_buffer(self.io_buffers.get(0).unwrap().clone()).unwrap() - .add_buffer(self.io_buffers.get(1).unwrap().clone()).unwrap() - .add_buffer(self.settings_buffer.clone()).unwrap() - .build().unwrap()) - } - - pub fn read_output_buffer(&self) -> ImageBuffer, Vec> { - let xy = self.get_size(); - - self.io_buffers.get(1).unwrap().write().unwrap().map(|x| x); - let data_buffer_content = self.io_buffers.get(1).unwrap().read().unwrap(); - 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]) - }) - } -} - -// Canvas analog -pub struct CompuState { - compute_buffers: Vec, - compute_buffer_handles: Vec>, - - kernels: Vec, - kernel_handles: Vec>, -} - -impl CompuState { - pub fn new() -> CompuState { - CompuState { - compute_buffers: vec![], - compute_buffer_handles: vec![], - kernels: vec![], - kernel_handles: vec![], - } - } - - pub fn new_compute_buffer(&mut self, - data: Vec, - dimensions: (u32, u32), - stride: u32, - device: Arc) -> Arc { - self.compute_buffers.push( - CompuBuffers::new(device.clone(), data, dimensions, stride)); - - let id = Arc::new(self.compute_buffers.len() as u32); - self.compute_buffer_handles.push(id.clone()); - id - } - - pub fn read_compute_buffer(&mut self, handle: Arc) -> Vec { - // This is way more difficult than it should be - //let compute_buffer : CompuBuffers = self.compute_buffers.get(handle.into()).unwrap(); - //compute_buffer.read_output_buffer().to_vec() - Vec::new() - } - pub fn write_compute_buffer(&self, handle: Arc, data: Vec) {} - - pub fn new_kernel(&mut self, - filename: String, - device: &Arc) -> Arc { - let kernel = ComputeKernel::new(filename, device.clone()); - - self.kernels.push(kernel); - - let id = Arc::new(self.kernels.len() as u32); - - self.kernel_handles.push(id.clone()); - - id - } - - pub fn compute_commands(&mut self, - compute_frame: ComputeFrame, - mut command_buffer: AutoCommandBufferBuilder, - canvas: &Canvas) - -> AutoCommandBufferBuilder { - - // i = (Buffer, Kernel) - for i in compute_frame.pure_compute { - let buffer_id = (*i.0).clone() as usize; - let kernel_id = (*i.1).clone() as usize; - - let buffer = self.compute_buffers.get(buffer_id).unwrap(); - let kernel = self.kernels.get(buffer_id).unwrap(); - - let p = kernel.clone().get_pipeline(); - let d = buffer.get_descriptor_set(kernel.clone().get_pipeline()); - - command_buffer = command_buffer - .dispatch([100,100,1], p, d, ()).unwrap() - } - - // i = (Buffer, Image, Kernel) - for i in compute_frame.swapped_to_image { - let buffer_id = (*i.0).clone() as usize; - let image_id = i.1.clone(); - let kernel_id = (*i.2).clone() as usize; - - let buffer = self.compute_buffers.get(buffer_id).unwrap(); - let image = canvas.get_image(image_id); - let kernel = self.kernels.get(buffer_id).unwrap(); - - let p = kernel.clone().get_pipeline(); - let d = buffer.get_descriptor_set(kernel.clone().get_pipeline()); - - command_buffer = command_buffer - .dispatch([100,100,1], p, d, ()).unwrap() - .copy_buffer_to_image(buffer.io_buffers.get(0).unwrap().clone(), image).unwrap(); - } - - - // i = (Input Buffer, Output Buffer, Kernel) - // Input buffer -> Kernel -> Output buffer - for i in compute_frame.swapped_to_buffer { - let input_buffer_id = (*i.0).clone() as usize; - let output_buffer_id = (*i.1).clone() as usize; - let kernel_id = (*i.2).clone() as usize; - - let input_buffer = self.compute_buffers.get(input_buffer_id).unwrap(); - let output_buffer = self.compute_buffers.get(output_buffer_id).unwrap(); - let kernel = self.kernels.get(kernel_id).unwrap(); - - let pipeline = kernel.clone().get_pipeline(); - let descriptor_set = input_buffer.get_descriptor_set(kernel.clone().get_pipeline()); - - command_buffer = command_buffer - .dispatch([100,100,1], pipeline, descriptor_set, ()).unwrap() - .copy_buffer( - input_buffer.io_buffers.get(1).unwrap().clone(), - output_buffer.io_buffers.get(0).unwrap().clone()).unwrap(); - } - - command_buffer - } -} - - -pub struct ComputeFrame { - // Vec<(Buffer, Kernel)> - pure_compute: Vec<(Arc, Arc)>, - - // Vec<(Buffer, Image, Kernel)> - swapped_to_image: Vec<(Arc, Arc, Arc)>, - - // Vec<(Input Buffer, Output Buffer, Kernel)> - swapped_to_buffer: Vec<(Arc, Arc, Arc)>, -} - -impl ComputeFrame { - pub fn new() -> ComputeFrame { - ComputeFrame { - pure_compute: vec![], - swapped_to_image: vec![], - swapped_to_buffer: vec![], - } - } - - pub fn add(&mut self, buffer: Arc, kernel: Arc) { - self.pure_compute.push((buffer, kernel)); - } - - /* - INPUT_BUFFER -> input -> kernel -> output - v------------------^ - OUTPUT_BUFFER -> input X kernel X output - */ - pub fn add_chained(&mut self, input_buffer: Arc, output_buffer: Arc, kernel: Arc) { - self.swapped_to_buffer.push((input_buffer, output_buffer, kernel)); - } - - pub fn add_with_image_swap(&mut self, buffer: Arc, kernel: Arc, sprite: &CompuSprite) { - self.swapped_to_image.push((buffer, sprite.get_image_handle().clone(), kernel)) - } -} diff --git a/src/main.rs b/src/main.rs index 2a22204e..3068451c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,9 +19,13 @@ use winit::{EventsLoop, WindowBuilder, WindowEvent, Event, DeviceEvent, VirtualK use winit::dpi::LogicalSize; use vulkano_win::VkSurfaceBuild; use sprite::Sprite; -use crate::canvas::CanvasFrame; -use crate::compu_wip::{CompuSprite, ComputeFrame, CompuBuffers, CompuState}; -use crate::util::compute_image::ComputeImage; +use crate::canvas::{CanvasFrame, CanvasImage}; +use crate::compu_state::CompuState; +use crate::compu_frame::CompuFrame; +use crate::compu_sprite::CompuSprite; +use crate::compu_kernel::CompuKernel; +use crate::compu_buffer::CompuBuffers; +use crate::util::load_raw; mod util; mod slider; @@ -33,7 +37,12 @@ mod vertex_2d; mod vertex_3d; mod sprite; mod canvas; -mod compu_wip; +mod canvas_frame; +mod compu_state; +mod compu_frame; +mod compu_sprite; +mod compu_kernel; +mod compu_buffer; /* @@ -174,7 +183,6 @@ vkprocessor.run(CanvasFrame, CompuFrame) */ - fn main() { let instance = { @@ -211,23 +219,22 @@ fn main() { let sprite = Sprite::new_with_color((0.,0.), (0.1,0.1), (1.,0.,0.,1.)); let sprite2 = Sprite::new_with_color((-1.,-0.5), (0.1,0.1), (0.,1.,0.,1.)); - /* - I need to get the image id from the CompuState - But the CompuState is owned by the vkprocessor I think... - - I will also need to get the texture id - */ - - - let compu_sprite1 = CompuSprite::new((-1.,-0.5), (0.1,0.1), processor.new_swap_image((300, 300))); - let image_data = ComputeImage::load_raw(String::from("funky-bird.jpg")); + let image_data = load_raw(String::from("funky-bird.jpg")); let compute_buffer = processor.new_compute_buffer(image_data.0, image_data.1, 4); + + // TODO need to implement let compute_kernel = processor.get_kernel_handle(String::from("simple-edge.compute")) .expect("Can't find that kernel"); - + + + + + + + while let Some(p) = window.get_position() { @@ -278,7 +285,7 @@ fn main() { return; } - let mut compu_frame = ComputeFrame::new(); + let mut compu_frame = CompuFrame::new(); compu_frame.add(compute_buffer.clone(), compute_kernel.clone()); compu_frame.add_with_image_swap(compute_buffer.clone(), compute_kernel.clone(), &compu_sprite1); diff --git a/src/util/compute_image.rs b/src/util/compute_image.rs deleted file mode 100644 index 2a76bf78..00000000 --- a/src/util/compute_image.rs +++ /dev/null @@ -1,172 +0,0 @@ -use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer}; -use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet}; -use vulkano::device::{Device}; -use vulkano::pipeline::{ComputePipeline}; -use std::time::SystemTime; -use std::sync::Arc; -use std::path::PathBuf; -use image::{ImageBuffer}; -use image::GenericImageView; -use vulkano::descriptor::pipeline_layout::PipelineLayout; -use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf}; -use vulkano::image::attachment::AttachmentImage; -use vulkano::image::{ImageUsage}; -use vulkano::format::Format; -use image::Rgba; - -/* - -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 { - - device: Arc, - - compute_graphics_swap_buffer: std::sync::Arc, - - pub rw_buffers: Vec>>, - pub settings_buffer: Arc>, -} - - -impl ComputeImage { - - pub fn load_raw(filename: String) -> (Vec, (u32,u32)) { - - 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(filename.clone())); - - let img = image::open(compute_path).expect("Couldn't find image"); - - let xy = img.dimensions(); - - let data_length = xy.0 * xy.1 * 4; - let pixel_count = img.raw_pixels().len(); - - let mut image_buffer = Vec::new(); - - if pixel_count != data_length as usize { - println!("Creating apha channel..."); - for i in img.raw_pixels().iter() { - if (image_buffer.len() + 1) % 4 == 0 { - image_buffer.push(255); - } - image_buffer.push(*i); - } - image_buffer.push(255); - } else { - image_buffer = img.raw_pixels(); - } - - (image_buffer, xy) - } - - pub fn new(device: Arc, image_filename: String) -> ComputeImage { - - let (image_buffer, xy) = ComputeImage::load_raw(image_filename); - - let compute_graphics_swap_buffer = { - - let mut usage = ImageUsage::none(); - usage.transfer_destination = true; - usage.storage = true; - - AttachmentImage::with_usage( - device.clone(), - [xy.0, xy.1], - Format::R8G8B8A8Uint, - usage) - }; - - let data_length = xy.0 * xy.1 * 4; - - // Pull out the image data and place it in a buffer for the kernel to write to and for us to read from - let write_buffer = { - let mut buff = image_buffer.iter(); - let data_iter = (0..data_length).map(|n| *(buff.next().unwrap())); - CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() - }; - - - // Pull out the image data and place it in a buffer for the kernel to read from - let read_buffer = { - let mut buff = image_buffer.iter(); - let data_iter = (0..data_length).map(|n| *(buff.next().unwrap())); - CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() - }; - - - // A buffer to hold many i32 values to use as settings - let settings_buffer = { - let vec = vec![xy.0, xy.1]; - let mut buff = vec.iter(); - let data_iter = - (0..2).map(|n| *(buff.next().unwrap())); - CpuAccessibleBuffer::from_iter(device.clone(), - BufferUsage::all(), - data_iter).unwrap() - }; - - ComputeImage{ - device: device.clone(), - compute_graphics_swap_buffer: compute_graphics_swap_buffer.unwrap(), - - rw_buffers: vec![write_buffer, read_buffer], - settings_buffer: settings_buffer - } - } - - pub fn get_swap_buffer(&mut self) -> Arc { - 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(); - - self.rw_buffers.get(0).unwrap().write().unwrap().map(|x| x); - let data_buffer_content = self.rw_buffers.get(0).unwrap().read().unwrap(); - 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]) - }) - } - - pub fn save_image(&self) { - self.read_read_buffer().save(format!("output/{}.jpg", SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs())); - } - - pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc>>) - -> Arc>>, ((((), - PersistentDescriptorSetBuf>>), - PersistentDescriptorSetBuf>>), - PersistentDescriptorSetBuf>>)>> { - - Arc::new(PersistentDescriptorSet::start(compute_pipeline.clone(), 0) - .add_buffer(self.rw_buffers.get(0).unwrap().clone()).unwrap() - .add_buffer(self.rw_buffers.get(1).unwrap().clone()).unwrap() - .add_buffer(self.settings_buffer.clone()).unwrap() - .build().unwrap()) - } -} \ No newline at end of file diff --git a/src/util/mod.rs b/src/util/mod.rs index b9d1e648..04c31575 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,3 +1,43 @@ -pub mod compute_image; -pub mod compute_kernel; -pub mod shader_kernels; \ No newline at end of file +use image::GenericImageView; +use std::sync::Arc; +use std::ffi::CStr; +use std::path::PathBuf; + +pub mod shader_kernels; + + + +pub fn load_raw(filename: String) -> (Vec, (u32,u32)) { + + 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(filename.clone())); + + let img = image::open(compute_path).expect("Couldn't find image"); + + let xy = img.dimensions(); + + let data_length = xy.0 * xy.1 * 4; + let pixel_count = img.raw_pixels().len(); + + let mut image_buffer = Vec::new(); + + if pixel_count != data_length as usize { + println!("Creating apha channel..."); + for i in img.raw_pixels().iter() { + if (image_buffer.len() + 1) % 4 == 0 { + image_buffer.push(255); + } + image_buffer.push(*i); + } + image_buffer.push(255); + } else { + image_buffer = img.raw_pixels(); + } + + (image_buffer, xy) +} \ No newline at end of file diff --git a/src/vkprocessor.rs b/src/vkprocessor.rs index 3fc5c35b..380bc988 100644 --- a/src/vkprocessor.rs +++ b/src/vkprocessor.rs @@ -7,11 +7,11 @@ use std::sync::Arc; use vulkano::swapchain::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError, Capabilities}; use vulkano::image::swapchain::SwapchainImage; use winit::{Window}; -use crate::util::compute_kernel::ComputeKernel; -use crate::util::compute_image::ComputeImage; -use crate::canvas::{Canvas, CanvasFrame}; -use crate::compu_wip::{CompuState, ComputeFrame}; +use crate::canvas::{CanvasState, CanvasFrame, ImageHandle}; +use crate::compu_state::CompuState; use vulkano::image::ImageUsage; +use crate::compu_buffer::CompuBufferHandle; +use crate::compu_frame::CompuFrame; pub struct VkProcessor<'a> { @@ -23,9 +23,6 @@ pub struct VkProcessor<'a> { pub queue: Arc, pub dynamic_state: DynamicState, - pub compute_kernel: Option, - pub compute_image: Option, - pub swapchain: Option>>, pub swapchain_images: Option>>>, @@ -34,7 +31,7 @@ pub struct VkProcessor<'a> { compute_state: CompuState, capabilities: Capabilities, - canvas: Canvas, + canvas: CanvasState, } @@ -74,7 +71,7 @@ impl<'a> VkProcessor<'a> { swapchain_recreate_needed: false, compute_state: CompuState::new(), capabilities: capabilities.clone(), - canvas: Canvas::new(queue, device, physical, capabilities), + canvas: CanvasState::new(queue, device, physical, capabilities), } } @@ -155,7 +152,7 @@ impl<'a> VkProcessor<'a> { } // Create a new image which has the transfer usage - pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc { + pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc { let mut usage = ImageUsage::none(); usage.transfer_destination = true; usage.storage = true; @@ -163,25 +160,25 @@ impl<'a> VkProcessor<'a> { self.canvas.create_image(dimensions, usage) } - pub fn new_compute_buffer(&mut self, data: Vec, dimensions: (u32, u32), stride: u32) -> Arc { + pub fn new_compute_buffer(&mut self, data: Vec, dimensions: (u32, u32), stride: u32) -> Arc { self.compute_state.new_compute_buffer(data, dimensions, stride, self.device.clone()) } - pub fn read_compute_buffer(&mut self, handle: Arc) -> Vec { + pub fn read_compute_buffer(&mut self, handle: Arc) -> Vec { self.compute_state.read_compute_buffer(handle) } - pub fn write_compute_buffer(&self, handle: Arc, data: Vec) { + pub fn write_compute_buffer(&self, handle: Arc, data: Vec) { self.compute_state.write_compute_buffer(handle, data) } pub fn run(&mut self, - surface: &'a Arc>, - mut frame_future: Box, - canvas_frame: CanvasFrame, - compute_frame: ComputeFrame, + surface: &'a Arc>, + mut frame_future: Box, + canvas_frame: CanvasFrame, + compute_frame: CompuFrame, ) - -> Box { + -> Box { // take the canvas frame and create the vertex buffers // TODO: This performs gpu buffer creation. Shouldn't be in hotpath