From a7e79668eb05c32e92739112b56f79366a6bdf5c Mon Sep 17 00:00:00 2001 From: mitchellhansen Date: Thu, 8 Aug 2019 00:34:37 -0700 Subject: [PATCH] very close to the skeleton of the canvas written. Still haven't tested it but it's looking good. Need to figure out how I'm goign to iterate shader_kernels without borrowing from self --- src/canvas.rs | 207 +++++++++++++++++++++++++++---------- src/util/shader_kernels.rs | 5 +- src/vkprocessor.rs | 9 +- 3 files changed, 162 insertions(+), 59 deletions(-) diff --git a/src/canvas.rs b/src/canvas.rs index b43149eb..781d0806 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -17,6 +17,9 @@ 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 shaderc::TargetEnv; // Canvas is the accumulator of Sprites for drawing // Needs to know: @@ -107,27 +110,8 @@ pub trait Drawable { -/* - - -OASIJDOQIWEJFOWIEJFOWIEJFOWEIJFOIWEJFOIW - - -Right now I'm in the middle of adding texture ownership to the canvas. -I'm aiming at being able to load them on the fly from what texture name (String) the -sprite is requesting. This might be too slow though as I can't really avoid a lookup table -somewhere in the code. - - - - - -*/ - // Need three types of shaders. Solid, Textured, Compute -#[derive(PartialEq)] -#[derive(Eq)] -#[derive(Hash)] +#[derive(PartialEq, Eq, Hash)] pub enum ShaderType { SOLID = 0, TEXTURED = 1, @@ -137,31 +121,61 @@ pub enum ShaderType { pub struct Canvas { colored_drawables : Vec, + colored_vertex_buffer: Vec>, textured_drawables: HashMap>, + textured_vertex_buffer: HashMap>, + vertex_buffers: Vec>, shader_kernels: HashMap, - textures: Vec>>, + texture_store: HashMap>>, + + // Looks like we gotta hold onto the queue for managing textures + queue: Arc, + sampler: Arc } impl Canvas { // needs to take in the texture list - pub fn new() -> Canvas { + pub fn new(queue: Arc, + device: Arc, + physical: PhysicalDevice, + capabilities: Capabilities) -> Canvas { + + let solid_color_kernel = String::from("color-passthrough"); + let texture_kernel = String::from("simple_texture"); + + let shader_kernels = 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 { colored_drawables: vec![], + colored_vertex_buffer: vec![], + textured_drawables: Default::default(), + textured_vertex_buffer: Default::default(), + vertex_buffers: vec![], - shader_kernels: HashMap::new(), - textures: vec![] - } + shader_kernels: shader_kernels, + texture_store: Default::default(), + + queue: queue.clone(), + 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_texture_from_file(image_filename: String, queue: Arc) -> Arc> { + // TODO Handle file not found gracefully + fn get_texture_from_file(&self, image_filename: String) -> Arc> { let project_root = std::env::current_dir() @@ -197,20 +211,26 @@ impl Canvas { image_buffer.iter().cloned(), Dimensions::Dim2d { width: xy.0, height: xy.1 }, Format::R8G8B8A8Srgb, - queue.clone() + self.queue.clone() ).unwrap(); texture } - pub fn load_texture_from_filename(&mut self, filename: String, queue: Arc) { - let texture = Canvas::get_texture_from_file(filename.clone(), queue.clone()); - self.textures.push(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 + } - let texture1 = Canvas::get_texture_from_file(String::from("button.png"), queue.clone()); - self.textures.push(texture1); } + // After done using this, need to call allocated vertex buffers pub fn draw(&mut self, drawable: &dyn Drawable) { match drawable.get_texture_id() { @@ -234,8 +254,20 @@ impl Canvas { } + fn get_texture(&mut self, texture_id: String) -> Arc> { - pub fn allocate_vertex_buffers(&mut self, device: Arc) { + if let Some(i) = self.texture_store.get(&texture_id) { + return i.clone(); + } else { + self.load_texture_from_filename(texture_id) + } + } + + + pub fn allocate_colored_vertex_buffers(&mut self, device: Arc) { + + self.vertex_buffers.clear(); + self.colored_vertex_buffer.clear(); self.vertex_buffers.push( CpuAccessibleBuffer::from_iter( @@ -244,6 +276,14 @@ impl Canvas { self.colored_drawables.iter().cloned() ).unwrap() ); + + self.colored_vertex_buffer.push( + CpuAccessibleBuffer::from_iter( + device.clone(), + BufferUsage::vertex_buffer(), + self.colored_drawables.iter().cloned() + ).unwrap() + ); } // I guess these go out as an array. So I can add multiple descriptor sets @@ -256,22 +296,37 @@ impl Canvas { // Choose which texture I want to add to this descriptor set. // Add multiple textures // Choose which shader and pipeline it should run on - fn get_texture_descriptor_set(&mut self, device: Arc) -> 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(); - - let o : Box = Box::new( - PersistentDescriptorSet::start( - self.shader_kernels.get(&ShaderType::TEXTURED).unwrap().clone().get_pipeline(), 0 - ) - .add_sampled_image(self.textures.get(0).unwrap().clone(), sampler.clone()).unwrap() - .build().unwrap()); - o + fn get_descriptor_set(&mut self, + shader_type: &ShaderType, + texture_id: String) -> Box { + + match shader_type { + ShaderType::SOLID => { + let o: Box = Box::new( + PersistentDescriptorSet::start( + self.shader_kernels.get(&shader_type).unwrap().clone().get_pipeline().clone(), 0 + ).build().unwrap()); + o + }, + ShaderType::TEXTURED => { + let o: Box = Box::new( + PersistentDescriptorSet::start( + self.shader_kernels.get(&shader_type).unwrap().clone().get_pipeline().clone(), 0 + ) + .add_sampled_image(self.get_texture(texture_id), self.sampler.clone()).unwrap() + .build().unwrap()); + o + }, + ShaderType::COMPUTE => { + unimplemented!("Compute dont work here"); + }, + } } - // The image set is the containing object for all texture and image hooks. + // 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 { @@ -290,6 +345,7 @@ impl Canvas { } + /* @@ -331,13 +387,26 @@ impl Canvas { framebuffers[image_num].clone(), false, clear_values.clone() ).unwrap(); -// for i in self.shader_kernels { -// command_buffer = command_buffer.draw( -// i.clone().unwrap().get_pipeline(), -// &dynamic_state.clone(), self.vertex_buffers, -// vec![self.get_image_set()], () -// ).unwrap(); -// } + + // So I need to do this without borrowing self from the shader_kernels.... + // Maybe self referential struct issue cropping up + // + // + // + // + // + // + // + // + + for (shader_type, kernel) in self.shader_kernels.iter() { + command_buffer = command_buffer.draw( + kernel.clone().get_pipeline().clone(), + &dynamic_state.clone(), self.vertex_buffers.clone(), + vec![self.get_descriptor_set(shader_type, String::from("texture"))], () + ).unwrap(); + } + // // .draw(self.shader_kernels.clone().unwrap().get_pipeline(), // &dynamic_state.clone(), self.vertex_buffers, @@ -348,4 +417,34 @@ impl Canvas { .end_render_pass() .unwrap() } -} \ No newline at end of file +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/util/shader_kernels.rs b/src/util/shader_kernels.rs index 4a674a39..f51bff2c 100644 --- a/src/util/shader_kernels.rs +++ b/src/util/shader_kernels.rs @@ -20,7 +20,7 @@ use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, Persistent use shaderc::CompileOptions; use vulkano::framebuffer::{Subpass, RenderPass, RenderPassAbstract, Framebuffer, FramebufferAbstract, RenderPassDesc}; use vulkano::pipeline::shader::{GraphicsShaderType, ShaderModule, GraphicsEntryPoint, SpecializationConstants, SpecializationMapEntry}; -use vulkano::swapchain::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError}; +use vulkano::swapchain::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError, Capabilities}; use vulkano::swapchain::acquire_next_image; use vulkano::image::swapchain::SwapchainImage; use winit::{EventsLoop, WindowBuilder, Window, Event, WindowEvent}; @@ -80,12 +80,11 @@ impl ShaderKernels { } pub fn new(filename: String, - surface: &Arc>, + capabilities: Capabilities, queue: Arc, physical: PhysicalDevice, device: Arc) -> ShaderKernels { - let capabilities = surface.capabilities(physical).unwrap(); let format = capabilities.supported_formats[0].0; let filenames = ShaderKernels::get_path(filename.clone()); diff --git a/src/vkprocessor.rs b/src/vkprocessor.rs index 5a8f229e..ebe6ce47 100644 --- a/src/vkprocessor.rs +++ b/src/vkprocessor.rs @@ -21,7 +21,7 @@ use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, Persistent 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::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError, Capabilities}; use vulkano::swapchain::acquire_next_image; use vulkano::image::swapchain::SwapchainImage; use winit::{EventsLoop, WindowBuilder, Window, Event, WindowEvent}; @@ -99,12 +99,16 @@ pub struct VkProcessor<'a> { swapchain_recreate_needed: bool, + capabilities: Capabilities } impl<'a> VkProcessor<'a> { pub fn new(instance: &'a Arc, surface: &'a Arc>) -> VkProcessor<'a> { + + + let physical = PhysicalDevice::enumerate(instance).next().unwrap(); let queue_family = physical.queue_families().find(|&q| { @@ -138,6 +142,7 @@ impl<'a> VkProcessor<'a> { swapchain: None, swapchain_images: None, swapchain_recreate_needed: false, + capabilities: surface.capabilities(physical).unwrap() } } @@ -149,7 +154,7 @@ impl<'a> VkProcessor<'a> { pub fn compile_shaders(&mut self, filename: String, surface: &'a Arc>) { self.shader_kernels = Some( ShaderKernels::new(filename.clone(), - surface, self.queue.clone(), + self.capabilities.clone(), self.queue.clone(), self.physical, self.device.clone()) );