From 2d2c88a704455f5dc3e14b557bd52eefcec14d2e Mon Sep 17 00:00:00 2001 From: Micha White Date: Sun, 18 Sep 2022 21:18:23 -0400 Subject: Some optimization --- src/config.rs | 6 ++- src/renderer.rs | 128 ++++++++++++++++++++++++++++++-------------------------- src/vertex.rs | 4 +- 3 files changed, 75 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index e9f9ca4..c29a957 100644 --- a/src/config.rs +++ b/src/config.rs @@ -69,7 +69,7 @@ pub struct RenderWindowConfig<'a> { /// The initial capacity of the instance buffer. The size will increase if /// it's not large enough. Increasing this value may improve performance /// towards the beginning, if a lot of instances are being created. - pub instance_capacity: usize + pub instance_capacity: usize, } impl<'a> Default for RenderWindowConfig<'a> { @@ -87,11 +87,13 @@ impl<'a> Default for RenderWindowConfig<'a> { } impl<'a> RenderWindowConfig<'a> { - /// Create a `WindowBuilder` from the configuration given + /// Create a `WindowBuilder` from the configuration given. This window is + /// initially invisible and must later be made visible. pub(crate) fn to_window(&self) -> WindowBuilder { // start building the window let mut builder = WindowBuilder::new() .with_title(self.title.as_ref()) + .with_visible(false) .with_inner_size(LogicalSize::new( self.default_width.get(), self.default_height.get(), diff --git a/src/renderer.rs b/src/renderer.rs index 81e1a3f..492501f 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -50,6 +50,69 @@ pub struct Renderer { // TODO make this more complete impl Renderer { + fn get_adapter( + instance: &wgpu::Instance, + surface: &wgpu::Surface, + power_preference: wgpu::PowerPreference, + ) -> Result { + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference, + compatible_surface: Some(surface), + force_fallback_adapter: false, + }) + .block_on(); // TODO this takes too long + + let adapter = adapter.or_else(|| { + instance + .enumerate_adapters(wgpu::Backends::all()) + .find(|adapter| !surface.get_supported_formats(adapter).is_empty()) + }); + + adapter.ok_or(NoGpuError::new()) + } + + fn sprite_render_pipeline( + device: &wgpu::Device, + texture_format: wgpu::TextureFormat, + ) -> wgpu::RenderPipeline { + let shader = device.create_shader_module(include_wgsl!("../shaders/sprite.wgsl")); + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Sprite Render Pipeline Layout"), + ..Default::default() + }); + + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Sprite Render Pipeline"), + layout: Some(&render_pipeline_layout), + // information about the vertex shader + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + buffers: &[Vertex::desc(), Instance::desc()], + }, + // information about the fragment shader + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + format: texture_format, + blend: Some(wgpu::BlendState::REPLACE), + write_mask: wgpu::ColorWrites::ALL, + })], + }), + primitive: wgpu::PrimitiveState { + // don't render the back of a sprite + cull_mode: Some(wgpu::Face::Back), + ..Default::default() + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + multiview: None, + }) + } + /// Initializes the renderer /// /// # Errors @@ -79,28 +142,15 @@ impl Renderer { let power_preference = config.power_preference(); // the adapter is the handle to the GPU - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions { - power_preference, - compatible_surface: Some(&surface), - force_fallback_adapter: false, - }) - .block_on(); - let adapter = adapter.or_else(|| { - instance - .enumerate_adapters(wgpu::Backends::all()) - .find(|adapter| !surface.get_supported_formats(adapter).is_empty()) - }); - let Some(adapter) = adapter else { return Err(NoGpuError::new().into()) }; + let adapter = Self::get_adapter(&instance, &surface, power_preference)?; // gets a connection to the device, as well as a handle to its command queue // the options chosen here ensure that this is guaranteed to not panic let (device, queue) = adapter .request_device( &wgpu::DeviceDescriptor { - label: None, features: wgpu::Features::empty(), - limits: wgpu::Limits::default(), + ..Default::default() }, None, ) @@ -108,58 +158,15 @@ impl Renderer { .expect("there was no device with the selected features"); // configuration for the surface + let surface_time = std::time::Instant::now(); let surface_config = config.to_surface_configuration( &surface.get_supported_modes(&adapter), surface.get_supported_formats(&adapter)[0], ); - surface.configure(&device, &surface_config); // set up a pipeline for sprite rendering - let shader = device.create_shader_module(include_wgsl!("../shaders/sprite.wgsl")); - let render_pipeline_layout = - device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Render Pipeline Layout"), - ..Default::default() - }); - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&render_pipeline_layout), - // information about the vertex shader - vertex: wgpu::VertexState { - module: &shader, - entry_point: "vs_main", - buffers: &[Vertex::desc(), Instance::desc()], - }, - // information about the fragment shader - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: "fs_main", - targets: &[Some(wgpu::ColorTargetState { - format: surface_config.format, - blend: Some(wgpu::BlendState::REPLACE), - write_mask: wgpu::ColorWrites::ALL, - })], - }), - primitive: wgpu::PrimitiveState { - // save some memory - topology: wgpu::PrimitiveTopology::TriangleStrip, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - // don't render the back of a sprite - cull_mode: Some(wgpu::Face::Back), - polygon_mode: wgpu::PolygonMode::Fill, - unclipped_depth: false, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - multiview: None, - }); + let render_pipeline = Self::sprite_render_pipeline(&device, surface_config.format); // the vertex buffer used for rendering squares let square_vertices = SQUARE @@ -282,6 +289,7 @@ impl Renderer { /// Run the renderer indefinitely pub fn run(mut self, event_loop: EventLoop<()>) -> ! { + self.window.set_visible(true); event_loop.run(move |event, _, control_flow| match event { Event::WindowEvent { window_id, event } => { if window_id == self.window.id() { diff --git a/src/vertex.rs b/src/vertex.rs index 6514fd3..a24a601 100644 --- a/src/vertex.rs +++ b/src/vertex.rs @@ -3,11 +3,13 @@ use std::mem::size_of; use bytemuck::{Pod, Zeroable}; /// The vertices needed to form a square -pub const SQUARE: [Vertex; 4] = [ +pub const SQUARE: [Vertex; 6] = [ Vertex::new(-0.5, -0.5), Vertex::new(0.5, -0.5), Vertex::new(-0.5, 0.5), Vertex::new(0.5, 0.5), + Vertex::new(-0.5, 0.5), + Vertex::new(0.5, -0.5), ]; #[repr(C)] -- cgit v1.2.3