diff --git a/Cargo.toml b/Cargo.toml index f0dc92fc..23accfcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,9 @@ rand = "0.6.5" #vulkano = "0.13.0" vulkano = {path = "../vulkano/vulkano"} #vulkano-shaders = "0.14.0" -vulkano-shaders = {path = "../vulkano-shaders"} +vulkano-shaders = {path = "../vulkano/vulkano-shaders"} #vulkano-win = "0.14.0" -vulkano-win= {path = "../vulkano-win"} +vulkano-win= {path = "../vulkano/vulkano-win"} time = "0.1.38" shaderc = "0.6.1" #shade_runner = {version = "0.1.1", git = "https://github.com/MitchellHansen/shade_runner"} diff --git a/src/canvas/canvas_buffer.rs b/src/canvas/canvas_buffer.rs index 0eb3c4c2..1c0d50b6 100644 --- a/src/canvas/canvas_buffer.rs +++ b/src/canvas/canvas_buffer.rs @@ -6,7 +6,7 @@ use vulkano::sampler::Sampler; use vulkano::descriptor::DescriptorSet; use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; use vulkano::buffer::CpuAccessibleBuffer; -use crate::canvas::canvas_text::{CanvasTextCacheHandle, CanvasTextHandle}; +use crate::canvas::canvas_text::{CanvasTextCacheHandle, CanvasFontHandle}; use vulkano::pipeline::GraphicsPipelineAbstract; #[derive(Clone)] @@ -75,7 +75,7 @@ impl CanvasTextCache { #[derive(Clone)] pub struct CanvasText { - pub(crate) handle: Arc, + pub(crate) handle: Arc, pub(crate) buffer: Arc>, pub(crate) size: (u32, u32), } diff --git a/src/canvas/canvas_state.rs b/src/canvas/canvas_state.rs index 624716f5..4bb02ef0 100644 --- a/src/canvas/canvas_state.rs +++ b/src/canvas/canvas_state.rs @@ -20,7 +20,7 @@ use vulkano::pipeline::viewport::Viewport; use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer; use crate::canvas::canvas_frame::CanvasFrame; use std::hash::Hash; -use crate::canvas::canvas_text::{CanvasText, CanvasTextHandle}; +use crate::canvas::canvas_text::{CanvasText, CanvasFontHandle}; use crate::canvas::canvas_buffer::{CanvasImage, CanvasTexture, CanvasTextCache}; use crate::util::vertex_3d::Vertex3D; @@ -28,6 +28,7 @@ use vulkano::pipeline::depth_stencil::{StencilFaceFlags, DynamicStencilValue}; use crate::canvas::shader::common::{CompiledGraphicsPipeline, CompiledGraphicsPipelineHandle}; use crate::canvas::shader::generic_shader::GenericShader; use vulkano::memory::pool::PotentialDedicatedAllocation::Generic; +use rusttype::Glyph; /// A drawable object can be passed into a CanvasFrame to be rendered /// Very generic implementation. (N % 2 == 0) vertices, ditto for texture coords, and rgba color @@ -92,6 +93,11 @@ pub struct CanvasState { image_drawables: HashMap, Vec>>, image_vertex_buffer: HashMap, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>, + // So what exactly is this going to hold? + // Its going to be untextured. Colored. Lists of vertices. + text_drawables: HashMap, Vec<(Vertex3D)>>, + text_vertex_buffer: HashMap, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>, + // Looks like we gotta hold onto the queue for managing textures queue: Arc, device: Arc, @@ -170,6 +176,8 @@ impl CanvasState { CanvasState { + + // TODO: Might need to move this dynamic_state: DynamicState { line_width: None, viewports: None, @@ -195,14 +203,16 @@ impl CanvasState { image_buffers: vec![], texture_buffers: vec![], shader_buffers: vec![], - text_buffers: vec![], + colored_drawables: vec![], colored_vertex_buffer: vec![], textured_drawables: HashMap::default(), textured_vertex_buffer: Default::default(), image_drawables: Default::default(), image_vertex_buffer: Default::default(), + text_drawables: HashMap::default(), + text_vertex_buffer: Default::default(), queue: queue.clone(), device: device.clone(), @@ -211,8 +221,8 @@ impl CanvasState { } /// Using the dimensions and suggested usage, load a CanvasImage and return it's handle - pub fn create_text_buffers(&mut self, dimensions: (u32, u32)) -> Arc { - let handle = Arc::new(CanvasTextHandle { handle: self.text_buffers.len() as u32 }); + pub fn create_text_buffers(&mut self, dimensions: (u32, u32)) -> Arc { + let handle = Arc::new(CanvasFontHandle { handle: self.text_buffers.len() as u32 }); // // let text = CanvasText { // handle: handle.clone(), @@ -338,20 +348,19 @@ impl CanvasState { /// Load and Compile a shader with the filename at resources/shaders /// Takes physical and capabilities as we don't store that in Canvas pub fn load_shader(&mut self, - filename: String, - physical: PhysicalDevice, - capabilities: Capabilities) -> Option> + filename: String, + physical: PhysicalDevice, + capabilities: Capabilities) -> Option> where T: CompiledGraphicsPipeline { - let handle = Arc::new(CompiledGraphicsPipelineHandle { handle: self.shader_buffers.len() as u32 }); - let shader : Box = Box::new(T::new( + let shader: Box = Box::new(T::new( filename.clone(), self.device.clone(), handle.clone(), - self.render_pass.clone() + self.render_pass.clone(), )); self.shader_buffers.push(Arc::new(shader)); @@ -482,12 +491,14 @@ impl CanvasState { ClearValue::DepthStencil((1.0, 0x00)), ); -// self.dynamic_state = DynamicState { -// line_width: None, -// viewports: self.dynamic_state.viewports.clone(), -// scissors: None, -// compare_mask: Some(StencilMask{ face: StencilFaceFlags::StencilFaceFrontBit, mask: 0xFF }), -// }; + self.dynamic_state = DynamicState { + line_width: None, + viewports: self.dynamic_state.viewports.clone(), + scissors: None, + compare_mask: None, + write_mask: None, + reference: None, + }; let mut command_buffer = command_buffer.begin_render_pass( framebuffers[image_num].clone(), false, clear_values.clone(), @@ -553,6 +564,27 @@ impl CanvasState { } } + // Text + let mut shader = self.text_buffers.get( + self.get_shader_handle(String::from("simple_text")) + .unwrap().clone().handle as usize + ).unwrap(); + + if !self.text_vertex_buffer.is_empty() { + for (text_handle, vertex_buffer) in self.text_vertex_buffer.clone() { + let handle = texture_handle.clone().handle as usize; + let descriptor_set = self.text_buffers.get(handle).clone().unwrap().clone() + .get_descriptor_set(shader.get_pipeline(), self.sampler.clone()); + + command_buffer = command_buffer.draw( + shader.get_pipeline().clone(), + // Multiple vertex buffers must have their definition in the pipeline! + &self.dynamic_state.clone(), vec![vertex_buffer], + vec![descriptor_set], (), + ).unwrap(); + } + } + command_buffer .end_render_pass() .unwrap() diff --git a/src/canvas/canvas_text.rs b/src/canvas/canvas_text.rs index c030e67e..de73f232 100644 --- a/src/canvas/canvas_text.rs +++ b/src/canvas/canvas_text.rs @@ -9,39 +9,50 @@ use vulkano::image::{ImmutableImage, ImageUsage, ImageLayout, Dimensions}; use vulkano::format::ClearValue; use vulkano::format::Format::R8Unorm; -const CACHE_WIDTH: usize = 1000; -const CACHE_HEIGHT: usize = 1000; -/// Typed wrapper for a u32 shader handle (index id) -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -pub struct CanvasTextHandle { - pub handle: u32 +/* + +So I think this thing is going to build text vertex buffers to send to the GPU. +I assume I will just lay them out in ASCII for now along with a list of +transformation matrices + +Glpyh: + index: 0-255, + scale: 0.0 - 99.99 + transform: (0.0, 0.0) - (1.0, 1.0) + +I'm not sure if I want to send a new transformation matrix for each frame. But I suppose +that can come when I look at caching the sprites + + + + + +*/ + +pub struct Glyph { + } +/// Typed wrapper for a u32 shader handle (index id) #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -pub struct CanvasTextCacheHandle { +pub struct CanvasFontHandle { pub handle: u32 } - /// So currently, I'm using these as container classes which vkprocessor owns /// I then use a CanvasFrame which accumulates lists of handles and vertices. pub struct CanvasText { device: Arc, queue: Arc, font: Font<'static>, - cache: Cache<'static>, - cache_pixel_buffer: Vec, - texts: Vec, } impl CanvasText { + /// Load the font pub fn new(device: Arc, queue: Arc) -> CanvasText { - let cache = Cache::builder().dimensions(CACHE_WIDTH as u32, CACHE_HEIGHT as u32).build(); - let cache_pixel_buffer = vec!(0; CACHE_WIDTH * CACHE_HEIGHT); - let font_data = include_bytes!("../../resources/fonts/sansation.ttf"); let font = Font::from_bytes(font_data as &[u8]).unwrap(); @@ -49,13 +60,19 @@ impl CanvasText { device: device.clone(), queue: queue.clone(), font: font, - cache: cache, - cache_pixel_buffer: vec![], - texts: vec![] } + } + + /// Generate a vertex buffer from the font + /* + So... These fonts are going to have unequal amounts of vertices. + */ + pub fn get_vertex_buffer(&self) { + unimplemented!() } + /// postpone this until caching pub fn queue_text(&mut self, x: f32, y: f32, size: f32, color: [f32; 4], @@ -74,7 +91,7 @@ impl CanvasText { command_buffer: AutoCommandBufferBuilder, image_num: usize ) -> AutoCommandBufferBuilder { -// + // let screen_width = 0; // let screen_height = 0; // diff --git a/src/canvas/shader/canvas_shader.rs b/src/canvas/shader/canvas_shader.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/src/canvas/shader/generic_shader.rs b/src/canvas/shader/generic_shader.rs index 35e62b6a..d84fe7e4 100644 --- a/src/canvas/shader/generic_shader.rs +++ b/src/canvas/shader/generic_shader.rs @@ -96,7 +96,7 @@ impl CompiledGraphicsPipeline for GenericShader { third_constant: 0.0, }) - .depth_stencil(DepthStencil::default()) + .depth_stencil_simple_depth() // 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. diff --git a/src/canvas/shader/mod.rs b/src/canvas/shader/mod.rs index da635645..5bda5c81 100644 --- a/src/canvas/shader/mod.rs +++ b/src/canvas/shader/mod.rs @@ -1,6 +1,5 @@ use crate::canvas::shader::common::CompiledGraphicsPipeline; -pub mod canvas_shader; pub mod common; pub mod generic_shader; pub mod text_shader; diff --git a/src/main.rs b/src/main.rs index 23149ba9..0c11fcfb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -164,10 +164,6 @@ pub fn main() { let mut canvas = CanvasFrame::new(); canvas.draw(&funky_sprite); - -// canvas.draw(&sfml_sprite); -// canvas.draw(&compu_sprite1); - canvas.draw(&test_polygon); { diff --git a/src/vkprocessor.rs b/src/vkprocessor.rs index 1dd43b17..2a8a2f4e 100644 --- a/src/vkprocessor.rs +++ b/src/vkprocessor.rs @@ -39,7 +39,7 @@ pub struct VkProcessor<'a> { compute_state: CompuState, capabilities: Capabilities, - canvas: CanvasState, + canvas_state: CanvasState, } @@ -79,7 +79,7 @@ impl<'a> VkProcessor<'a> { swapchain_recreate_needed: false, compute_state: CompuState::new(), capabilities: capabilities.clone(), - canvas: CanvasState::new(queue, device, physical, capabilities), + canvas_state: CanvasState::new(queue, device, physical, capabilities), } } @@ -142,11 +142,11 @@ impl<'a> VkProcessor<'a> { /// A hardcoded list of textures which can be preloaded from this function pub fn preload_textures(&mut self) { - self.canvas.load_texture(String::from("funky-bird.jpg")); - self.canvas.load_texture(String::from("button.png")); - self.canvas.load_texture(String::from("background.jpg")); - self.canvas.load_texture(String::from("test2.png")); - self.canvas.load_texture(String::from("sfml.png")); + self.canvas_state.load_texture(String::from("funky-bird.jpg")); + self.canvas_state.load_texture(String::from("button.png")); + self.canvas_state.load_texture(String::from("background.jpg")); + self.canvas_state.load_texture(String::from("test2.png")); + self.canvas_state.load_texture(String::from("sfml.png")); } /// A hardcoded list of kernels which can be preloaded from this function @@ -157,15 +157,15 @@ impl<'a> VkProcessor<'a> { /// A hardcoded list of shaders which can be proloaded from this function pub fn preload_shaders(&mut self) { - self.canvas.load_shader::(String::from("color-passthrough"), self.physical.clone(), self.capabilities.clone()); - self.canvas.load_shader::(String::from("simple_texture"), self.physical.clone(), self.capabilities.clone()); - self.canvas.load_shader::(String::from("simple_image"), self.physical.clone(), self.capabilities.clone()); - self.canvas.load_shader::(String::from("simple_text"), self.physical.clone(), self.capabilities.clone()); + self.canvas_state.load_shader::(String::from("color-passthrough"), self.physical.clone(), self.capabilities.clone()); + self.canvas_state.load_shader::(String::from("simple_texture"), self.physical.clone(), self.capabilities.clone()); + self.canvas_state.load_shader::(String::from("simple_image"), self.physical.clone(), self.capabilities.clone()); + self.canvas_state.load_shader::(String::from("simple_text"), self.physical.clone(), self.capabilities.clone()); } /// O(n) Lookup for the matching texture string pub fn get_texture_handle(&self, texture_name: String) -> Option> { - self.canvas.get_texture_handle(texture_name) + self.canvas_state.get_texture_handle(texture_name) } /// O(n) Lookup for the matching kernel string @@ -175,7 +175,7 @@ impl<'a> VkProcessor<'a> { /// O(n) Lookup for the matching shader string pub fn get_shader_handle(&self, shader_name: String) -> Option> { - self.canvas.get_shader_handle(shader_name) + self.canvas_state.get_shader_handle(shader_name) } /// Create a new image which has the transfer usage @@ -184,7 +184,7 @@ impl<'a> VkProcessor<'a> { usage.transfer_destination = true; usage.storage = true; - self.canvas.create_image(dimensions, usage) + self.canvas_state.create_image(dimensions, usage) } /// Builds a compute buffer and returns it's handle @@ -215,14 +215,14 @@ impl<'a> VkProcessor<'a> { let g = hprof::enter("Frame buffer, future, swapchain recreate"); let mut framebuffers = - self.canvas.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone()); + self.canvas_state.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone()); // Whenever the window resizes we need to recreate everything dependent on the window size. // In this example that includes the swapchain, the framebuffers and the dynamic state viewport. if self.swapchain_recreate_needed { self.recreate_swapchain(surface); framebuffers = - self.canvas.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone()); + self.canvas_state.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone()); self.swapchain_recreate_needed = false; } @@ -247,7 +247,7 @@ impl<'a> VkProcessor<'a> { let g = hprof::enter("Canvas creates GPU buffers"); // take the canvas frame and create the vertex buffers // TODO: This performs gpu buffer creation. Shouldn't be in hotpath?? - self.canvas.draw(canvas_frame); + self.canvas_state.draw(canvas_frame); } let mut command_buffer = @@ -255,13 +255,13 @@ impl<'a> VkProcessor<'a> { let g = hprof::enter("Push compute commands to command buffer"); // Add the compute commands - let mut command_buffer = self.compute_state.compute_commands(compute_frame, command_buffer, &self.canvas); + let mut command_buffer = self.compute_state.compute_commands(compute_frame, command_buffer, &self.canvas_state); drop(g); let g = hprof::enter("Push draw commands to command buffer"); // Add the draw commands - let mut command_buffer = self.canvas.draw_commands(command_buffer, framebuffers, image_num); + let mut command_buffer = self.canvas_state.draw_commands(command_buffer, framebuffers, image_num); // And build let command_buffer = command_buffer.build().unwrap();