diff --git a/src/app/mod.rs b/src/app/mod.rs index a9adefe..b0b93ab 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -18,7 +18,7 @@ use winit::{ event_loop::ControlFlow, }; -use crate::render::{self, context::Renderable, texture::Texture}; +use crate::render::{self, Renderable, texture::Texture, Renderer}; const FPS_POLL_TIME: f32 = 0.5; const SPRITES_PATH: &str = "assets/images"; @@ -31,24 +31,27 @@ pub enum StateTransition { Exit, } -pub struct Context<'app> { - pub audio: &'app mut AudioManager, - pub renderer: &'app mut render::Renderer, - pub keyboard: &'app KeyboardState, - pub textures: &'app mut TextureCache, - pub mouse: &'app MouseState, +pub struct Context<'ctx> { + pub audio: &'ctx mut AudioManager, + pub renderer: &'ctx mut render::Renderer, + pub keyboard: &'ctx KeyboardState, + pub textures: &'ctx mut TextureCache, + pub mouse: &'ctx MouseState, } -pub struct RenderContext<'app, 'pass> { - pub audio: &'app mut AudioManager, - pub render_pass: &'app mut render::RenderPassContext<'pass>, - pub keyboard: &'app KeyboardState, - pub textures: &'app mut TextureCache, +pub struct RenderContext<'ctx, 'pass> { + pub audio: &'ctx mut AudioManager, + pub renderer: &'pass Renderer, + pub textures: &'ctx mut TextureCache, + pub keyboard: &'ctx KeyboardState, + pub mouse: &'ctx MouseState, + + pub render_pass: &'ctx mut wgpu::RenderPass<'pass>, } impl<'pass> RenderContext<'_, 'pass> { pub fn render(&mut self, target: &'pass R) { - self.render_pass.render(target); + target.render(self.renderer, self.render_pass); } } @@ -291,12 +294,14 @@ impl App { } } - pub fn render<'pass>(&'pass mut self, rctx: &mut render::RenderPassContext<'pass>) { + pub fn render<'pass>(&'pass mut self, renderer: &'pass Renderer, render_pass: &mut wgpu::RenderPass<'pass>) { let mut ctx = RenderContext { audio: &mut self.audio_manager, - render_pass: rctx, + renderer, keyboard: &self.keyboard, + mouse: &self.mouse, textures: &mut self.textures, + render_pass, }; self.state.last_mut().unwrap().render(&mut ctx) diff --git a/src/app/taiko_mode/mod.rs b/src/app/taiko_mode/mod.rs index 2c4402e..1481372 100644 --- a/src/app/taiko_mode/mod.rs +++ b/src/app/taiko_mode/mod.rs @@ -500,7 +500,7 @@ impl GameState for TaikoMode { 0.0, 0.0, ], - ctx.render_pass.queue, + &ctx.renderer.queue, ); ctx.render(v_barline); @@ -514,7 +514,7 @@ impl GameState for TaikoMode { NOTE_Y, note.time, ], - ctx.render_pass.queue, + &ctx.renderer.queue, ); ctx.render(v_note) @@ -532,7 +532,7 @@ impl GameState for TaikoMode { self.ui.judgement_text[i] .sprite - .set_position([0.0, -10.0 * progress + 5.0, 0.0], ctx.render_pass.queue); + .set_position([0.0, -10.0 * progress + 5.0, 0.0], &ctx.renderer.queue); ctx.render(&self.ui.judgement_text[i]); } diff --git a/src/app/taiko_mode/note.rs b/src/app/taiko_mode/note.rs index 3cca5a5..b3f11e2 100644 --- a/src/app/taiko_mode/note.rs +++ b/src/app/taiko_mode/note.rs @@ -1,13 +1,13 @@ use lyon::lyon_tessellation::TessellationError; use crate::beatmap_parser::track::NoteType; +use crate::render::Renderer; use crate::{app::TextureCache, render::shapes::ShapeBuilder}; use crate::render::{ - context::Renderable, + Renderable, shapes::{Shape, SolidColour}, texture::Sprite, - RenderPassContext, }; const ROLL_COLOUR: [f32; 4] = [1.0, 195.0 / 255.0, 44.0 / 255.0, 1.0]; @@ -141,14 +141,14 @@ impl VisualNote { } impl Renderable for VisualNote { - fn render<'a>(&'a self, ctx: &mut RenderPassContext<'a>) { + fn render<'pass>(&'pass self, renderer: &'pass Renderer, render_pass: &mut wgpu::RenderPass<'pass>) { match self { - VisualNote::Note(sprite) => sprite.render(ctx), + VisualNote::Note(sprite) => sprite.render(renderer, render_pass), VisualNote::Roll { start, body } => { // If start and body both have the same depth, then start should render on top // of the body, given the compare function is `LessEqual` - body.render(ctx); - start.render(ctx); + body.render(renderer, render_pass); + start.render(renderer, render_pass); } } } diff --git a/src/app/ui_elements/button.rs b/src/app/ui_elements/button.rs index 99d27b2..3b23b41 100644 --- a/src/app/ui_elements/button.rs +++ b/src/app/ui_elements/button.rs @@ -1,8 +1,8 @@ use crate::app::Context; -use crate::render::context::Renderable; +use crate::render::Renderable; use crate::render::shapes::{Shape, ShapeBuilder, ShapeVertex, SolidColour}; use crate::render::text::Text; -use crate::render::{RenderPassContext, Renderer}; +use crate::render::Renderer; use lyon::tessellation::FillVertexConstructor; use wgpu_text::glyph_brush; use wgpu_text::glyph_brush::{HorizontalAlign, Layout, Section, VerticalAlign}; @@ -100,14 +100,14 @@ impl Button { } impl Renderable for Button { - fn render<'pass>(&'pass self, ctx: &mut RenderPassContext<'pass>) { - self.shadow.render(ctx); - self.bg.render(ctx); - self.text.render(ctx); + fn render<'pass>(&'pass self, renderer: &'pass Renderer, render_pass: &mut wgpu::RenderPass<'pass>) { + self.shadow.render(renderer, render_pass); + self.bg.render(renderer, render_pass); + self.text.render(renderer, render_pass); if self.mouse_entered { - self.hover_overlay.render(ctx); - self.outline.render(ctx); + self.hover_overlay.render(renderer, render_pass); + self.outline.render(renderer, render_pass); } } } diff --git a/src/render/context.rs b/src/render/context.rs deleted file mode 100644 index f2bd83c..0000000 --- a/src/render/context.rs +++ /dev/null @@ -1,35 +0,0 @@ -/// A handle to a [wgpu::RenderPass] and all the related resources needed to render things in the -/// render pass. -pub struct RenderPassContext<'pass> { - pub render_pass: wgpu::RenderPass<'pass>, - pub device: &'pass wgpu::Device, - pub queue: &'pass wgpu::Queue, - pub pipeline_cache: &'pass Vec<(&'static str, wgpu::RenderPipeline)>, -} - -/// A trait that allows objects to render themselves to the screen in any given render pass. If a -/// type implements Renderable, then it is able to be rendered by the [RenderPassContext]'s render -/// function. -pub trait Renderable { - fn render<'pass>(&'pass self, ctx: &mut RenderPassContext<'pass>); -} - -impl<'pass> RenderPassContext<'pass> { - /// Renders the target object in the current render pass using its [Renderable] implementation. - pub fn render(&mut self, target: &'pass R) { - target.render(self); - } - - /// Gets the render pipeline referred to by the given name, if it exists. - pub fn pipeline(&self, name: &str) -> Option<&'pass wgpu::RenderPipeline> { - self.pipeline_cache.iter().find_map( - |(n, pipeline)| { - if name == *n { - Some(pipeline) - } else { - None - } - }, - ) - } -} diff --git a/src/render/mod.rs b/src/render/mod.rs index 56264dd..032b371 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -21,13 +21,17 @@ const SAMPLE_COUNT: u32 = 4; const CLEAR_COLOUR: wgpu::Color = wgpu::Color::BLACK; const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; -pub mod context; mod egui; pub mod shapes; pub mod text; pub mod texture; -pub use context::RenderPassContext; +/// A trait that allows objects to render themselves to the screen in any given render pass. If a +/// type implements Renderable, then it is able to be rendered by the [RenderPassContext]'s render +/// function. +pub trait Renderable { + fn render<'pass>(&'pass self, renderer: &'pass Renderer, render_pass: &mut wgpu::RenderPass<'pass>); +} #[repr(C)] #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] @@ -480,7 +484,7 @@ impl Renderer { &self.window, ); - let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Render pass"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: if SAMPLE_COUNT == 1 { @@ -508,23 +512,15 @@ impl Renderer { .queue(&self.device, &self.queue, Vec::
::new()) .unwrap(); - let mut ctx = RenderPassContext { - render_pass, - device: &self.device, - queue: &self.queue, - pipeline_cache: &self.pipeline_cache, - }; - - ctx.render_pass - .set_bind_group(0, &self.screen_bind_group, &[]); + render_pass.set_bind_group(0, &self.screen_bind_group, &[]); // Rendering goes here... - app.render(&mut ctx); + app.render(self, &mut render_pass); self.egui_handler - .render(&mut ctx.render_pass, &paint_jobs, &screen_descriptor); + .render(&mut render_pass, &paint_jobs, &screen_descriptor); - drop(ctx); + drop(render_pass); self.queue.submit([encoder.finish()]); texture.present(); diff --git a/src/render/shapes.rs b/src/render/shapes.rs index 503b493..8b12883 100644 --- a/src/render/shapes.rs +++ b/src/render/shapes.rs @@ -19,7 +19,7 @@ use wgpu::{ vertex_attr_array, }; -use super::{context::Renderable, SpriteInstance}; +use super::{Renderable, Renderer, SpriteInstance}; #[repr(C)] #[derive(Copy, Clone, Debug, bytemuck::Zeroable, bytemuck::Pod)] @@ -415,22 +415,22 @@ impl Shape { } impl Renderable for Shape { - fn render<'a>(&'a self, ctx: &mut super::RenderPassContext<'a>) { + fn render<'pass>(&'pass self, renderer: &'pass Renderer, render_pass: &mut wgpu::RenderPass<'pass>) { let pipeline = if self.has_depth { "primitive_depth" } else { "primitive" }; - ctx.render_pass.set_pipeline( - ctx.pipeline(pipeline) + render_pass.set_pipeline( + renderer.pipeline(pipeline) .unwrap_or_else(|| panic!("{pipeline} render pipeline doesn't exist!")), ); - ctx.render_pass.set_vertex_buffer(0, self.vertex.slice(..)); - ctx.render_pass + render_pass.set_vertex_buffer(0, self.vertex.slice(..)); + render_pass .set_vertex_buffer(1, self.instance.slice(..)); - ctx.render_pass + render_pass .set_index_buffer(self.index.slice(..), wgpu::IndexFormat::Uint32); - ctx.render_pass.draw_indexed(0..self.indices, 0, 0..1); + render_pass.draw_indexed(0..self.indices, 0, 0..1); } } diff --git a/src/render/text.rs b/src/render/text.rs index f3a9542..a51c255 100644 --- a/src/render/text.rs +++ b/src/render/text.rs @@ -2,7 +2,7 @@ use std::rc::Rc; use wgpu_text::glyph_brush::Section; -use crate::render::{context::Renderable, texture, RenderPassContext, Renderer}; +use crate::render::{Renderable, texture, Renderer}; #[derive(Debug)] pub struct Text { @@ -105,7 +105,7 @@ impl Text { } impl Renderable for Text { - fn render<'a>(&'a self, ctx: &mut RenderPassContext<'a>) { - ctx.render(&self.sprite); + fn render<'pass>(&'pass self, renderer: &'pass Renderer, render_pass: &mut wgpu::RenderPass<'pass>) { + self.sprite.render(renderer, render_pass); } } diff --git a/src/render/texture.rs b/src/render/texture.rs index 1339c1c..84ebbfe 100644 --- a/src/render/texture.rs +++ b/src/render/texture.rs @@ -1,6 +1,5 @@ //! Various types used for drawing textures -use crate::render; use image::GenericImageView; use std::{path::Path, rc::Rc, sync::OnceLock}; use wgpu::{ @@ -8,7 +7,7 @@ use wgpu::{ vertex_attr_array, }; -use super::context::Renderable; +use super::{Renderable, Renderer}; static TEXTURE_BIND_GROUP_LAYOUT: OnceLock = OnceLock::new(); @@ -318,25 +317,25 @@ impl Sprite { } impl Renderable for Sprite { - fn render<'a>(&'a self, ctx: &mut render::context::RenderPassContext<'a>) { - ctx.render_pass.set_pipeline( - ctx.pipeline(if self.use_depth { + fn render<'pass>(&'pass self, renderer: &'pass Renderer, render_pass: &mut wgpu::RenderPass<'pass>) { + render_pass.set_pipeline( + renderer.pipeline(if self.use_depth { "texture_depth" } else { "texture" }) .expect("texture render pipeline does not exist!"), ); - ctx.render_pass + render_pass .set_vertex_buffer(0, self.texture.vertex_buffer.slice(..)); - ctx.render_pass.set_index_buffer( + render_pass.set_index_buffer( self.texture.index_buffer.slice(..), wgpu::IndexFormat::Uint16, ); - ctx.render_pass + render_pass .set_bind_group(1, &self.texture.bind_group, &[]); - ctx.render_pass + render_pass .set_vertex_buffer(1, self.instance_buffer.slice(..)); - ctx.render_pass.draw_indexed(0..6 as _, 0, 0..1); + render_pass.draw_indexed(0..6 as _, 0, 0..1); } }