diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:23 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:23 +0100 |
commit | 6ab13f2d0cb345795f761181a06777ade61ff09c (patch) | |
tree | 42007acef9846d5e79f1bf418a96647f34b530d1 /stockton-render/src | |
parent | ccf0074b08ce835cf22e7d46153d1cb3f3d06d32 (diff) |
refactor(all): separate rendering from framework
stockton-passes is mostly just a stand-in until this is
properly separated
Diffstat (limited to 'stockton-render/src')
-rw-r--r-- | stockton-render/src/buffers/dedicated_image.rs (renamed from stockton-render/src/draw/buffers/dedicated_image.rs) | 2 | ||||
-rw-r--r-- | stockton-render/src/buffers/draw_buffers.rs (renamed from stockton-render/src/draw/buffers/draw_buffers.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/buffers/mod.rs (renamed from stockton-render/src/draw/buffers/mod.rs) | 12 | ||||
-rw-r--r-- | stockton-render/src/buffers/staged.rs (renamed from stockton-render/src/draw/buffers/staged.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/builders/mod.rs | 7 | ||||
-rw-r--r-- | stockton-render/src/builders/pipeline.rs (renamed from stockton-render/src/draw/builders/pipeline.rs) | 18 | ||||
-rw-r--r-- | stockton-render/src/builders/renderpass.rs (renamed from stockton-render/src/draw/builders/renderpass.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/builders/shader.rs (renamed from stockton-render/src/draw/builders/shader.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/context.rs (renamed from stockton-render/src/draw/context.rs) | 75 | ||||
-rw-r--r-- | stockton-render/src/culling.rs | 70 | ||||
-rw-r--r-- | stockton-render/src/draw/builders/mod.rs | 3 | ||||
-rw-r--r-- | stockton-render/src/draw/camera.rs | 61 | ||||
-rw-r--r-- | stockton-render/src/draw/data/stockton.frag | 15 | ||||
-rw-r--r-- | stockton-render/src/draw/data/stockton.vert | 23 | ||||
-rw-r--r-- | stockton-render/src/draw/draw_passes/level.rs | 478 | ||||
-rw-r--r-- | stockton-render/src/draw/draw_passes/ui.rs | 348 | ||||
-rw-r--r-- | stockton-render/src/draw/mod.rs | 17 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/data/stockton.frag | 15 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/data/stockton.vert | 37 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/mod.rs | 52 | ||||
-rw-r--r-- | stockton-render/src/draw_passes/cons.rs (renamed from stockton-render/src/draw/draw_passes/cons.rs) | 44 | ||||
-rw-r--r-- | stockton-render/src/draw_passes/mod.rs (renamed from stockton-render/src/draw/draw_passes/mod.rs) | 29 | ||||
-rw-r--r-- | stockton-render/src/draw_passes/util.rs (renamed from stockton-render/src/draw/draw_passes/util.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/lib.rs | 91 | ||||
-rw-r--r-- | stockton-render/src/queue_negotiator.rs (renamed from stockton-render/src/draw/queue_negotiator.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/systems.rs | 2 | ||||
-rw-r--r-- | stockton-render/src/target.rs (renamed from stockton-render/src/draw/target.rs) | 13 | ||||
-rw-r--r-- | stockton-render/src/texture/block.rs (renamed from stockton-render/src/draw/texture/block.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/texture/image.rs (renamed from stockton-render/src/draw/texture/image.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/texture/load.rs (renamed from stockton-render/src/draw/texture/load.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/texture/loader.rs (renamed from stockton-render/src/draw/texture/loader.rs) | 2 | ||||
-rw-r--r-- | stockton-render/src/texture/mod.rs (renamed from stockton-render/src/draw/texture/mod.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/texture/repo.rs (renamed from stockton-render/src/draw/texture/repo.rs) | 4 | ||||
-rw-r--r-- | stockton-render/src/texture/resolver.rs (renamed from stockton-render/src/draw/texture/resolver.rs) | 2 | ||||
-rw-r--r-- | stockton-render/src/texture/staging_buffer.rs (renamed from stockton-render/src/draw/texture/staging_buffer.rs) | 0 | ||||
-rw-r--r-- | stockton-render/src/utils.rs (renamed from stockton-render/src/draw/utils.rs) | 2 | ||||
-rw-r--r-- | stockton-render/src/window.rs | 239 |
37 files changed, 155 insertions, 1506 deletions
diff --git a/stockton-render/src/draw/buffers/dedicated_image.rs b/stockton-render/src/buffers/dedicated_image.rs index 878d304..bf49a38 100644 --- a/stockton-render/src/draw/buffers/dedicated_image.rs +++ b/stockton-render/src/buffers/dedicated_image.rs @@ -1,6 +1,6 @@ //! A dedicated image. Used for depth buffers. -use crate::draw::texture::PIXEL_SIZE; +use crate::texture::PIXEL_SIZE; use crate::types::*; use std::mem::ManuallyDrop; diff --git a/stockton-render/src/draw/buffers/draw_buffers.rs b/stockton-render/src/buffers/draw_buffers.rs index 5baec92..5baec92 100644 --- a/stockton-render/src/draw/buffers/draw_buffers.rs +++ b/stockton-render/src/buffers/draw_buffers.rs diff --git a/stockton-render/src/draw/buffers/mod.rs b/stockton-render/src/buffers/mod.rs index dc7df65..82ca62a 100644 --- a/stockton-render/src/draw/buffers/mod.rs +++ b/stockton-render/src/buffers/mod.rs @@ -11,13 +11,13 @@ use hal::{ MemoryTypeId, }; -pub mod dedicated_image; -pub mod draw_buffers; -pub mod staged; +mod dedicated_image; +mod draw_buffers; +mod staged; -pub use dedicated_image::DedicatedLoadedImage; -pub use draw_buffers::DrawBuffers; -pub use staged::StagedBuffer; +pub use dedicated_image::*; +pub use draw_buffers::*; +pub use staged::*; /// Create a buffer of the given specifications, allocating more device memory. // TODO: Use a different memory allocator? diff --git a/stockton-render/src/draw/buffers/staged.rs b/stockton-render/src/buffers/staged.rs index 71b5204..71b5204 100644 --- a/stockton-render/src/draw/buffers/staged.rs +++ b/stockton-render/src/buffers/staged.rs diff --git a/stockton-render/src/builders/mod.rs b/stockton-render/src/builders/mod.rs new file mode 100644 index 0000000..97b47a0 --- /dev/null +++ b/stockton-render/src/builders/mod.rs @@ -0,0 +1,7 @@ +mod pipeline; +mod renderpass; +mod shader; + +pub use pipeline::*; +pub use renderpass::*; +pub use shader::*; diff --git a/stockton-render/src/draw/builders/pipeline.rs b/stockton-render/src/builders/pipeline.rs index 0c06774..25a4dc6 100644 --- a/stockton-render/src/draw/builders/pipeline.rs +++ b/stockton-render/src/builders/pipeline.rs @@ -1,5 +1,5 @@ use super::{renderpass::RenderpassSpec, shader::ShaderDesc}; -use crate::{draw::target::SwapchainProperties, error::EnvironmentError, types::*}; +use crate::{error::EnvironmentError, target::SwapchainProperties, types::*}; use std::{mem::ManuallyDrop, ops::Range}; @@ -241,23 +241,23 @@ impl PipelineSpec { pub struct CompletePipeline { /// Our main render pass - pub(crate) renderpass: ManuallyDrop<RenderPassT>, + pub renderpass: ManuallyDrop<RenderPassT>, /// The layout of our main graphics pipeline - pub(crate) pipeline_layout: ManuallyDrop<PipelineLayoutT>, + pub pipeline_layout: ManuallyDrop<PipelineLayoutT>, /// Our main graphics pipeline - pub(crate) pipeline: ManuallyDrop<GraphicsPipelineT>, + pub pipeline: ManuallyDrop<GraphicsPipelineT>, /// The vertex shader module - pub(crate) vs_module: ManuallyDrop<ShaderModuleT>, + pub vs_module: ManuallyDrop<ShaderModuleT>, /// The fragment shader module - pub(crate) fs_module: Option<ShaderModuleT>, - pub(crate) gm_module: Option<ShaderModuleT>, - pub(crate) ts_module: Option<(ShaderModuleT, ShaderModuleT)>, + pub fs_module: Option<ShaderModuleT>, + pub gm_module: Option<ShaderModuleT>, + pub ts_module: Option<(ShaderModuleT, ShaderModuleT)>, - pub(crate) render_area: Rect, + pub render_area: Rect, } impl CompletePipeline { diff --git a/stockton-render/src/draw/builders/renderpass.rs b/stockton-render/src/builders/renderpass.rs index 43f0eb2..43f0eb2 100644 --- a/stockton-render/src/draw/builders/renderpass.rs +++ b/stockton-render/src/builders/renderpass.rs diff --git a/stockton-render/src/draw/builders/shader.rs b/stockton-render/src/builders/shader.rs index fde185d..fde185d 100644 --- a/stockton-render/src/draw/builders/shader.rs +++ b/stockton-render/src/builders/shader.rs diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/context.rs index 65dcff6..3985c47 100644 --- a/stockton-render/src/draw/context.rs +++ b/stockton-render/src/context.rs @@ -28,7 +28,7 @@ use stockton_types::Session; /// Contains all the hal related stuff. /// In the end, this takes in a depth-sorted list of faces and a map file and renders them. // TODO: Settings for clear colour, buffer sizes, etc -pub struct RenderingContext<DP> { +pub struct RenderingContext { // Parents for most of these things /// Vulkan Instance instance: ManuallyDrop<back::Instance>, @@ -40,28 +40,23 @@ pub struct RenderingContext<DP> { adapter: Adapter, /// Swapchain and stuff - pub(crate) target_chain: ManuallyDrop<TargetChain>, + target_chain: ManuallyDrop<TargetChain>, // Command pool and buffers /// The command pool used for our buffers cmd_pool: ManuallyDrop<CommandPoolT>, + queue_negotiator: QueueNegotiator, + /// The queue to use for drawing queue: Arc<RwLock<QueueT>>, - /// Deals with drawing logic, and holds any data required for drawing. - draw_pass: ManuallyDrop<DP>, - - pub(crate) pixels_per_point: f32, + pixels_per_point: f32, } -impl<DP: DrawPass> RenderingContext<DP> { +impl RenderingContext { /// Create a new RenderingContext for the given window. - pub fn new<IDP: IntoDrawPass<DP>>( - window: &Window, - session: &Session, - idp: IDP, - ) -> Result<Self> { + pub fn new<IDP: IntoDrawPass<DP>, DP: DrawPass>(window: &Window) -> Result<Self> { // Create surface let (instance, surface, mut adapters) = unsafe { let instance = @@ -125,17 +120,6 @@ impl<DP: DrawPass> RenderingContext<DP> { let swapchain_properties = SwapchainProperties::find_best(&adapter, &surface) .context("Error getting properties for swapchain")?; - // Draw pass - let dp = idp - .init( - session, - &adapter, - device_lock.clone(), - &mut queue_negotiator, - &swapchain_properties, - ) - .context("Error initialising draw pass")?; - // Lock device let mut device = device_lock .write() @@ -168,18 +152,20 @@ impl<DP: DrawPass> RenderingContext<DP> { // Unlock device drop(device); + let queue = queue_negotiator + .get_queue::<DrawQueue>() + .ok_or(EnvironmentError::NoQueues) + .context("Error getting draw queue")?; + Ok(RenderingContext { instance: ManuallyDrop::new(instance), device: device_lock, adapter, - queue: queue_negotiator - .get_queue::<DrawQueue>() - .ok_or(EnvironmentError::NoQueues) - .context("Error getting draw queue")?, + queue_negotiator, + queue, - draw_pass: ManuallyDrop::new(dp), target_chain: ManuallyDrop::new(target_chain), cmd_pool: ManuallyDrop::new(cmd_pool), @@ -208,8 +194,6 @@ impl<DP: DrawPass> RenderingContext<DP> { let properties = SwapchainProperties::find_best(&self.adapter, &surface) .context("Error finding best swapchain properties")?; - // TODO: Notify draw passes - self.target_chain = ManuallyDrop::new( TargetChain::new( &mut device, @@ -224,7 +208,7 @@ impl<DP: DrawPass> RenderingContext<DP> { } /// Draw onto the next frame of the swapchain - pub fn draw_next_frame(&mut self, session: &Session) -> Result<()> { + pub fn draw_next_frame<DP: DrawPass>(&mut self, session: &Session, dp: &mut DP) -> Result<()> { let mut device = self .device .write() @@ -238,14 +222,39 @@ impl<DP: DrawPass> RenderingContext<DP> { // Level draw pass self.target_chain - .do_draw_with(&mut device, &mut queue, &mut *self.draw_pass, session) + .do_draw_with(&mut device, &mut queue, dp, session) .context("Error preparing next target")?; Ok(()) } + + /// Get a reference to the rendering context's pixels per point. + pub fn pixels_per_point(&self) -> f32 { + self.pixels_per_point + } + + /// Get a reference to the rendering context's device. + pub fn device(&self) -> &Arc<RwLock<DeviceT>> { + &self.device + } + + /// Get a reference to the rendering context's target chain. + pub fn target_chain(&self) -> &TargetChain { + &self.target_chain + } + + /// Get a reference to the rendering context's adapter. + pub fn adapter(&self) -> &Adapter { + &self.adapter + } + + /// Get a mutable reference to the rendering context's queue negotiator. + pub fn queue_negotiator_mut(&mut self) -> &mut QueueNegotiator { + &mut self.queue_negotiator + } } -impl<DP> core::ops::Drop for RenderingContext<DP> { +impl core::ops::Drop for RenderingContext { fn drop(&mut self) { { self.device.write().unwrap().wait_idle().unwrap(); diff --git a/stockton-render/src/culling.rs b/stockton-render/src/culling.rs deleted file mode 100644 index c10605f..0000000 --- a/stockton-render/src/culling.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! Functions for figuring out what to render -#![allow(dead_code)] - -use stockton_levels::prelude::*; -use stockton_levels::parts::tree::{BspNode, BspNodeValue}; -use stockton_types::Vector3; - -/// Get the visible faces according to visdata and frustum culling -// TODO: Write this. For now, just render all faces -pub fn get_visible_faces<X: CoordSystem, T: MinBspFeatures<X>>(pos: Vector3, file: &T) -> Vec<u32> { - let vis_cluster = get_cluster_id(pos, file); - - let mut visible = Vec::with_capacity(file.faces_len() as usize); - if (vis_cluster & 0x80000000) != 0 { - // Negative = Invalid camera position - // For now just render everything - for face_idx in 0..file.faces_len() { - visible.push(face_idx); - } - - return visible; - } - - walk_bsp_tree(file.get_bsp_root(), vis_cluster, &mut visible, file); - - visible -} - -pub fn walk_bsp_tree<X: CoordSystem, T: MinBspFeatures<X>>( - node: &BspNode, - vis_cluster: u32, - visible_faces: &mut Vec<u32>, - file: &T, -) { - if let BspNodeValue::Children(front, back) = &node.value { - walk_bsp_tree(back, vis_cluster, visible_faces, file); - walk_bsp_tree(front, vis_cluster, visible_faces, file); - } else if let BspNodeValue::Leaf(leaf) = &node.value { - if (leaf.cluster_id & 0x80000000) != 0 { - // Negative means invalid leaf - return; - } else if file.cluster_visible_from(vis_cluster, leaf.cluster_id) { - for face_idx in leaf.faces_idx.iter() { - // TODO: Culling or something - visible_faces.push(*face_idx); - } - } - } -} - -/// Get the viscluster pos lies in -fn get_cluster_id<X: CoordSystem, T: MinBspFeatures<X>>(pos: Vector3, file: &T) -> u32 { - let mut node = file.get_bsp_root(); - while let BspNodeValue::Children(front, back) = &node.value { - let plane = file.get_plane(node.plane_idx); - let dist = plane.normal.dot(&pos) - plane.dist; - - if dist >= 0.0 { - node = front; - } else { - node = back; - } - } - - if let BspNodeValue::Leaf(leaf) = &node.value { - leaf.cluster_id - } else { - panic!("should have had a leaf but didn't"); - } -} diff --git a/stockton-render/src/draw/builders/mod.rs b/stockton-render/src/draw/builders/mod.rs deleted file mode 100644 index 002c09f..0000000 --- a/stockton-render/src/draw/builders/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod pipeline; -pub mod renderpass; -pub mod shader; diff --git a/stockton-render/src/draw/camera.rs b/stockton-render/src/draw/camera.rs deleted file mode 100644 index 62784de..0000000 --- a/stockton-render/src/draw/camera.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Things related to converting 3D world space to 2D screen space - -use legion::maybe_changed; -use na::{look_at_lh, perspective_lh_zo}; -use stockton_types::{ - components::{CameraSettings, CameraVPMatrix, Transform}, - Vector3, -}; - -use crate::Renderer; - -use super::DrawPass; - -fn euler_to_direction(euler: &Vector3) -> Vector3 { - let pitch = euler.x; - let yaw = euler.y; - let _roll = euler.z; // TODO: Support camera roll - - Vector3::new( - yaw.sin() * pitch.cos(), - pitch.sin(), - yaw.cos() * pitch.cos(), - ) -} - -#[system(for_each)] -#[filter(maybe_changed::<Transform>() | maybe_changed::<CameraSettings>())] -pub fn calc_vp_matrix<DP: DrawPass + 'static>( - transform: &Transform, - settings: &CameraSettings, - matrix: &mut CameraVPMatrix, - #[resource] renderer: &Renderer<DP>, -) { - // Get look direction from euler angles - let direction = euler_to_direction(&transform.rotation); - - // Converts world space to camera space - let view_matrix = look_at_lh( - &transform.position, - &(transform.position + direction), - &Vector3::new(0.0, 1.0, 0.0), - ); - - // Converts camera space to screen space - let projection_matrix = { - let mut temp = perspective_lh_zo( - renderer.get_aspect_ratio(), - settings.fov, - settings.near, - settings.far, - ); - - // Vulkan's co-ord system is different from OpenGLs - temp[(1, 1)] *= -1.0; - - temp - }; - - // Chain them together into a single matrix - matrix.vp_matrix = projection_matrix * view_matrix; -} diff --git a/stockton-render/src/draw/data/stockton.frag b/stockton-render/src/draw/data/stockton.frag deleted file mode 100644 index 336d9fe..0000000 --- a/stockton-render/src/draw/data/stockton.frag +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 - -// 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_tex; - -layout (location = 0) out vec4 color; - -void main() -{ - color = texture(sampler2D(tex[frag_tex % 8], samp[frag_tex % 8]), frag_uv); -}
\ No newline at end of file diff --git a/stockton-render/src/draw/data/stockton.vert b/stockton-render/src/draw/data/stockton.vert deleted file mode 100644 index aaee1a5..0000000 --- a/stockton-render/src/draw/data/stockton.vert +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -// DescriptorSet 0 = Matrices -layout (push_constant) uniform PushConsts { - mat4 vp; -} push; - -layout (location = 0) in vec3 position; -layout (location = 1) in int tex; -layout (location = 2) in vec2 uv; - -out gl_PerVertex { - vec4 gl_Position; -}; -layout (location = 1) out vec2 frag_uv; -layout (location = 2) out flat int frag_tex; - -void main() -{ - gl_Position = push.vp * vec4(position, 1.0); - frag_uv = uv; - frag_tex = tex; -}
\ No newline at end of file diff --git a/stockton-render/src/draw/draw_passes/level.rs b/stockton-render/src/draw/draw_passes/level.rs deleted file mode 100644 index 682c775..0000000 --- a/stockton-render/src/draw/draw_passes/level.rs +++ /dev/null @@ -1,478 +0,0 @@ -//! Minimal code for drawing any level, based on traits from stockton-levels - -use super::{util::TargetSpecificResources, DrawPass, IntoDrawPass}; -use crate::{ - draw::{ - buffers::{ - draw_buffers::{DrawBuffers, INITIAL_INDEX_SIZE, INITIAL_VERT_SIZE}, - DedicatedLoadedImage, ModifiableBuffer, - }, - builders::{ - pipeline::{ - CompletePipeline, PipelineSpecBuilder, VertexBufferSpec, - VertexPrimitiveAssemblerSpec, - }, - renderpass::RenderpassSpec, - shader::ShaderDesc, - }, - queue_negotiator::QueueNegotiator, - target::SwapchainProperties, - texture::{resolver::TextureResolver, TexLoadQueue, TextureLoadConfig, TextureRepo}, - }, - error::{EnvironmentError, LevelError, LockPoisoned}, - types::*, -}; -use hal::{ - buffer::SubRange, - command::{ClearColor, ClearDepthStencil, ClearValue, RenderAttachmentInfo, SubpassContents}, - format::{Aspects, Format}, - image::{ - Filter, FramebufferAttachment, Layout, SubresourceRange, Usage, ViewCapabilities, WrapMode, - }, - pass::{Attachment, AttachmentLoadOp, AttachmentOps, AttachmentStoreOp}, - pso::{ - BlendDesc, BlendOp, BlendState, ColorBlendDesc, ColorMask, Comparison, DepthStencilDesc, - DepthTest, Face, Factor, FrontFace, InputAssemblerDesc, LogicOp, PolygonMode, Primitive, - Rasterizer, ShaderStageFlags, State, VertexInputRate, - }, -}; -use legion::{Entity, IntoQuery}; -use shaderc::ShaderKind; -use stockton_levels::{ - features::MinRenderFeatures, - parts::{data::Geometry, IsFace}, -}; -use stockton_types::{ - components::{CameraSettings, CameraVPMatrix, Transform}, - *, -}; - -use std::{ - array::IntoIter, - convert::TryInto, - iter::{empty, once}, - marker::PhantomData, - sync::{Arc, RwLock}, -}; - -use anyhow::{Context, Result}; - -/// The Vertexes that go to the shader -#[derive(Debug, Clone, Copy)] -struct UvPoint(pub Vector3, pub i32, pub Vector2); - -/// Draw a level -pub struct LevelDrawPass<'a, M> { - pipeline: CompletePipeline, - repo: TextureRepo, - active_camera: Entity, - draw_buffers: DrawBuffers<'a, UvPoint>, - - framebuffers: TargetSpecificResources<FramebufferT>, - depth_buffers: TargetSpecificResources<DedicatedLoadedImage>, - - _d: PhantomData<M>, -} - -impl<'a, M> DrawPass for LevelDrawPass<'a, M> -where - M: for<'b> MinRenderFeatures<'b> + 'static, -{ - fn queue_draw( - &mut self, - session: &Session, - img_view: &ImageViewT, - cmd_buffer: &mut crate::types::CommandBufferT, - ) -> anyhow::Result<()> { - // We might have loaded more textures - self.repo.process_responses(); - - // Make sure we update the vertex buffers after they're written to, but before they're read from. - self.draw_buffers - .vertex_buffer - .record_commit_cmds(cmd_buffer)?; - self.draw_buffers - .index_buffer - .record_commit_cmds(cmd_buffer)?; - - // Get level & camera - let mut query = <(&Transform, &CameraSettings, &CameraVPMatrix)>::query(); - let (camera_transform, camera_settings, camera_vp) = query - .get(&session.world, self.active_camera) - .context("Couldn't find camera components")?; - let map_lock: Arc<RwLock<M>> = session.resources.get::<Arc<RwLock<M>>>().unwrap().clone(); - let map = map_lock.read().map_err(|_| LockPoisoned::Map)?; - - // Get framebuffer and depth buffer - let fb = self.framebuffers.get_next(); - let db = self.depth_buffers.get_next(); - - unsafe { - cmd_buffer.begin_render_pass( - &self.pipeline.renderpass, - fb, - self.pipeline.render_area, - vec![ - RenderAttachmentInfo { - image_view: img_view, - clear_value: ClearValue { - color: ClearColor { - float32: [0.0, 0.0, 0.0, 1.0], - }, - }, - }, - RenderAttachmentInfo { - image_view: &*db.image_view, - clear_value: ClearValue { - depth_stencil: ClearDepthStencil { - depth: 1.0, - stencil: 0, - }, - }, - }, - ] - .into_iter(), - SubpassContents::Inline, - ); - cmd_buffer.bind_graphics_pipeline(&self.pipeline.pipeline); - - // VP Matrix - let vp = &*(camera_vp.vp_matrix.data.as_slice() as *const [f32] as *const [u32]); - - cmd_buffer.push_graphics_constants( - &self.pipeline.pipeline_layout, - ShaderStageFlags::VERTEX, - 0, - vp, - ); - - // Bind buffers - cmd_buffer.bind_vertex_buffers( - 0, - once(( - self.draw_buffers.vertex_buffer.get_buffer(), - SubRange { - offset: 0, - size: None, - }, - )), - ); - cmd_buffer.bind_index_buffer( - self.draw_buffers.index_buffer.get_buffer(), - SubRange { - offset: 0, - size: None, - }, - hal::IndexType::U16, - ); - } - - // Get visible faces - let mut faces = map.get_visible(camera_transform, camera_settings); - - // Iterate over faces, copying them in and drawing groups that use the same texture chunk all at once. - let face = faces.next(); - if let Some(face) = face { - let mut face = map.get_face(face).ok_or(LevelError::BadReference)?; - let mut current_chunk = face.texture_idx(&map) as usize / 8; - let mut chunk_start = 0; - - let mut curr_vert_idx: usize = 0; - let mut curr_idx_idx: usize = 0; - loop { - if current_chunk != face.texture_idx(&map) as usize / 8 { - // Last index was last of group, so draw it all if textures are loaded. - draw_or_queue( - current_chunk, - &mut self.repo, - cmd_buffer, - &*self.pipeline.pipeline_layout, - chunk_start as u32, - curr_idx_idx as u32, - )?; - - // Next group of same-chunked faces starts here. - chunk_start = curr_idx_idx; - current_chunk = face.texture_idx(&map) as usize / 8; - } - - match face.geometry(&map) { - Geometry::Vertices(v1, v2, v3) => { - for v in &[v1, v2, v3] { - let uvp = - UvPoint(v.position, face.texture_idx(&map).try_into()?, v.tex); - - self.draw_buffers.vertex_buffer[curr_vert_idx] = uvp; - curr_vert_idx += 1; - } - self.draw_buffers.index_buffer[curr_idx_idx] = ( - curr_vert_idx as u16 - 3, - curr_vert_idx as u16 - 2, - curr_vert_idx as u16 - 1, - ); - curr_idx_idx += 1; - } - } - - if curr_vert_idx >= INITIAL_VERT_SIZE.try_into()? - || curr_idx_idx >= INITIAL_INDEX_SIZE.try_into()? - { - println!("out of vertex buffer space!"); - break; - } - - match faces.next() { - Some(x) => face = map.get_face(x).ok_or(LevelError::BadReference)?, - None => break, - }; - } - - // Draw the final group of chunks - draw_or_queue( - current_chunk, - &mut self.repo, - cmd_buffer, - &*self.pipeline.pipeline_layout, - chunk_start as u32, - curr_idx_idx as u32, - )?; - } - - unsafe { - cmd_buffer.end_render_pass(); - } - - Ok(()) - } - - fn deactivate(self, device_lock: &mut Arc<RwLock<DeviceT>>) -> Result<()> { - unsafe { - let mut device = device_lock.write().map_err(|_| LockPoisoned::Device)?; - self.pipeline.deactivate(&mut device); - self.draw_buffers.deactivate(&mut device); - for fb in self.framebuffers.dissolve() { - device.destroy_framebuffer(fb); - } - for db in self.depth_buffers.dissolve() { - db.deactivate(&mut device); - } - } - self.repo.deactivate(device_lock); - - Ok(()) - } -} - -pub struct LevelDrawPassConfig<R> { - pub active_camera: Entity, - pub tex_resolver: R, -} - -impl<'a, M, R> IntoDrawPass<LevelDrawPass<'a, M>> for LevelDrawPassConfig<R> -where - M: for<'b> MinRenderFeatures<'b> + 'static, - R: TextureResolver + Send + Sync + 'static, -{ - fn init( - self, - _session: &Session, - adapter: &Adapter, - device_lock: Arc<RwLock<DeviceT>>, - queue_negotiator: &mut QueueNegotiator, - swapchain_properties: &SwapchainProperties, - ) -> Result<LevelDrawPass<'a, M>> { - let spec = PipelineSpecBuilder::default() - .rasterizer(Rasterizer { - polygon_mode: PolygonMode::Fill, - cull_face: Face::BACK, - front_face: FrontFace::CounterClockwise, - depth_clamping: false, - depth_bias: None, - conservative: true, - line_width: State::Static(1.0), - }) - .depth_stencil(DepthStencilDesc { - depth: Some(DepthTest { - fun: Comparison::Less, - write: true, - }), - depth_bounds: false, - stencil: None, - }) - .blender(BlendDesc { - logic_op: Some(LogicOp::Copy), - targets: vec![ColorBlendDesc { - mask: ColorMask::ALL, - blend: Some(BlendState { - color: BlendOp::Add { - src: Factor::One, - dst: Factor::Zero, - }, - alpha: BlendOp::Add { - src: Factor::One, - dst: Factor::Zero, - }, - }), - }], - }) - .primitive_assembler(VertexPrimitiveAssemblerSpec::with_buffers( - InputAssemblerDesc::new(Primitive::TriangleList), - vec![VertexBufferSpec { - attributes: vec![Format::Rgb32Sfloat, Format::R32Sint, Format::Rg32Sfloat], - rate: VertexInputRate::Vertex, - }], - )) - .shader_vertex(ShaderDesc { - source: include_str!("../data/stockton.vert").to_string(), - entry: "main".to_string(), - kind: ShaderKind::Vertex, - }) - .shader_fragment(ShaderDesc { - source: include_str!("../data/stockton.frag").to_string(), - entry: "main".to_string(), - kind: ShaderKind::Fragment, - }) - .push_constants(vec![(ShaderStageFlags::VERTEX, 0..64)]) - .renderpass(RenderpassSpec { - colors: vec![Attachment { - format: Some(swapchain_properties.format), - samples: 1, - ops: AttachmentOps::new(AttachmentLoadOp::Clear, AttachmentStoreOp::Store), - stencil_ops: AttachmentOps::new( - AttachmentLoadOp::Clear, - AttachmentStoreOp::DontCare, - ), - layouts: Layout::ColorAttachmentOptimal..Layout::ColorAttachmentOptimal, - }], - depth: Some(Attachment { - format: Some(swapchain_properties.depth_format), - samples: 1, - ops: AttachmentOps::new(AttachmentLoadOp::Clear, AttachmentStoreOp::DontCare), - stencil_ops: AttachmentOps::new( - AttachmentLoadOp::DontCare, - AttachmentStoreOp::DontCare, - ), - layouts: Layout::Undefined..Layout::DepthStencilAttachmentOptimal, - }), - inputs: vec![], - resolves: vec![], - preserves: vec![], - }) - .build() - .context("Error building pipeline")?; - - let repo = TextureRepo::new( - device_lock.clone(), - queue_negotiator - .family::<TexLoadQueue>() - .ok_or(EnvironmentError::NoSuitableFamilies) - .context("Error finding texture queue")?, - queue_negotiator - .get_queue::<TexLoadQueue>() - .ok_or(EnvironmentError::NoQueues) - .context("Error finding texture queue")?, - adapter, - TextureLoadConfig { - resolver: self.tex_resolver, - filter: Filter::Linear, - wrap_mode: WrapMode::Tile, - }, - ) - .context("Error creating texture repo")?; - - let (draw_buffers, pipeline, framebuffers, depth_buffers) = { - let mut device = device_lock.write().map_err(|_| LockPoisoned::Device)?; - let draw_buffers = - DrawBuffers::new(&mut device, adapter).context("Error creating draw buffers")?; - let pipeline = spec - .build( - &mut device, - swapchain_properties.extent, - swapchain_properties, - once(&*repo.get_ds_layout()?), - ) - .context("Error building pipeline")?; - - let fat = swapchain_properties.framebuffer_attachment(); - let dat = FramebufferAttachment { - usage: Usage::DEPTH_STENCIL_ATTACHMENT, - format: swapchain_properties.depth_format, - view_caps: ViewCapabilities::empty(), - }; - let framebuffers = TargetSpecificResources::new( - || unsafe { - Ok(device.create_framebuffer( - &pipeline.renderpass, - IntoIter::new([fat.clone(), dat.clone()]), - swapchain_properties.extent, - )?) - }, - swapchain_properties.image_count as usize, - )?; - let depth_buffers = TargetSpecificResources::new( - || { - DedicatedLoadedImage::new( - &mut device, - adapter, - swapchain_properties.depth_format, - Usage::DEPTH_STENCIL_ATTACHMENT, - SubresourceRange { - aspects: Aspects::DEPTH, - level_start: 0, - level_count: Some(1), - layer_start: 0, - layer_count: Some(1), - }, - swapchain_properties.extent.width as usize, - swapchain_properties.extent.height as usize, - ) - .context("Error creating depth buffer") - }, - swapchain_properties.image_count as usize, - )?; - - (draw_buffers, pipeline, framebuffers, depth_buffers) - }; - - Ok(LevelDrawPass { - pipeline, - repo, - draw_buffers, - active_camera: self.active_camera, - _d: PhantomData, - framebuffers, - depth_buffers, - }) - } - - fn find_aux_queues<'c>( - adapter: &'c Adapter, - queue_negotiator: &mut QueueNegotiator, - ) -> Result<Vec<(&'c QueueFamilyT, Vec<f32>)>> { - queue_negotiator.find(adapter, &TexLoadQueue)?; - - Ok(vec![queue_negotiator - .family_spec::<TexLoadQueue>(&adapter.queue_families, 1) - .ok_or(EnvironmentError::NoSuitableFamilies)?]) - } -} - -fn draw_or_queue( - current_chunk: usize, - tex_repo: &mut TextureRepo, - cmd_buffer: &mut CommandBufferT, - pipeline_layout: &PipelineLayoutT, - chunk_start: u32, - curr_idx_idx: u32, -) -> Result<()> { - if let Some(ds) = tex_repo.attempt_get_descriptor_set(current_chunk) { - unsafe { - cmd_buffer.bind_graphics_descriptor_sets(pipeline_layout, 0, once(ds), empty()); - cmd_buffer.draw_indexed(chunk_start * 3..(curr_idx_idx * 3) + 1, 0, 0..1); - } - } else { - tex_repo.queue_load(current_chunk)? - } - - Ok(()) -} diff --git a/stockton-render/src/draw/draw_passes/ui.rs b/stockton-render/src/draw/draw_passes/ui.rs deleted file mode 100644 index 5e6c68e..0000000 --- a/stockton-render/src/draw/draw_passes/ui.rs +++ /dev/null @@ -1,348 +0,0 @@ -//! Minimal code for drawing any level, based on traits from stockton-levels - -use super::{util::TargetSpecificResources, DrawPass, IntoDrawPass}; -use crate::{ - draw::{ - buffers::{draw_buffers::DrawBuffers, ModifiableBuffer}, - builders::{ - pipeline::{ - CompletePipeline, PipelineSpecBuilder, VertexBufferSpec, - VertexPrimitiveAssemblerSpec, - }, - renderpass::RenderpassSpec, - shader::ShaderDesc, - }, - queue_negotiator::QueueNegotiator, - target::SwapchainProperties, - texture::{TexLoadQueue, TextureLoadConfig, TextureRepo}, - ui::UiTextures, - }, - error::{EnvironmentError, LockPoisoned}, - types::*, - UiState, -}; -use egui::{ClippedMesh, TextureId}; -use hal::{ - buffer::SubRange, - command::{ClearColor, ClearValue, RenderAttachmentInfo, SubpassContents}, - format::Format, - image::Layout, - pass::{Attachment, AttachmentLoadOp, AttachmentOps, AttachmentStoreOp}, - pso::{ - BlendDesc, BlendOp, BlendState, ColorBlendDesc, ColorMask, DepthStencilDesc, Face, Factor, - FrontFace, InputAssemblerDesc, LogicOp, PolygonMode, Primitive, Rasterizer, Rect, - ShaderStageFlags, State, VertexInputRate, - }, -}; -use shaderc::ShaderKind; -use stockton_types::{Session, Vector2}; - -use std::{ - array::IntoIter, - convert::TryInto, - iter::{empty, once}, - sync::{Arc, RwLock}, -}; - -use anyhow::{anyhow, Context, Result}; - -#[derive(Debug)] -pub struct UiPoint(pub Vector2, pub Vector2, pub [f32; 4]); - -/// Draw a Ui object -pub struct UiDrawPass<'a> { - pipeline: CompletePipeline, - repo: TextureRepo, - draw_buffers: DrawBuffers<'a, UiPoint>, - - framebuffers: TargetSpecificResources<FramebufferT>, -} - -impl<'a> DrawPass for UiDrawPass<'a> { - fn queue_draw( - &mut self, - session: &Session, - img_view: &ImageViewT, - cmd_buffer: &mut crate::types::CommandBufferT, - ) -> anyhow::Result<()> { - // We might have loaded more textures - self.repo.process_responses(); - - // Make sure we update the vertex buffers after they're written to, but before they're read from. - self.draw_buffers - .vertex_buffer - .record_commit_cmds(cmd_buffer)?; - self.draw_buffers - .index_buffer - .record_commit_cmds(cmd_buffer)?; - - // Get level & camera - let ui: &mut UiState = &mut session.resources.get_mut::<UiState>().unwrap(); - - // Get framebuffer and depth buffer - let fb = self.framebuffers.get_next(); - unsafe { - cmd_buffer.begin_render_pass( - &self.pipeline.renderpass, - fb, - self.pipeline.render_area, - vec![RenderAttachmentInfo { - image_view: img_view, - clear_value: ClearValue { - color: ClearColor { - float32: [0.0, 0.0, 0.0, 1.0], - }, - }, - }] - .into_iter(), - SubpassContents::Inline, - ); - cmd_buffer.bind_graphics_pipeline(&self.pipeline.pipeline); - - // Bind buffers - cmd_buffer.bind_vertex_buffers( - 0, - once(( - self.draw_buffers.vertex_buffer.get_buffer(), - SubRange { - offset: 0, - size: None, - }, - )), - ); - cmd_buffer.bind_index_buffer( - self.draw_buffers.index_buffer.get_buffer(), - SubRange { - offset: 0, - size: None, - }, - hal::IndexType::U16, - ); - } - - let (_out, shapes) = ui.end_frame(); - let screen = ui.dimensions().ok_or(anyhow!("UI not set up properly."))?; - let shapes = ui.ctx().tessellate(shapes); - - for ClippedMesh(rect, tris) in shapes.iter() { - assert!(tris.texture_id == TextureId::Egui); - - // Copy triangles/indicies - for i in (0..tris.indices.len()).step_by(3) { - self.draw_buffers.index_buffer[i / 3] = ( - tris.indices[i].try_into()?, - tris.indices[i + 1].try_into()?, - tris.indices[i + 2].try_into()?, - ); - } - for (i, vertex) in tris.vertices.iter().enumerate() { - self.draw_buffers.vertex_buffer[i] = UiPoint( - Vector2::new(vertex.pos.x, vertex.pos.y), - Vector2::new(vertex.uv.x, vertex.uv.y), - [ - vertex.color.r() as f32 / 255.0, - vertex.color.g() as f32 / 255.0, - vertex.color.b() as f32 / 255.0, - vertex.color.a() as f32 / 255.0, - ], - ); - } - // TODO: *Properly* deal with textures - if let Some(ds) = self.repo.attempt_get_descriptor_set(0) { - unsafe { - cmd_buffer.push_graphics_constants( - &self.pipeline.pipeline_layout, - ShaderStageFlags::VERTEX, - 0, - &[screen.x.to_bits(), screen.y.to_bits()], - ); - - cmd_buffer.set_scissors( - 0, - IntoIter::new([Rect { - x: rect.min.x as i16, - y: rect.min.y as i16, - w: rect.width() as i16, - h: rect.height() as i16, - }]), - ); - cmd_buffer.bind_graphics_descriptor_sets( - &self.pipeline.pipeline_layout, - 0, - IntoIter::new([ds]), - empty(), - ); - // Call draw - cmd_buffer.draw_indexed(0..tris.indices.len() as u32, 0, 0..1); - } - } else { - self.repo.queue_load(0)?; - } - } - - unsafe { - cmd_buffer.end_render_pass(); - } - - Ok(()) - } - - fn deactivate(self, device_lock: &mut Arc<RwLock<DeviceT>>) -> Result<()> { - unsafe { - let mut device = device_lock.write().map_err(|_| LockPoisoned::Device)?; - self.pipeline.deactivate(&mut device); - self.draw_buffers.deactivate(&mut device); - for fb in self.framebuffers.dissolve() { - device.destroy_framebuffer(fb); - } - } - self.repo.deactivate(device_lock); - - Ok(()) - } -} - -impl<'a> IntoDrawPass<UiDrawPass<'a>> for () { - fn init( - self, - session: &Session, - adapter: &Adapter, - device_lock: Arc<RwLock<DeviceT>>, - queue_negotiator: &mut QueueNegotiator, - swapchain_properties: &SwapchainProperties, - ) -> Result<UiDrawPass<'a>> { - let spec = PipelineSpecBuilder::default() - .rasterizer(Rasterizer { - polygon_mode: PolygonMode::Fill, - cull_face: Face::NONE, - front_face: FrontFace::CounterClockwise, - depth_clamping: false, - depth_bias: None, - conservative: true, - line_width: State::Static(1.0), - }) - .depth_stencil(DepthStencilDesc { - depth: None, - depth_bounds: false, - stencil: None, - }) - .blender(BlendDesc { - logic_op: Some(LogicOp::Copy), - targets: vec![ColorBlendDesc { - mask: ColorMask::ALL, - blend: Some(BlendState { - color: BlendOp::Add { - src: Factor::SrcAlpha, - dst: Factor::OneMinusSrcAlpha, - }, - alpha: BlendOp::Add { - src: Factor::SrcAlpha, - dst: Factor::OneMinusSrcAlpha, - }, - }), - }], - }) - .primitive_assembler(VertexPrimitiveAssemblerSpec::with_buffers( - InputAssemblerDesc::new(Primitive::TriangleList), - vec![VertexBufferSpec { - attributes: vec![Format::Rg32Sfloat, Format::Rg32Sfloat, Format::Rgba32Sfloat], - rate: VertexInputRate::Vertex, - }], - )) - .shader_vertex(ShaderDesc { - source: include_str!("../ui/data/stockton.vert").to_string(), - entry: "main".to_string(), - kind: ShaderKind::Vertex, - }) - .shader_fragment(ShaderDesc { - source: include_str!("../ui/data/stockton.frag").to_string(), - entry: "main".to_string(), - kind: ShaderKind::Fragment, - }) - .push_constants(vec![(ShaderStageFlags::VERTEX, 0..8)]) - .renderpass(RenderpassSpec { - colors: vec![Attachment { - format: Some(swapchain_properties.format), - samples: 1, - ops: AttachmentOps::new(AttachmentLoadOp::Load, AttachmentStoreOp::Store), - stencil_ops: AttachmentOps::new( - AttachmentLoadOp::DontCare, - AttachmentStoreOp::DontCare, - ), - layouts: Layout::ColorAttachmentOptimal..Layout::ColorAttachmentOptimal, - }], - depth: None, - inputs: vec![], - resolves: vec![], - preserves: vec![], - }) - .dynamic_scissor(true) - .build() - .context("Error building pipeline")?; - - let ui: &mut UiState = &mut session.resources.get_mut::<UiState>().unwrap(); - let repo = TextureRepo::new( - device_lock.clone(), - queue_negotiator - .family::<TexLoadQueue>() - .ok_or(EnvironmentError::NoSuitableFamilies) - .context("Error finding texture queue")?, - queue_negotiator - .get_queue::<TexLoadQueue>() - .ok_or(EnvironmentError::NoQueues) - .context("Error finding texture queue")?, - adapter, - TextureLoadConfig { - resolver: UiTextures::new(ui.ctx().clone()), - filter: hal::image::Filter::Linear, - wrap_mode: hal::image::WrapMode::Clamp, - }, - ) - .context("Error creating texture repo")?; - - let (draw_buffers, pipeline, framebuffers) = { - let mut device = device_lock.write().map_err(|_| LockPoisoned::Device)?; - let draw_buffers = - DrawBuffers::new(&mut device, adapter).context("Error creating draw buffers")?; - let pipeline = spec - .build( - &mut device, - swapchain_properties.extent, - swapchain_properties, - once(&*repo.get_ds_layout()?), - ) - .context("Error building pipeline")?; - - let fat = swapchain_properties.framebuffer_attachment(); - let framebuffers = TargetSpecificResources::new( - || unsafe { - Ok(device.create_framebuffer( - &pipeline.renderpass, - IntoIter::new([fat.clone()]), - swapchain_properties.extent, - )?) - }, - swapchain_properties.image_count as usize, - )?; - (draw_buffers, pipeline, framebuffers) - }; - - Ok(UiDrawPass { - pipeline, - repo, - draw_buffers, - framebuffers, - }) - } - - fn find_aux_queues<'c>( - adapter: &'c Adapter, - queue_negotiator: &mut QueueNegotiator, - ) -> Result<Vec<(&'c QueueFamilyT, Vec<f32>)>> { - queue_negotiator.find(adapter, &TexLoadQueue)?; - - Ok(vec![queue_negotiator - .family_spec::<TexLoadQueue>(&adapter.queue_families, 1) - .ok_or(EnvironmentError::NoSuitableFamilies)?]) - } -} diff --git a/stockton-render/src/draw/mod.rs b/stockton-render/src/draw/mod.rs deleted file mode 100644 index 4ba38cd..0000000 --- a/stockton-render/src/draw/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Given 3D points and some camera information, renders to the screen. - -pub mod target; - -mod buffers; -mod builders; -pub mod camera; -mod context; -pub mod draw_passes; -mod queue_negotiator; -pub mod texture; -mod ui; -mod utils; - -pub use self::context::RenderingContext; - -pub use self::draw_passes::*; diff --git a/stockton-render/src/draw/ui/data/stockton.frag b/stockton-render/src/draw/ui/data/stockton.frag deleted file mode 100644 index c30c99e..0000000 --- a/stockton-render/src/draw/ui/data/stockton.frag +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 -#extension GL_ARB_separate_shader_objects : enable - -// 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 vec4 frag_col; - -layout (location = 0) out vec4 color; - -void main() { - color = texture(sampler2D(tex[0], samp[0]), frag_uv) * frag_col; -}
\ 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 deleted file mode 100644 index 8912e96..0000000 --- a/stockton-render/src/draw/ui/data/stockton.vert +++ /dev/null @@ -1,37 +0,0 @@ -#version 450 - -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 vec4 col; - -out gl_PerVertex { - vec4 gl_Position; -}; -layout (location = 1) out vec2 frag_uv; -layout (location = 2) out vec4 frag_col; - -vec3 linear_from_srgb(vec3 srgb) { - bvec3 cutoff = lessThan(srgb, vec3(10.31475)); - vec3 lower = srgb / vec3(3294.6); - vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); - return mix(higher, lower, cutoff); -} - -vec4 linear_from_srgba(vec4 srgba) { - return vec4(linear_from_srgb(srgba.rgb * 255.0), srgba.a); -} - -void main() { - gl_Position = vec4( - 2.0 * pos.x / push.screen_size.x - 1.0, - 2.0 * pos.y / push.screen_size.y - 1.0, - 0.0, - 1.0 - ); - frag_uv = uv; - frag_col = linear_from_srgba(col); -} diff --git a/stockton-render/src/draw/ui/mod.rs b/stockton-render/src/draw/ui/mod.rs deleted file mode 100644 index 1b52753..0000000 --- a/stockton-render/src/draw/ui/mod.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::draw::texture::{resolver::TextureResolver, LoadableImage}; -use egui::{CtxRef, Texture}; -use std::{convert::TryInto, sync::Arc}; - -pub struct UiTextures { - ctx: CtxRef, -} - -impl TextureResolver for UiTextures { - type Image = Arc<Texture>; - fn resolve(&mut self, tex: u32) -> Option<Self::Image> { - if tex == 0 { - Some(self.ctx.texture()) - } else { - None - } - } -} - -impl UiTextures { - pub fn new(ctx: CtxRef) -> Self { - UiTextures { ctx } - } -} - -impl LoadableImage for Arc<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 * 4) = 255; - *ptr.offset((i as isize * 4) + 1) = 255; - *ptr.offset((i as isize * 4) + 2) = 255; - *ptr.offset((i as isize * 4) + 3) = *x; - } - } - } - - unsafe fn copy_into(&self, ptr: *mut u8, row_size: usize) { - for y in 0..self.height() { - self.copy_row(y, ptr.offset((row_size * y as usize).try_into().unwrap())); - } - } -} diff --git a/stockton-render/src/draw/draw_passes/cons.rs b/stockton-render/src/draw_passes/cons.rs index 3209806..ad94b1c 100644 --- a/stockton-render/src/draw/draw_passes/cons.rs +++ b/stockton-render/src/draw_passes/cons.rs @@ -1,10 +1,8 @@ //! Code for using multiple draw passes in place of just one //! Note that this can be extended to an arbitrary amount of draw passes. -use std::sync::{Arc, RwLock}; - use super::{DrawPass, IntoDrawPass}; -use crate::types::*; +use crate::{context::RenderingContext, queue_negotiator::QueueNegotiator, types::*}; use stockton_types::Session; use anyhow::Result; @@ -28,9 +26,18 @@ impl<A: DrawPass, B: DrawPass> DrawPass for ConsDrawPass<A, B> { Ok(()) } - fn deactivate(self, device: &mut Arc<RwLock<DeviceT>>) -> Result<()> { - self.a.deactivate(device)?; - self.b.deactivate(device) + fn deactivate(self, context: &mut RenderingContext) -> Result<()> { + self.a.deactivate(context)?; + self.b.deactivate(context) + } + + fn handle_surface_change( + &mut self, + session: &Session, + context: &mut RenderingContext, + ) -> Result<()> { + self.a.handle_surface_change(session, context)?; + self.b.handle_surface_change(session, context) } } @@ -39,33 +46,18 @@ impl<A: DrawPass, B: DrawPass, IA: IntoDrawPass<A>, IB: IntoDrawPass<B>> { fn init( self, - session: &Session, - adapter: &Adapter, - device: Arc<RwLock<DeviceT>>, - queue_negotiator: &mut crate::draw::queue_negotiator::QueueNegotiator, - swapchain_properties: &crate::draw::target::SwapchainProperties, + session: &mut Session, + context: &mut RenderingContext, ) -> Result<ConsDrawPass<A, B>> { Ok(ConsDrawPass { - a: self.0.init( - session, - adapter, - device.clone(), - queue_negotiator, - swapchain_properties, - )?, - b: self.1.init( - session, - adapter, - device, - queue_negotiator, - swapchain_properties, - )?, + a: self.0.init(session, context)?, + b: self.1.init(session, context)?, }) } fn find_aux_queues<'a>( adapter: &'a Adapter, - queue_negotiator: &mut crate::draw::queue_negotiator::QueueNegotiator, + queue_negotiator: &mut QueueNegotiator, ) -> Result<Vec<(&'a QueueFamilyT, Vec<f32>)>> { let mut v = IA::find_aux_queues(adapter, queue_negotiator)?; v.extend(IB::find_aux_queues(adapter, queue_negotiator)?); diff --git a/stockton-render/src/draw/draw_passes/mod.rs b/stockton-render/src/draw_passes/mod.rs index 8d1d59b..a0dbba5 100644 --- a/stockton-render/src/draw/draw_passes/mod.rs +++ b/stockton-render/src/draw_passes/mod.rs @@ -1,20 +1,14 @@ //! Traits and common draw passes. -use super::{queue_negotiator::QueueNegotiator, target::SwapchainProperties}; +use super::{queue_negotiator::QueueNegotiator, RenderingContext}; use crate::types::*; use stockton_types::Session; -use std::sync::{Arc, RwLock}; - use anyhow::Result; mod cons; -mod level; -mod ui; pub mod util; pub use cons::ConsDrawPass; -pub use level::{LevelDrawPass, LevelDrawPassConfig}; -pub use ui::UiDrawPass; /// One of several 'passes' that draw on each frame. pub trait DrawPass { @@ -27,20 +21,21 @@ pub trait DrawPass { cmd_buffer: &mut CommandBufferT, ) -> Result<()>; - fn deactivate(self, device: &mut Arc<RwLock<DeviceT>>) -> Result<()>; + /// Called just after the surface changes (probably a resize). + fn handle_surface_change( + &mut self, + session: &Session, + context: &mut RenderingContext, + ) -> Result<()>; + + /// Deactivate any vulkan parts that need to be deactivated + fn deactivate(self, context: &mut RenderingContext) -> Result<()>; } /// A type that can be made into a specific draw pass type. /// This allows extra data to be used in initialisation without the Renderer needing to worry about it. -pub trait IntoDrawPass<O: DrawPass> { - fn init( - self, - session: &Session, - adapter: &Adapter, - device: Arc<RwLock<DeviceT>>, - queue_negotiator: &mut QueueNegotiator, - swapchain_properties: &SwapchainProperties, - ) -> Result<O>; +pub trait IntoDrawPass<T: DrawPass> { + fn init(self, session: &mut Session, context: &mut RenderingContext) -> Result<T>; /// This function should ask the queue negotatior to find families for any auxilary operations this draw pass needs to perform /// For example, .find(&TexLoadQueue) diff --git a/stockton-render/src/draw/draw_passes/util.rs b/stockton-render/src/draw_passes/util.rs index 5a4eb1a..5a4eb1a 100644 --- a/stockton-render/src/draw/draw_passes/util.rs +++ b/stockton-render/src/draw_passes/util.rs diff --git a/stockton-render/src/lib.rs b/stockton-render/src/lib.rs index 37acf27..03f6d53 100644 --- a/stockton-render/src/lib.rs +++ b/stockton-render/src/lib.rs @@ -6,86 +6,87 @@ extern crate nalgebra_glm as na; #[macro_use] extern crate derive_builder; -#[macro_use] -extern crate legion; - -pub mod draw; +pub mod buffers; +pub mod builders; +pub mod context; +pub mod draw_passes; pub mod error; -pub mod systems; -mod types; -pub mod window; - -use draw::{ - draw_passes::{DrawPass, IntoDrawPass}, - RenderingContext, -}; +pub mod queue_negotiator; +mod target; +pub mod texture; +pub mod types; +pub mod utils; -use std::sync::mpsc::{Receiver, Sender}; -use std::sync::Arc; -use std::sync::RwLock; -pub use window::{UiState, WindowEvent}; +use context::RenderingContext; +use draw_passes::{DrawPass, IntoDrawPass}; -use anyhow::Result; +use anyhow::{Context, Result}; use stockton_types::Session; -use winit::event_loop::ControlFlow; use winit::window::Window; -use std::sync::mpsc::channel; - /// Renders a world to a window when you tell it to. /// Also takes ownership of the window and channels window events to be processed outside winit's event loop. pub struct Renderer<DP> { /// All the vulkan stuff - pub(crate) context: RenderingContext<DP>, - - /// For getting events from the winit event loop - pub window_events: Receiver<WindowEvent>, + context: RenderingContext, - /// For updating the control flow of the winit event loop - pub update_control_flow: Arc<RwLock<ControlFlow>>, + /// The draw pass we're using + draw_pass: DP, } impl<DP: DrawPass> Renderer<DP> { /// Create a new Renderer. pub fn new<IDP: IntoDrawPass<DP>>( window: &Window, - session: &Session, + session: &mut Session, idp: IDP, - ) -> Result<(Self, Sender<WindowEvent>)> { - let (tx, rx) = channel(); - let update_control_flow = Arc::new(RwLock::new(ControlFlow::Poll)); - - Ok(( - Renderer { - context: RenderingContext::new(window, session, idp)?, - window_events: rx, - update_control_flow, - }, - tx, - )) + ) -> Result<Self> { + let mut context = RenderingContext::new::<IDP, DP>(window)?; + + // Draw pass + let draw_pass = idp + .init(session, &mut context) + .context("Error initialising draw pass")?; + + Ok(Renderer { context, draw_pass }) } /// Render a single frame of the given session. pub fn render(&mut self, session: &Session) -> Result<()> { // Try to draw - if self.context.draw_next_frame(session).is_err() { + if self + .context + .draw_next_frame(session, &mut self.draw_pass) + .is_err() + { // Probably the surface changed - unsafe { self.context.handle_surface_change()? }; + self.handle_surface_change(session)?; // If it fails twice, then error - self.context.draw_next_frame(session)?; + self.context.draw_next_frame(session, &mut self.draw_pass)?; } Ok(()) } pub fn get_aspect_ratio(&self) -> f32 { - let e = self.context.target_chain.properties.extent; + let e = self.context.target_chain().properties().extent; e.width as f32 / e.height as f32 } - fn resize(&mut self) -> Result<()> { - unsafe { self.context.handle_surface_change() } + pub fn handle_surface_change(&mut self, session: &Session) -> Result<()> { + unsafe { + self.context.handle_surface_change()?; + self.draw_pass + .handle_surface_change(session, &mut self.context)?; + } + + Ok(()) + } + + /// Get a reference to the renderer's context. + pub fn context(&self) -> &RenderingContext { + &self.context } } diff --git a/stockton-render/src/draw/queue_negotiator.rs b/stockton-render/src/queue_negotiator.rs index 65c7aa4..65c7aa4 100644 --- a/stockton-render/src/draw/queue_negotiator.rs +++ b/stockton-render/src/queue_negotiator.rs diff --git a/stockton-render/src/systems.rs b/stockton-render/src/systems.rs deleted file mode 100644 index 5f86c29..0000000 --- a/stockton-render/src/systems.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub use crate::draw::camera::calc_vp_matrix_system; -pub use crate::window::process_window_events_system; diff --git a/stockton-render/src/draw/target.rs b/stockton-render/src/target.rs index 3861192..d0d2380 100644 --- a/stockton-render/src/draw/target.rs +++ b/stockton-render/src/target.rs @@ -122,15 +122,15 @@ impl SwapchainProperties { pub struct TargetChain { /// Surface we're targeting - pub surface: ManuallyDrop<SurfaceT>, - pub properties: SwapchainProperties, + surface: ManuallyDrop<SurfaceT>, + properties: SwapchainProperties, /// Resources tied to each target frame in the swapchain - pub targets: Box<[TargetResources]>, + targets: Box<[TargetResources]>, /// Sync objects used in drawing /// These are seperated from the targets because we don't necessarily always match up indexes - pub sync_objects: Box<[SyncObjects]>, + sync_objects: Box<[SyncObjects]>, /// The last set of sync objects used last_syncs: usize, @@ -327,6 +327,11 @@ impl TargetChain { Ok(()) } + + /// Get a reference to the target chain's properties. + pub fn properties(&self) -> &SwapchainProperties { + &self.properties + } } /// Resources for a single target frame, including sync objects diff --git a/stockton-render/src/draw/texture/block.rs b/stockton-render/src/texture/block.rs index 5ac3a94..5ac3a94 100644 --- a/stockton-render/src/draw/texture/block.rs +++ b/stockton-render/src/texture/block.rs diff --git a/stockton-render/src/draw/texture/image.rs b/stockton-render/src/texture/image.rs index 0e272e9..0e272e9 100644 --- a/stockton-render/src/draw/texture/image.rs +++ b/stockton-render/src/texture/image.rs diff --git a/stockton-render/src/draw/texture/load.rs b/stockton-render/src/texture/load.rs index 1f33ad5..1f33ad5 100644 --- a/stockton-render/src/draw/texture/load.rs +++ b/stockton-render/src/texture/load.rs diff --git a/stockton-render/src/draw/texture/loader.rs b/stockton-render/src/texture/loader.rs index e6c19db..f9c643c 100644 --- a/stockton-render/src/draw/texture/loader.rs +++ b/stockton-render/src/texture/loader.rs @@ -7,7 +7,7 @@ use super::{ resolver::TextureResolver, PIXEL_SIZE, }; -use crate::{draw::utils::find_memory_type_id, error::LockPoisoned, types::*}; +use crate::{error::LockPoisoned, types::*, utils::find_memory_type_id}; use std::{ array::IntoIter, diff --git a/stockton-render/src/draw/texture/mod.rs b/stockton-render/src/texture/mod.rs index aef1b03..aef1b03 100644 --- a/stockton-render/src/draw/texture/mod.rs +++ b/stockton-render/src/texture/mod.rs diff --git a/stockton-render/src/draw/texture/repo.rs b/stockton-render/src/texture/repo.rs index e427eef..e29625b 100644 --- a/stockton-render/src/draw/texture/repo.rs +++ b/stockton-render/src/texture/repo.rs @@ -4,8 +4,8 @@ use super::{ loader::{BlockRef, LoaderRequest, TextureLoader, TextureLoaderRemains, NUM_SIMULTANEOUS_CMDS}, resolver::TextureResolver, }; -use crate::draw::queue_negotiator::QueueFamilySelector; use crate::error::LockPoisoned; +use crate::queue_negotiator::QueueFamilySelector; use crate::types::*; use std::{ @@ -153,7 +153,7 @@ impl TextureRepo { } } - pub fn deactivate(mut self, device_lock: &mut Arc<RwLock<DeviceT>>) { + pub fn deactivate(mut self, device_lock: &Arc<RwLock<DeviceT>>) { unsafe { use std::ptr::read; diff --git a/stockton-render/src/draw/texture/resolver.rs b/stockton-render/src/texture/resolver.rs index 4b61c41..f66b724 100644 --- a/stockton-render/src/draw/texture/resolver.rs +++ b/stockton-render/src/texture/resolver.rs @@ -1,6 +1,6 @@ //! Resolves a texture in a BSP File to an image -use crate::draw::texture::image::LoadableImage; +use crate::texture::image::LoadableImage; use stockton_levels::{parts::IsTexture, prelude::HasTextures}; use std::{ diff --git a/stockton-render/src/draw/texture/staging_buffer.rs b/stockton-render/src/texture/staging_buffer.rs index 8d2ae17..8d2ae17 100644 --- a/stockton-render/src/draw/texture/staging_buffer.rs +++ b/stockton-render/src/texture/staging_buffer.rs diff --git a/stockton-render/src/draw/utils.rs b/stockton-render/src/utils.rs index 2ab984b..152ba10 100644 --- a/stockton-render/src/draw/utils.rs +++ b/stockton-render/src/utils.rs @@ -1,5 +1,5 @@ use crate::types::*; -use hal::{memory::Properties as MemProperties, prelude::*, MemoryTypeId}; +use hal::{memory::Properties as MemProperties, MemoryTypeId}; pub fn find_memory_type_id( adapter: &Adapter, diff --git a/stockton-render/src/window.rs b/stockton-render/src/window.rs deleted file mode 100644 index 87f3182..0000000 --- a/stockton-render/src/window.rs +++ /dev/null @@ -1,239 +0,0 @@ -use crate::{error::full_error_display, DrawPass, Renderer}; -use egui::{Modifiers, Rect, Vec2}; -use legion::systems::Runnable; -use log::debug; - -use egui::{CtxRef, Event, Output, Pos2, RawInput}; -use epaint::ClippedShape; -use log::error; -use stockton_input::{Action as KBAction, InputManager, Mouse}; - -use winit::event::{ - ElementState, Event as WinitEvent, MouseButton, WindowEvent as WinitWindowEvent, -}; -use winit::event_loop::ControlFlow; - -#[derive(Debug, Clone, Copy)] -pub enum WindowEvent { - SizeChanged(u32, u32), - CloseRequested, - KeyboardAction(KBAction), - MouseAction(KBAction), - MouseMoved(f32, f32), - MouseLeft, -} - -impl WindowEvent { - pub fn from(winit_event: &WinitEvent<()>) -> Option<WindowEvent> { - // TODO - match winit_event { - WinitEvent::WindowEvent { event, .. } => match event { - WinitWindowEvent::CloseRequested => Some(WindowEvent::CloseRequested), - WinitWindowEvent::Resized(size) => { - Some(WindowEvent::SizeChanged(size.width, size.height)) - } - WinitWindowEvent::KeyboardInput { input, .. } => match input.state { - ElementState::Pressed => Some(WindowEvent::KeyboardAction(KBAction::KeyPress( - input.scancode, - ))), - ElementState::Released => Some(WindowEvent::KeyboardAction( - KBAction::KeyRelease(input.scancode), - )), - }, - WinitWindowEvent::CursorMoved { position, .. } => Some(WindowEvent::MouseMoved( - position.x as f32, - position.y as f32, - )), - WinitWindowEvent::CursorLeft { .. } => Some(WindowEvent::MouseLeft), - WinitWindowEvent::MouseInput { button, state, .. } => { - let mb: stockton_input::MouseButton = match button { - MouseButton::Left => stockton_input::MouseButton::Left, - MouseButton::Right => stockton_input::MouseButton::Right, - MouseButton::Middle => stockton_input::MouseButton::Middle, - MouseButton::Other(x) => stockton_input::MouseButton::Other(*x), - }; - - match state { - ElementState::Pressed => { - Some(WindowEvent::MouseAction(KBAction::MousePress(mb))) - } - ElementState::Released => { - Some(WindowEvent::MouseAction(KBAction::MouseRelease(mb))) - } - } - } - _ => None, - }, - _ => None, - } - } -} - -pub struct UiState { - ctx: CtxRef, - raw_input: RawInput, - frame_active: bool, - - modifiers: Modifiers, - pointer_pos: Pos2, -} - -impl UiState { - pub fn new() -> Self { - UiState { - ctx: CtxRef::default(), - raw_input: RawInput::default(), - frame_active: false, - modifiers: Default::default(), - pointer_pos: Pos2::new(0.0, 0.0), - } - } - - pub fn populate_initial_state<'a, T: DrawPass>(&mut self, renderer: &Renderer<T>) { - let props = &renderer.context.target_chain.properties; - self.set_dimensions(props.extent.width, props.extent.height); - self.set_pixels_per_point(Some(renderer.context.pixels_per_point)); - debug!("{:?}", self.raw_input); - } - - #[inline] - pub fn ctx(&mut self) -> &CtxRef { - if !self.frame_active { - self.begin_frame() - } - &self.ctx - } - - #[inline] - fn begin_frame(&mut self) { - #[allow(deprecated)] - let new_raw_input = RawInput { - scroll_delta: Vec2::new(0.0, 0.0), - zoom_delta: 0.0, - screen_size: self.raw_input.screen_size, - screen_rect: self.raw_input.screen_rect, - pixels_per_point: self.raw_input.pixels_per_point, - time: self.raw_input.time, - predicted_dt: self.raw_input.predicted_dt, - modifiers: self.modifiers, - events: Vec::new(), - }; - self.ctx.begin_frame(self.raw_input.take()); - self.raw_input = new_raw_input; - self.frame_active = true; - } - - #[inline] - pub(crate) fn end_frame(&mut self) -> (Output, Vec<ClippedShape>) { - self.frame_active = false; - self.ctx.end_frame() - } - - #[inline] - pub fn dimensions(&self) -> Option<egui::math::Vec2> { - Some(self.raw_input.screen_rect?.size()) - } - - fn set_mouse_pos(&mut self, x: f32, y: f32) { - self.raw_input - .events - .push(Event::PointerMoved(Pos2::new(x, y))); - - self.pointer_pos = Pos2::new(x, y); - } - - fn set_mouse_left(&mut self) { - self.raw_input.events.push(Event::PointerGone); - } - - fn set_dimensions(&mut self, w: u32, h: u32) { - self.raw_input.screen_rect = - Some(Rect::from_x_y_ranges(0.0..=(w as f32), 0.0..=(h as f32))); - } - fn set_pixels_per_point(&mut self, ppp: Option<f32>) { - debug!("Using {:?} pixels per point", ppp); - self.raw_input.pixels_per_point = ppp; - } - - fn handle_action(&mut self, action: KBAction) { - // TODO - match action { - KBAction::MousePress(stockton_input::MouseButton::Left) => { - self.raw_input.events.push(Event::PointerButton { - pos: self.pointer_pos, - button: egui::PointerButton::Primary, - pressed: true, - modifiers: self.modifiers, - }); - } - _ => (), - } - } -} - -#[system] -/// A system to process the window events sent to renderer by the winit event loop. -pub fn _process_window_events<T: 'static + InputManager, DP: 'static + DrawPass>( - #[resource] renderer: &mut Renderer<DP>, - #[resource] manager: &mut T, - #[resource] mouse: &mut Mouse, - #[resource] ui_state: &mut UiState, - #[state] actions_buf: &mut Vec<KBAction>, -) { - let mut actions_buf_cursor = 0; - let mut mouse_delta = mouse.abs; - - while let Ok(event) = renderer.window_events.try_recv() { - match event { - WindowEvent::SizeChanged(w, h) => { - if let Err(err) = renderer.resize() { - error!("{}", full_error_display(err)); - }; - ui_state.set_dimensions(w, h); - } - WindowEvent::CloseRequested => { - let mut flow = renderer.update_control_flow.write().unwrap(); - // TODO: Let everything know this is our last frame - *flow = ControlFlow::Exit; - } - WindowEvent::KeyboardAction(action) => { - if actions_buf_cursor >= actions_buf.len() { - actions_buf.push(action); - } else { - actions_buf[actions_buf_cursor] = action; - } - actions_buf_cursor += 1; - - ui_state.handle_action(action); - } - WindowEvent::MouseMoved(x, y) => { - mouse_delta.x = x; - mouse_delta.y = y; - - ui_state.set_mouse_pos(x, y); - } - WindowEvent::MouseLeft => { - ui_state.set_mouse_left(); - } - WindowEvent::MouseAction(action) => { - if actions_buf_cursor >= actions_buf.len() { - actions_buf.push(action); - } else { - actions_buf[actions_buf_cursor] = action; - } - actions_buf_cursor += 1; - - ui_state.handle_action(action); - } - }; - } - - mouse.handle_frame(mouse_delta); - - manager.handle_frame(&actions_buf[0..actions_buf_cursor]); -} - -pub fn process_window_events_system<T: 'static + InputManager, DP: 'static + DrawPass>( -) -> impl Runnable { - _process_window_events_system::<T, DP>(Vec::with_capacity(4)) -} |