diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:20 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:20 +0100 |
commit | c3683cb91a7142be405aa672fcbae4238a3bde72 (patch) | |
tree | 3069cd8aef8212e864181732a27534008f533d25 /stockton-render/src/draw/context.rs | |
parent | 7cdb4bb159a7df88390e63c59f0d4c5538d7411b (diff) |
feat(render): texture store
Diffstat (limited to 'stockton-render/src/draw/context.rs')
-rw-r--r-- | stockton-render/src/draw/context.rs | 85 |
1 files changed, 60 insertions, 25 deletions
diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs index 882db44..f8a057c 100644 --- a/stockton-render/src/draw/context.rs +++ b/stockton-render/src/draw/context.rs @@ -17,9 +17,14 @@ //! In the end, this takes in vertices and renders them to a window. //! You'll need something else to actually generate the vertices though. -use std::mem::{ManuallyDrop, size_of}; +use std::{ + mem::{ManuallyDrop, size_of}, + iter::once, + ops::Deref +}; use winit::window::Window; use arrayvec::ArrayVec; +use image::RgbaImage; use hal::{ prelude::*, @@ -30,6 +35,7 @@ use stockton_types::{Vector2, Vector3}; use crate::types::*; use crate::error; +use super::texture::TextureStore; use super::buffer::{StagedBuffer, ModifiableBuffer}; /// Entry point name for shaders @@ -42,15 +48,24 @@ const COLOR_RANGE: hal::image::SubresourceRange = hal::image::SubresourceRange { layers: 0..1, }; +/// Size of texturestore. This needs to sync up with the array size in the fragment shader +const INITIAL_TEX_SIZE: usize = 2; + +/// Initial size of vertex buffer. TODO: Way of overriding this +const INITIAL_VERT_SIZE: u64 = 32; + +/// Initial size of index buffer. TODO: Way of overriding this +const INITIAL_INDEX_SIZE: u64 = 16; + /// Source for vertex shader. TODO const VERTEX_SOURCE: &str = include_str!("./data/stockton.vert"); /// Source for fragment shader. TODO const FRAGMENT_SOURCE: &str = include_str!("./data/stockton.frag"); -/// Represents a point of a vertices, including RGB and UV information. +/// Represents a point of a vertices, including RGB, UV and texture information. #[derive(Debug, Clone, Copy)] -pub struct UVPoint (pub Vector2, pub Vector3, pub Vector2); +pub struct UVPoint (pub Vector2, pub Vector3, pub Vector2, pub i32); /// Contains all the hal related stuff. /// In the end, this takes some 3D points and puts it on the screen. @@ -59,6 +74,7 @@ pub struct RenderingContext<'a> { // Parents for most of these things instance: ManuallyDrop<back::Instance>, device: ManuallyDrop<Device>, + adapter: Adapter, // Render destination surface: ManuallyDrop<Surface>, @@ -78,7 +94,6 @@ pub struct RenderingContext<'a> { // Pipeline renderpass: ManuallyDrop<RenderPass>, - descriptor_set_layouts: ManuallyDrop<DescriptorSetLayout>, pipeline_layout: ManuallyDrop<PipelineLayout>, pipeline: ManuallyDrop<GraphicsPipeline>, @@ -87,6 +102,9 @@ pub struct RenderingContext<'a> { cmd_buffers: Vec<CommandBuffer>, queue_group: QueueGroup, + // Texture store + texture_store: ManuallyDrop<TextureStore>, + // Vertex and index buffers // These are both staged pub vert_buffer: ManuallyDrop<StagedBuffer<'a, UVPoint>>, @@ -257,8 +275,8 @@ impl<'a> RenderingContext<'a> { let (vert_buffer, index_buffer) = { use hal::buffer::Usage; - let vert = StagedBuffer::new(&mut device, &adapter, Usage::VERTEX, 4)?; - let index = StagedBuffer::new(&mut device, &adapter, Usage::INDEX, 2)?; + let vert = StagedBuffer::new(&mut device, &adapter, Usage::VERTEX, INITIAL_VERT_SIZE)?; + let index = StagedBuffer::new(&mut device, &adapter, Usage::INDEX, INITIAL_INDEX_SIZE)?; (vert, index) }; @@ -311,14 +329,18 @@ impl<'a> RenderingContext<'a> { (cmd_pool, cmd_buffers, get_image, render_complete, present_complete, imageviews, framebuffers) }; + // Texture store + let texture_store = TextureStore::new(&mut device, INITIAL_TEX_SIZE)?; + // Graphics pipeline - let (descriptor_set_layouts, pipeline_layout, pipeline) = Self::create_pipeline(&mut device, extent, &subpass)?; + let (pipeline_layout, pipeline) = Self::create_pipeline(&mut device, extent, &subpass, &texture_store.descriptor_set_layout)?; Ok(RenderingContext { instance: ManuallyDrop::new(instance), surface: ManuallyDrop::new(surface), device: ManuallyDrop::new(device), + adapter, queue_group, swapchain: ManuallyDrop::new(swapchain), viewport, @@ -336,19 +358,28 @@ impl<'a> RenderingContext<'a> { cmd_pool, cmd_buffers, - descriptor_set_layouts: ManuallyDrop::new(descriptor_set_layouts), pipeline_layout: ManuallyDrop::new(pipeline_layout), pipeline: ManuallyDrop::new(pipeline), + texture_store: ManuallyDrop::new(texture_store), + vert_buffer: ManuallyDrop::new(vert_buffer), index_buffer: ManuallyDrop::new(index_buffer), }) } + /// Load the given image into the texturestore, returning the index or an error. + pub fn add_texture(&mut self, image: RgbaImage) -> Result<usize, &'static str> { + self.texture_store.add_texture(image, + &mut self.device, + &mut self.adapter, + &mut self.queue_group.queues[0], + &mut self.cmd_pool) + } + #[allow(clippy::type_complexity)] - pub fn create_pipeline(device: &mut Device, extent: hal::image::Extent, subpass: &hal::pass::Subpass<back::Backend>) -> Result< + pub fn create_pipeline(device: &mut Device, extent: hal::image::Extent, subpass: &hal::pass::Subpass<back::Backend>, set_layout: &DescriptorSetLayout) -> Result< ( - DescriptorSetLayout, PipelineLayout, GraphicsPipeline, ), error::CreationError> { @@ -404,7 +435,7 @@ impl<'a> RenderingContext<'a> { // Vertex buffers let vertex_buffers: Vec<VertexBufferDesc> = vec![VertexBufferDesc { binding: 0, - stride: (size_of::<f32>() * 7) as u32, + stride: (size_of::<f32>() * 8) as u32, rate: VertexInputRate::Vertex, }]; @@ -429,6 +460,13 @@ impl<'a> RenderingContext<'a> { format: Format::Rg32Sfloat, offset: (size_of::<f32>() * 5) as ElemOffset, } + }, AttributeDesc { // Tex Attribute + location: 3, + binding: 0, + element: Element { + format: Format::R32Sint, + offset: (size_of::<f32>() * 7) as ElemOffset + } }]; // Rasterizer @@ -449,17 +487,9 @@ impl<'a> RenderingContext<'a> { stencil: None, }; - // Descriptor set layout - let set_layout = unsafe { - device.create_descriptor_set_layout( - &[], - &[], - ) - }.map_err(|_| error::CreationError::OutOfMemoryError)?; - // Pipeline layout let layout = unsafe { - device.create_pipeline_layout(std::iter::once(&set_layout), &[]) + device.create_pipeline_layout(once(set_layout), &[]) }.map_err(|_| error::CreationError::OutOfMemoryError)?; // Colour blending @@ -517,7 +547,7 @@ impl<'a> RenderingContext<'a> { device.create_graphics_pipeline(&pipeline_desc, None) }.map_err(|e| error::CreationError::PipelineError (e))?; - Ok((set_layout, layout, pipeline)) + Ok((layout, pipeline)) } /// Draw a frame that's just cleared to the color specified. @@ -663,8 +693,15 @@ impl<'a> RenderingContext<'a> { SubpassContents::Inline ); buffer.bind_graphics_pipeline(&self.pipeline); - buffer.bind_vertex_buffers(0, vbufs); + buffer.bind_graphics_descriptor_sets( + &self.pipeline_layout, + 0, + once(self.texture_store.descriptor_set.deref()), + &[] + ); + + buffer.bind_vertex_buffers(0, vbufs); buffer.bind_index_buffer(IndexBufferView { buffer: ibuf, range: SubRange::WHOLE, @@ -727,6 +764,7 @@ impl<'a> core::ops::Drop for RenderingContext<'a> { use core::ptr::read; ManuallyDrop::into_inner(read(&self.vert_buffer)).deactivate(&mut self.device); ManuallyDrop::into_inner(read(&self.index_buffer)).deactivate(&mut self.device); + ManuallyDrop::into_inner(read(&self.texture_store)).deactivate(&mut self.device); self.device.destroy_command_pool( ManuallyDrop::into_inner(read(&self.cmd_pool)), @@ -738,9 +776,6 @@ impl<'a> core::ops::Drop for RenderingContext<'a> { .destroy_swapchain(ManuallyDrop::into_inner(read(&self.swapchain))); self.device - .destroy_descriptor_set_layout(ManuallyDrop::into_inner(read(&self.descriptor_set_layouts))); - - self.device .destroy_pipeline_layout(ManuallyDrop::into_inner(read(&self.pipeline_layout))); self.instance |