diff options
Diffstat (limited to 'stockton-render/src/draw')
-rw-r--r-- | stockton-render/src/draw/context.rs | 63 | ||||
-rw-r--r-- | stockton-render/src/draw/draw_buffers.rs | 8 | ||||
-rw-r--r-- | stockton-render/src/draw/macros.rs | 28 | ||||
-rw-r--r-- | stockton-render/src/draw/render.rs | 2 | ||||
-rw-r--r-- | stockton-render/src/draw/target.rs | 8 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/data/stockton.frag | 11 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/data/stockton.vert | 27 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/mod.rs | 8 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/pipeline.rs | 18 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/render.rs | 55 | ||||
-rwxr-xr-x | stockton-render/src/draw/ui/texture.rs | 54 |
11 files changed, 234 insertions, 48 deletions
diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs index 94f1f0c..4d700e5 100644 --- a/stockton-render/src/draw/context.rs +++ b/stockton-render/src/draw/context.rs @@ -29,14 +29,14 @@ use winit::window::Window; use super::{ buffer::ModifiableBuffer, - draw_buffers::DrawBuffers, + draw_buffers::{DrawBuffers, UVPoint}, pipeline::CompletePipeline, render::do_render, target::{SwapchainProperties, TargetChain}, texture::TextureStore, - ui::{do_render as do_render_ui, UIPipeline}, + ui::{do_render as do_render_ui, ensure_textures as ensure_textures_ui, UIPipeline, UIPoint}, }; -use crate::{error, types::*}; +use crate::{error, types::*, window::UIState}; use stockton_levels::prelude::*; /// Contains all the hal related stuff. @@ -76,14 +76,19 @@ pub struct RenderingContext<'a> { /// Texture store texture_store: ManuallyDrop<TextureStore>, + /// Texture store for UI + ui_texture_store: ManuallyDrop<TextureStore>, + /// Buffers used for drawing - draw_buffers: ManuallyDrop<DrawBuffers<'a>>, + draw_buffers: ManuallyDrop<DrawBuffers<'a, UVPoint>>, /// Buffers used for drawing the UI - ui_draw_buffers: ManuallyDrop<DrawBuffers<'a>>, + ui_draw_buffers: ManuallyDrop<DrawBuffers<'a, UIPoint>>, /// View projection matrix pub(crate) vp_matrix: Mat4, + + pub(crate) pixels_per_point: f32, } impl<'a> RenderingContext<'a> { @@ -156,9 +161,21 @@ impl<'a> RenderingContext<'a> { file, )?; + // Texture store for UI elements + let ui_texture_store = TextureStore::new_empty( + &mut device, + &mut adapter, + &mut queue_group.queues[0], + &mut cmd_pool, + 1, // TODO + )?; + let mut descriptor_set_layouts: ArrayVec<[_; 2]> = ArrayVec::new(); descriptor_set_layouts.push(texture_store.descriptor_set_layout.deref()); + let mut ui_descriptor_set_layouts: ArrayVec<[_; 2]> = ArrayVec::new(); + ui_descriptor_set_layouts.push(ui_texture_store.descriptor_set_layout.deref()); + // Graphics pipeline let pipeline = CompletePipeline::new( &mut device, @@ -172,7 +189,7 @@ impl<'a> RenderingContext<'a> { &mut device, swapchain_properties.extent, &swapchain_properties, - &[], + ui_descriptor_set_layouts, )?; // Swapchain and associated resources @@ -207,7 +224,11 @@ impl<'a> RenderingContext<'a> { draw_buffers: ManuallyDrop::new(draw_buffers), ui_draw_buffers: ManuallyDrop::new(ui_draw_buffers), + ui_texture_store: ManuallyDrop::new(ui_texture_store), + vp_matrix: Mat4::identity(), + + pixels_per_point: window.scale_factor() as f32, }) } @@ -241,7 +262,15 @@ impl<'a> RenderingContext<'a> { // TODO: Recycle ManuallyDrop::into_inner(read(&self.ui_pipeline)).deactivate(&mut self.device); self.ui_pipeline = ManuallyDrop::new({ - UIPipeline::new(&mut self.device, properties.extent, &properties, &[])? + let mut descriptor_set_layouts: ArrayVec<[_; 1]> = ArrayVec::new(); + descriptor_set_layouts.push(self.ui_texture_store.descriptor_set_layout.deref()); + + UIPipeline::new( + &mut self.device, + properties.extent, + &properties, + descriptor_set_layouts, + )? }); let old_swapchain = ManuallyDrop::into_inner(read(&self.target_chain)) @@ -267,8 +296,19 @@ impl<'a> RenderingContext<'a> { pub fn draw_vertices<M: MinBSPFeatures<VulkanSystem>>( &mut self, file: &M, + ui: &mut UIState, faces: &[u32], ) -> Result<(), &'static str> { + // Ensure UI texture(s) are loaded + ensure_textures_ui( + &mut self.ui_texture_store, + ui, + &mut self.device, + &mut self.adapter, + &mut self.queue_group.queues[0], + &mut self.cmd_pool, + ); + // 3D Pass let cmd_buffer = self.target_chain.prep_next_target( &mut self.device, @@ -289,7 +329,13 @@ impl<'a> RenderingContext<'a> { let cmd_buffer = self .target_chain .target_2d_pass(&mut self.ui_draw_buffers, &self.ui_pipeline)?; - do_render_ui(cmd_buffer, &mut self.ui_draw_buffers); + do_render_ui( + cmd_buffer, + &self.ui_pipeline.pipeline_layout, + &mut self.ui_draw_buffers, + &mut self.ui_texture_store, + ui, + ); // Update our buffers before we actually start drawing self.draw_buffers.vertex_buffer.commit( @@ -334,6 +380,7 @@ impl<'a> core::ops::Drop for RenderingContext<'a> { ManuallyDrop::into_inner(read(&self.draw_buffers)).deactivate(&mut self.device); ManuallyDrop::into_inner(read(&self.ui_draw_buffers)).deactivate(&mut self.device); ManuallyDrop::into_inner(read(&self.texture_store)).deactivate(&mut self.device); + ManuallyDrop::into_inner(read(&self.ui_texture_store)).deactivate(&mut self.device); ManuallyDrop::into_inner(read(&self.target_chain)) .deactivate(&mut self.device, &mut self.cmd_pool); diff --git a/stockton-render/src/draw/draw_buffers.rs b/stockton-render/src/draw/draw_buffers.rs index a6e0996..837356a 100644 --- a/stockton-render/src/draw/draw_buffers.rs +++ b/stockton-render/src/draw/draw_buffers.rs @@ -31,13 +31,13 @@ pub const INITIAL_VERT_SIZE: u64 = 3 * 3000; pub const INITIAL_INDEX_SIZE: u64 = 3000; /// The buffers used for drawing, ie index and vertex buffer -pub struct DrawBuffers<'a> { - pub vertex_buffer: ManuallyDrop<StagedBuffer<'a, UVPoint>>, +pub struct DrawBuffers<'a, T: Sized> { + pub vertex_buffer: ManuallyDrop<StagedBuffer<'a, T>>, pub index_buffer: ManuallyDrop<StagedBuffer<'a, (u16, u16, u16)>>, } -impl<'a> DrawBuffers<'a> { - pub fn new(device: &mut Device, adapter: &Adapter) -> Result<DrawBuffers<'a>, CreationError> { +impl<'a, T> DrawBuffers<'a, T> { + pub fn new(device: &mut Device, adapter: &Adapter) -> Result<DrawBuffers<'a, T>, CreationError> { let vert = StagedBuffer::new(device, &adapter, Usage::VERTEX, INITIAL_VERT_SIZE)?; let index = StagedBuffer::new(device, &adapter, Usage::INDEX, INITIAL_INDEX_SIZE)?; diff --git a/stockton-render/src/draw/macros.rs b/stockton-render/src/draw/macros.rs index 9096958..e1ee515 100644 --- a/stockton-render/src/draw/macros.rs +++ b/stockton-render/src/draw/macros.rs @@ -29,6 +29,20 @@ /// ``` /// See the hal::pso::Format enum for possible types macro_rules! pipeline_vb_attributes { + // Special case for single item + ( $binding:expr, $firstSize:expr; $firstType:ident ) => ({ + vec![ + AttributeDesc { + location: 0, + binding: $binding, + element: Element { + format: Format::$firstType, + offset: $firstSize as u32 + } + } + ] + }); + // Start of recursion ( $binding:expr, $firstSize:expr; $firstType:ident, @@ -55,20 +69,6 @@ macro_rules! pipeline_vb_attributes { vec }); - // Special case for single item - ( $binding:expr; $firstSize:expr; $firstType:ident ) => ({ - vec![ - AttributeDesc { - location: 0, - binding: $binding, - element: Element { - format: Format::$firstType, - offset: $firstSize as u32 - } - } - ] - }); - // Middle of recursion ( $vec:ident; $binding:expr; $location:expr; $prevSize:expr, $firstSize:expr; $firstType:ident, diff --git a/stockton-render/src/draw/render.rs b/stockton-render/src/draw/render.rs index e73b569..093e257 100644 --- a/stockton-render/src/draw/render.rs +++ b/stockton-render/src/draw/render.rs @@ -31,7 +31,7 @@ use crate::types::*; pub fn do_render<M: MinBSPFeatures<VulkanSystem>>( cmd_buffer: &mut CommandBuffer, - draw_buffers: &mut DrawBuffers, + draw_buffers: &mut DrawBuffers<UVPoint>, texture_store: &TextureStore, pipeline_layout: &PipelineLayout, file: &M, diff --git a/stockton-render/src/draw/target.rs b/stockton-render/src/draw/target.rs index b47700f..daf9942 100644 --- a/stockton-render/src/draw/target.rs +++ b/stockton-render/src/draw/target.rs @@ -31,8 +31,8 @@ use hal::{ use na::Mat4; use super::{ - buffer::ModifiableBuffer, draw_buffers::DrawBuffers, pipeline::CompletePipeline, - texture::image::LoadedImage, ui::UIPipeline, + buffer::ModifiableBuffer, draw_buffers::{DrawBuffers, UVPoint}, pipeline::CompletePipeline, + texture::image::LoadedImage, ui::{UIPipeline, UIPoint}, }; use crate::types::*; @@ -275,7 +275,7 @@ impl TargetChain { pub fn prep_next_target<'a>( &'a mut self, device: &mut Device, - draw_buffers: &mut DrawBuffers, + draw_buffers: &mut DrawBuffers<UVPoint>, pipeline: &CompletePipeline, vp: &Mat4, ) -> Result<&'a mut crate::types::CommandBuffer, &'static str> { @@ -373,7 +373,7 @@ impl TargetChain { pub fn target_2d_pass<'a>( &'a mut self, - draw_buffers: &mut DrawBuffers, + draw_buffers: &mut DrawBuffers<UIPoint>, pipeline: &UIPipeline, ) -> Result<&'a mut CommandBuffer, &'static str> { let target = &mut self.targets[self.last_image as usize]; diff --git a/stockton-render/src/draw/ui/data/stockton.frag b/stockton-render/src/draw/ui/data/stockton.frag index 1a85ab6..e5b2b4d 100644 --- a/stockton-render/src/draw/ui/data/stockton.frag +++ b/stockton-render/src/draw/ui/data/stockton.frag @@ -1,8 +1,15 @@ #version 450 #extension GL_ARB_separate_shader_objects : enable -layout(location = 0) out vec4 outColor; +// DescriptorSet 0 = Textures +layout(set = 0, binding = 0) uniform texture2D tex[8]; +layout(set = 0, binding = 1) uniform sampler samp[8]; + +layout (location = 1) in vec2 frag_uv; +layout (location = 2) in flat int frag_col; + +layout (location = 0) out vec4 color; void main() { - outColor = vec4(1.0, 0.0, 0.0, 1.0); + color = texture(sampler2D(tex[0], samp[0]), frag_uv); }
\ No newline at end of file diff --git a/stockton-render/src/draw/ui/data/stockton.vert b/stockton-render/src/draw/ui/data/stockton.vert index 1dd9477..7447fec 100644 --- a/stockton-render/src/draw/ui/data/stockton.vert +++ b/stockton-render/src/draw/ui/data/stockton.vert @@ -1,11 +1,26 @@ #version 450 -vec2 positions[3] = vec2[]( - vec2(0.0, -0.5), - vec2(0.5, 0.5), - vec2(-0.5, 0.5) -); +layout (push_constant) uniform PushConsts { + vec2 screen_size; +} push; + +layout(location = 0) in vec2 pos; +layout (location = 1) in vec2 uv; +layout (location = 2) in int col; // rgba of u8s + +out gl_PerVertex { + vec4 gl_Position; +}; +layout (location = 1) out vec2 frag_uv; +layout (location = 2) out int frag_col; void main() { - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + gl_Position = vec4( + ((pos.x / push.screen_size.x) * 2.0) - 1.0, + ((pos.y / push.screen_size.y) * 2.0) - 1.0, + 0.0, + 1.0 + ); + frag_uv = uv; + frag_col = col; } diff --git a/stockton-render/src/draw/ui/mod.rs b/stockton-render/src/draw/ui/mod.rs index cd19362..bcf5f38 100644 --- a/stockton-render/src/draw/ui/mod.rs +++ b/stockton-render/src/draw/ui/mod.rs @@ -15,8 +15,16 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +use egui::paint::color::Srgba; + pub mod pipeline; pub mod render; +pub mod texture; pub use pipeline::UIPipeline; pub use render::do_render; +use stockton_types::Vector2; +pub use texture::ensure_textures; + +#[derive(Debug)] +pub struct UIPoint(pub Vector2, pub Vector2, pub Srgba); diff --git a/stockton-render/src/draw/ui/pipeline.rs b/stockton-render/src/draw/ui/pipeline.rs index 378c558..3b643e4 100644 --- a/stockton-render/src/draw/ui/pipeline.rs +++ b/stockton-render/src/draw/ui/pipeline.rs @@ -62,7 +62,7 @@ impl UIPipeline { set_layouts: T, ) -> Result<Self, error::CreationError> where - T: IntoIterator, + T: IntoIterator + std::fmt::Debug, T::Item: Borrow<DescriptorSetLayout>, { use hal::format::Format; @@ -125,7 +125,7 @@ impl UIPipeline { .compile_into_spirv( VERTEX_SOURCE, shaderc::ShaderKind::Vertex, - "vertex.vert", + "vertex_ui.vert", ENTRY_NAME, None, ) @@ -135,7 +135,7 @@ impl UIPipeline { .compile_into_spirv( FRAGMENT_SOURCE, shaderc::ShaderKind::Fragment, - "fragment.frag", + "fragment_ui.frag", ENTRY_NAME, None, ) @@ -180,13 +180,14 @@ impl UIPipeline { // Vertex buffers let vertex_buffers: Vec<VertexBufferDesc> = vec![VertexBufferDesc { binding: 0, - stride: (size_of::<f32>() * 5) as u32, + stride: ((size_of::<f32>() * 4) + (size_of::<u8>() * 4)) as u32, rate: VertexInputRate::Vertex, }]; let attributes: Vec<AttributeDesc> = pipeline_vb_attributes!(0, size_of::<f32>() * 2; Rg32Sfloat, - size_of::<f32>() * 3; Rgb32Sfloat + size_of::<f32>() * 2; Rg32Sfloat, + size_of::<u8>() * 4; Rgba8Uint ); // Rasterizer @@ -207,9 +208,12 @@ impl UIPipeline { stencil: None, }; + log::debug!("ui set layouts: {:?}", set_layouts); // Pipeline layout - let layout = unsafe { device.create_pipeline_layout(set_layouts, &[]) } - .map_err(|_| error::CreationError::OutOfMemoryError)?; + let layout = unsafe { + device.create_pipeline_layout(set_layouts, &[(ShaderStageFlags::VERTEX, 0..8)]) + } + .map_err(|_| error::CreationError::OutOfMemoryError)?; // Colour blending let blender = { diff --git a/stockton-render/src/draw/ui/render.rs b/stockton-render/src/draw/ui/render.rs index b965a80..ad23dfb 100644 --- a/stockton-render/src/draw/ui/render.rs +++ b/stockton-render/src/draw/ui/render.rs @@ -15,14 +15,65 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +use crate::draw::texture::TextureStore; +use arrayvec::ArrayVec; +use egui::Pos2; use hal::prelude::*; +use hal::pso::ShaderStageFlags; +use super::UIPoint; use crate::draw::draw_buffers::DrawBuffers; use crate::types::*; +use crate::UIState; +use std::convert::TryInto; +use std::mem::transmute; +use stockton_types::Vector2; -pub fn do_render(cmd_buffer: &mut CommandBuffer, _draw_buffers: &mut DrawBuffers) { +pub fn do_render( + cmd_buffer: &mut CommandBuffer, + pipeline_layout: &PipelineLayout, + draw_buffers: &mut DrawBuffers<UIPoint>, + texture_store: &mut TextureStore, + ui: &mut UIState, +) { // TODO: Actual UI Rendering + let (_out, paint) = ui.end_frame(); + let screen = ui.dimensions(); + unsafe { - cmd_buffer.draw(0..3, 0..1); + cmd_buffer.push_graphics_constants( + &pipeline_layout, + ShaderStageFlags::VERTEX, + 0, + &[transmute(screen.x), transmute(screen.y)], + ); + } + + for (_rect, tris) in paint.iter() { + // Copy triangles/indicies + for i in (0..tris.indices.len()).step_by(3) { + draw_buffers.index_buffer[i / 3] = ( + tris.indices[i].try_into().unwrap(), + tris.indices[i + 1].try_into().unwrap(), + tris.indices[i + 2].try_into().unwrap(), + ); + } + for (i, vertex) in tris.vertices.iter().enumerate() { + draw_buffers.vertex_buffer[i] = UIPoint( + Vector2::new(vertex.pos.x, vertex.pos.y), + Vector2::new(vertex.uv.x, vertex.uv.y), + vertex.color, + ); + } + + // TODO: *Properly* deal with textures + let mut descriptor_sets: ArrayVec<[_; 1]> = ArrayVec::new(); + descriptor_sets.push(texture_store.get_chunk_descriptor_set(0)); + + unsafe { + cmd_buffer.bind_graphics_descriptor_sets(pipeline_layout, 0, descriptor_sets, &[]); + // Call draw + cmd_buffer.draw_indexed(0..tris.indices.len() as u32, 0, 0..1); + } } } diff --git a/stockton-render/src/draw/ui/texture.rs b/stockton-render/src/draw/ui/texture.rs new file mode 100755 index 0000000..ce18f02 --- /dev/null +++ b/stockton-render/src/draw/ui/texture.rs @@ -0,0 +1,54 @@ +/* + * Copyright (C) Oscar Shrimpton 2020 + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ +use egui::Texture; +use crate::types::*; +use crate::draw::texture::{TextureStore, LoadableImage}; +use crate::UIState; + +impl LoadableImage for &Texture { + fn width(&self) -> u32 { + self.width as u32 + } + fn height(&self) -> u32 { + self.height as u32 + } + fn copy_row(&self, y: u32, ptr: *mut u8) -> () { + let row_size = self.width(); + let pixels = &self.pixels[(y * row_size) as usize..((y + 1) * row_size) as usize]; + + for (i,x) in pixels.iter().enumerate() { + unsafe { + *ptr.offset(i as isize * 3) = *x; + *ptr.offset((i as isize * 3) + 1) = *x; + *ptr.offset((i as isize * 3) + 2) = *x; + } + } + } +} + +pub fn ensure_textures(texture_store: &mut TextureStore, ui: &mut UIState, + device: &mut Device, + adapter: &mut Adapter, + command_queue: &mut CommandQueue, + command_pool: &mut CommandPool) { + let tex = ui.ctx.texture(); + + if tex.version != ui.last_tex_ver { + texture_store.put_texture(0, &*tex, device, adapter, command_queue, command_pool).unwrap(); // TODO + ui.last_tex_ver = tex.version; + } +}
\ No newline at end of file |