From 86eb27f86de64b98a5c5b646b398e8ae0e0353a4 Mon Sep 17 00:00:00 2001 From: mitchellhansen Date: Mon, 7 Oct 2019 23:34:11 -0700 Subject: [PATCH] getting the canvasframe set up for text --- resources/shaders/simple_text.vert | 5 ++ src/canvas/canvas_buffer.rs | 42 ------------- src/canvas/canvas_frame.rs | 6 ++ src/canvas/canvas_state.rs | 96 ++++++++++++++++++------------ src/canvas/shader/text_shader.rs | 13 +++- 5 files changed, 80 insertions(+), 82 deletions(-) diff --git a/resources/shaders/simple_text.vert b/resources/shaders/simple_text.vert index 83a06f4e..24c8c470 100644 --- a/resources/shaders/simple_text.vert +++ b/resources/shaders/simple_text.vert @@ -7,6 +7,11 @@ layout(location = 0) in vec3 v_position; layout(location = 1) in vec4 color; layout(location = 2) in vec2 ti_position; +layout(location = 3) in vec2 screen_position; +layout(location = 4) in vec2 atlas_position; +layout(location = 5) in vec2 atlas_size; +layout(location = 6 in float scale; + // These are made up in the shader themselves layout(location = 0) out vec2 tex_coords; diff --git a/src/canvas/canvas_buffer.rs b/src/canvas/canvas_buffer.rs index 5522ddb9..abb212af 100644 --- a/src/canvas/canvas_buffer.rs +++ b/src/canvas/canvas_buffer.rs @@ -51,45 +51,3 @@ impl CanvasImage { } } -#[derive(Clone)] -pub struct CanvasTextCache { - //pub(crate) handle: Arc, - pub(crate) buffer: Arc>, - pub(crate) size: (u32, u32), -} - -impl CanvasTextCache { - pub fn get_descriptor_set(&self, - pipeline: Arc, - sampler: Arc) -> Box { - let o: Box = Box::new( - PersistentDescriptorSet::start( - pipeline.clone(), 0, - ) - .add_buffer(self.buffer.clone()).unwrap() - .build().unwrap()); - o - } -} - - -#[derive(Clone)] -pub struct CanvasText { - pub(crate) handle: Arc, - pub(crate) buffer: Arc>, - pub(crate) size: (u32, u32), -} - -impl CanvasText { - pub fn get_descriptor_set(&self, - pipeline: Arc, - sampler: Arc) -> Box { - let o: Box = Box::new( - PersistentDescriptorSet::start( - pipeline.clone(), 0, - ) - .add_sampled_image(self.buffer.clone(), sampler.clone()).unwrap() - .build().unwrap()); - o - } -} \ No newline at end of file diff --git a/src/canvas/canvas_frame.rs b/src/canvas/canvas_frame.rs index adeccd9f..5db3e487 100644 --- a/src/canvas/canvas_frame.rs +++ b/src/canvas/canvas_frame.rs @@ -2,12 +2,15 @@ use crate::util::vertex_3d::{Vertex3D}; use std::sync::Arc; use std::collections::HashMap; use crate::canvas::canvas_state::{Drawable, CanvasTextureHandle, CanvasImageHandle}; +use crate::canvas::canvas_text::CanvasFontHandle; +use crate::canvas::shader::text_shader::GlyphInstance; /// pub struct CanvasFrame { pub colored_drawables: Vec, pub textured_drawables: HashMap, Vec>>, pub image_drawables: HashMap, Vec>>, + pub text_drawables: HashMap, Vec> } impl CanvasFrame { @@ -18,9 +21,12 @@ impl CanvasFrame { colored_drawables: vec![], textured_drawables: Default::default(), image_drawables: Default::default(), + text_drawables: Default::default() } } + + // TODO: Fix this for text and fonts /// Accumulates the drawables collected Vertex2D's pub fn draw(&mut self, drawable: &dyn Drawable) { match drawable.get_texture_handle() { diff --git a/src/canvas/canvas_state.rs b/src/canvas/canvas_state.rs index e9585bfb..1bee29ff 100644 --- a/src/canvas/canvas_state.rs +++ b/src/canvas/canvas_state.rs @@ -29,6 +29,7 @@ use crate::canvas::shader::common::{CompiledGraphicsPipeline, CompiledGraphicsPi use crate::canvas::shader::generic_shader::GenericShader; use vulkano::memory::pool::PotentialDedicatedAllocation::Generic; use rusttype::Glyph; +use std::borrow::Borrow; /// 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 @@ -80,23 +81,22 @@ pub struct CanvasState { image_buffers: Vec>, texture_buffers: Vec>, shader_buffers: Vec>>, - text_buffers: Vec>, + + // + text_buffers: Vec>, // Hold onto the vertices we get from the Compu and Canvas Frames // When the run comes around, push the vertices to the GPU - colored_drawables: Vec, colored_vertex_buffer: Vec>, - textured_drawables: HashMap, Vec>>, textured_vertex_buffer: HashMap, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>, - 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)>>, + text_instances: HashMap, Vec<(Vertex3D, )>>, + text_atlas_buffer: HashMap, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>, // Looks like we gotta hold onto the queue for managing textures queue: Arc, @@ -211,8 +211,8 @@ impl CanvasState { textured_vertex_buffer: Default::default(), image_drawables: Default::default(), image_vertex_buffer: Default::default(), - text_drawables: HashMap::default(), - text_vertex_buffer: Default::default(), + text_instances: HashMap::default(), + text_atlas_buffer: Default::default(), queue: queue.clone(), device: device.clone(), @@ -257,7 +257,6 @@ impl CanvasState { handle } - /// Using the dimensions and suggested usage, load a CanvasImage and return it's handle pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc { let handle = Arc::new(CanvasImageHandle { handle: self.image_buffers.len() as u32 }); @@ -404,22 +403,17 @@ impl CanvasState { /// Scrape all the values from the CanvasFrame and then allocate the vertex buffers pub fn draw(&mut self, canvas_frame: CanvasFrame) { - self.textured_drawables = canvas_frame.textured_drawables; - self.colored_drawables = canvas_frame.colored_drawables; - self.image_drawables = canvas_frame.image_drawables; + let textured_drawables = canvas_frame.textured_drawables; + let colored_drawables = canvas_frame.colored_drawables; + let image_drawables = canvas_frame.image_drawables; + let text_drawables = canvas_frame.text_drawables; - self.allocate_vertex_buffers(); - } - - /// draw(canvas_fame) stored all the intermediate information, this function - /// allocates the vertex buffers using that information - fn allocate_vertex_buffers(&mut self) { self.colored_vertex_buffer.clear(); { let g = hprof::enter("Colored Vertex Buffer"); self.colored_vertex_buffer.push( ImmutableBuffer::from_iter( - self.colored_drawables.iter().cloned(), + colored_drawables.iter().cloned(), BufferUsage::vertex_buffer(), self.queue.clone(), ).unwrap().0 @@ -467,6 +461,27 @@ impl CanvasState { ); } } + + self.text_instances.clear(); + { + let g = hprof::enter("Text Instance Vertex Buffer"); + for (k, v) in self.text_.drain() { + let vertex_buffer = v.clone().iter() + .fold(Vec::new(), |mut a: Vec, b| { + a.extend(b); + a + }); + + self.image_vertex_buffer.insert( + k.clone(), + ImmutableBuffer::from_iter( + vertex_buffer.iter().cloned(), + BufferUsage::vertex_buffer(), + self.queue.clone(), + ).unwrap().0, + ); + } + } } /// Builds the descriptor set for solid colors using the input kernel (needs to support solid colors) @@ -565,25 +580,30 @@ 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 = text_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(); -// } -// } + let mut shader = self.text_buffers.get( + self.get_shader_handle(String::from("simple_text")) + .unwrap().clone().handle as usize + ).unwrap(); + + + // + + if !self.text_atlas_buffer.is_empty() { + for (text_handle, vertex_buffer) in self.text_atlas_buffer.clone() { + let handle = text_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()); + let instance_data = self.text_instances.get(text_handle.borrow()).unwrap(); + + 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![]), + vec![descriptor_set], (), + ).unwrap(); + } + } command_buffer .end_render_pass() diff --git a/src/canvas/shader/text_shader.rs b/src/canvas/shader/text_shader.rs index ceac10fb..01f0b1fb 100644 --- a/src/canvas/shader/text_shader.rs +++ b/src/canvas/shader/text_shader.rs @@ -11,11 +11,20 @@ use shade_runner::{Input, Output, Layout, Entry}; use std::ffi::CStr; use std::marker::PhantomData; use vulkano::pipeline::depth_stencil::{DepthStencil, Compare, DepthBounds, Stencil, StencilOp}; -use vulkano::pipeline::vertex::SingleBufferDefinition; +use vulkano::pipeline::vertex::{SingleBufferDefinition, OneVertexOneInstanceDefinition}; use crate::util::vertex_3d::Vertex3D; use crate::canvas::shader::generic_shader::GenericShader; use shade_runner as sr; +#[derive(Default, Debug, Clone, Copy)] +pub struct GlyphInstance { + screen_position: (f32, f32), + atlas_position: (f32, f32), + atlas_size: (f32, f32), + scale: f32, +} +vulkano::impl_vertex!(GlyphInstance, screen_position, atlas_position, atlas_size, scale); + /// CanvasShader holds the pipeline and render pass for the input shader source #[derive(Clone)] pub struct TextShader { @@ -99,7 +108,7 @@ impl CompiledGraphicsPipeline for TextShader { graphics_pipeline: Some(Arc::new(GraphicsPipeline::start() - .vertex_input(SingleBufferDefinition::::new()) + .vertex_input(OneVertexOneInstanceDefinition::::new()) .vertex_shader(vertex_entry_point.clone(), ShaderSpecializationConstants { first_constant: 0,