diff --git a/src/canvas.rs b/src/canvas.rs index 4ce939f9..245cfa86 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -9,7 +9,7 @@ use vulkano::device::{Device, Queue}; use vulkano::instance::PhysicalDevice; use vulkano::image::immutable::ImmutableImage; use crate::util::shader_kernels::ShaderKernels; -use vulkano::image::{Dimensions, ImageAccess, ImageDimensions, SwapchainImage}; +use vulkano::image::{Dimensions, ImageAccess, ImageDimensions, SwapchainImage, ImageUsage, AttachmentImage}; use vulkano::sampler::{Sampler, SamplerAddressMode, MipmapMode, Filter}; use vulkano::descriptor::DescriptorSet; use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; @@ -82,7 +82,8 @@ impl Vertex for ColoredVertex2D { pub trait Drawable { fn get_vertices(&self) -> Vec<(f32, f32)>; fn get_color(&self) -> (f32, f32, f32, f32); - fn get_texture_id(&self) -> Option; + fn get_texture_handle(&self) -> Option>; + fn get_image_handle(&self) -> Option>; } // Need three types of shaders. Solid, Textured, Compute @@ -95,7 +96,7 @@ pub enum ShaderType { pub struct CanvasFrame { colored_drawables : Vec, - textured_drawables: HashMap>, + textured_drawables: HashMap, Vec>, } impl CanvasFrame { @@ -110,10 +111,10 @@ impl CanvasFrame { // After done using this, need to call allocated vertex buffers pub fn draw(&mut self, drawable: &dyn Drawable) { - match drawable.get_texture_id() { + match drawable.get_texture_handle() { Some(id) => { self.textured_drawables - .entry(id) + .entry(id.clone()) .or_insert(Vec::new()) .extend(drawable.get_vertices().iter().map(|n| Vertex2D { @@ -145,8 +146,8 @@ pub struct Canvas { colored_drawables : Vec, colored_vertex_buffer: Vec>, - textured_drawables: HashMap>, - textured_vertex_buffer: HashMap>, + textured_drawables: HashMap, Vec>, + textured_vertex_buffer: HashMap, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>, shader_kernels: HashMap, @@ -154,9 +155,13 @@ pub struct Canvas { dynamic_state: DynamicState, + image_buffers: Vec>, + image_buffer_handles: Vec>, + // Looks like we gotta hold onto the queue for managing textures queue: Arc, - sampler: Arc + sampler: Arc, + device: Arc, } @@ -177,6 +182,7 @@ impl Canvas { ]); Canvas { + colored_drawables: vec![], colored_vertex_buffer: vec![], @@ -188,6 +194,10 @@ impl Canvas { dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None }, + image_buffers: Vec::new(), + image_buffer_handles: Vec::new(), + + device: device.clone(), queue: queue.clone(), sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear, MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, @@ -196,6 +206,18 @@ impl Canvas { } } + pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc { + self.image_buffers.push( + 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 + } + // TODO Handle file not found gracefully fn get_texture_from_file(&self, image_filename: String) -> Arc> { diff --git a/src/compu_wip.rs b/src/compu_wip.rs index e4908260..4a3c0b75 100644 --- a/src/compu_wip.rs +++ b/src/compu_wip.rs @@ -5,14 +5,15 @@ use vulkano::framebuffer::RenderPassAbstract; use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline}; use vulkano::device::Device; use crate::util::compute_kernel::ComputeKernel; -use image::{ImageBuffer}; +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; pub struct CompuSprite { vertices: [(f32, f32); 6], @@ -22,28 +23,44 @@ pub struct CompuSprite { image_handle: Arc, } -impl CompuSprite { +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.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() + color: (0.0, 0.0, 0.0, 0.0), + image_handle: image_handle.clone(), } } @@ -60,7 +77,7 @@ impl CompuSprite { } } - +#[derive(Clone)] pub struct CompuBuffers { dimensions: (u32, u32), device: Arc, @@ -72,7 +89,6 @@ pub struct CompuBuffers { 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 = { @@ -99,33 +115,46 @@ impl CompuBuffers { data_iter).unwrap() }; - CompuBuffers{ + CompuBuffers { dimensions: dimensions, device: device.clone(), io_buffers: vec![input_buffer, output_buffer], - settings_buffer: settings_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>>)>> { - + 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 @@ -138,14 +167,42 @@ pub struct CompuState { } impl CompuState { - fn new_compute_buffer() -> Arc { + pub fn new() -> CompuState { + CompuState { + compute_buffers: vec![], + compute_buffer_handles: vec![], + kernels: vec![], + kernel_handles: vec![], + } } - fn new_kernel(&mut self, - filename: String, - device: &Arc) -> Arc { + 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); @@ -168,17 +225,39 @@ impl CompuState { It will need to convert these into a logical list of command_buffer commands */ 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 { - fn add() { + 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)); } - fn add_chained(output_buffer_id: Arc, input_buffer_id: Arc, kernel_id: Arc ) { + /* + 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)); } - fn add_with_image_swap(buffer_id: Arc, sprite: CompuSprite, ) { + 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 ccec939a..c0603c5a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,7 @@ 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; mod util; mod slider; @@ -221,9 +222,14 @@ fn main() { I will also need to get the texture id */ - let compu_sprite1 = CompuSprite::new((-1.,-0.5), (0.1,0.1)); + 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 compute_buffer = processor.new_compute_buffer(image_data.0, image_data.1, 4); + 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() { @@ -273,13 +279,18 @@ fn main() { return; } + let mut compu_frame = ComputeFrame::new(); + compu_frame.add(compute_buffer.clone(), compute_kernel.clone()); + compu_frame.add_with_image_swap(compute_buffer.clone(), compute_kernel.clone(), &compu_sprite1); let mut canvas = CanvasFrame::new(); canvas.draw(&sprite); canvas.draw(&sprite2); + canvas.draw(&compu_sprite1); - - (frame_future) = processor.run(&surface, frame_future, canvas); + (frame_future) = processor.run(&surface, frame_future, + canvas, + compu_frame); } } diff --git a/src/sprite.rs b/src/sprite.rs index 9bb7468c..d0d15421 100644 --- a/src/sprite.rs +++ b/src/sprite.rs @@ -1,4 +1,5 @@ use crate::canvas::Drawable; +use std::sync::Arc; #[derive(Debug, Clone)] pub struct Sprite { @@ -9,7 +10,7 @@ pub struct Sprite { color: (f32, f32, f32, f32), textured: bool, - texture_id: Option, + texture_id: Option>, } @@ -41,7 +42,7 @@ impl Sprite { } } - pub fn new_with_texture(position: (f32, f32), size: (f32, f32), texture_id: String) -> Sprite { + pub fn new_with_texture(position: (f32, f32), size: (f32, f32), texture_id: Arc) -> Sprite { let fsize = (size.0 as f32, size.1 as f32); @@ -75,7 +76,7 @@ impl Drawable for Sprite { self.color.clone() } - fn get_texture_id(&self) -> Option { + fn get_texture_handle(&self) -> Option> { match self.textured { true => { self.texture_id.clone() @@ -83,6 +84,10 @@ impl Drawable for Sprite { false => None, } } + + fn get_image_handle(&self) -> Option> { + None + } } /* diff --git a/src/util/compute_image.rs b/src/util/compute_image.rs index 51f27ab4..2a76bf78 100644 --- a/src/util/compute_image.rs +++ b/src/util/compute_image.rs @@ -38,7 +38,7 @@ pub struct ComputeImage { impl ComputeImage { - fn load_raw(filename: String) -> (Vec, (u32,u32)) { + pub fn load_raw(filename: String) -> (Vec, (u32,u32)) { let project_root = std::env::current_dir() @@ -141,6 +141,7 @@ impl ComputeImage { 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; diff --git a/src/vkprocessor.rs b/src/vkprocessor.rs index 375a950e..7019f43a 100644 --- a/src/vkprocessor.rs +++ b/src/vkprocessor.rs @@ -10,6 +10,8 @@ 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 vulkano::image::ImageUsage; pub struct VkProcessor<'a> { @@ -29,6 +31,8 @@ pub struct VkProcessor<'a> { swapchain_recreate_needed: bool, + compute_state: CompuState, + capabilities: Capabilities, canvas: Canvas, } @@ -36,6 +40,45 @@ pub struct VkProcessor<'a> { impl<'a> VkProcessor<'a> { + pub fn preload_textures(&mut self) { + + } + pub fn preload_kernels(&mut self) { + + } + pub fn preload_shaders(&mut self) { + + } + + pub fn get_texture_handle(&self, texture_name: String) -> Option> { + None + } + pub fn get_kernel_handle(&self, kernel_name: String) -> Option> { + None + } + pub fn get_shader_handle(&self, shader_name: String) -> Option> { + None + } + + pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc { + let mut usage = ImageUsage::none(); + usage.transfer_destination = true; + usage.storage = true; + + self.canvas.create_image(dimensions, usage) + } + + 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 { + self.compute_state.read_compute_buffer(handle) + } + pub fn write_compute_buffer(&self, handle: Arc, data: Vec) { + self.compute_state.write_compute_buffer(handle, data) + } + + pub fn new(instance: &'a Arc, surface: &'a Arc>) -> VkProcessor<'a> { let physical = PhysicalDevice::enumerate(instance).next().unwrap(); @@ -68,6 +111,7 @@ impl<'a> VkProcessor<'a> { swapchain: None, swapchain_images: None, swapchain_recreate_needed: false, + compute_state: CompuState::new(), capabilities: capabilities.clone(), canvas: Canvas::new(queue, device, physical, capabilities), } @@ -153,8 +197,12 @@ impl<'a> VkProcessor<'a> { surface: &'a Arc>, mut frame_future: Box, canvas_frame: CanvasFrame, + compute_frame: ComputeFrame, ) -> Box { + + + // self.canvas.draw(canvas_frame); self.canvas.allocate_vertex_buffers(self.device.clone());