From f8a80039c74332e2101a177ef3fde31ef2077224 Mon Sep 17 00:00:00 2001 From: Micha White Date: Thu, 15 Aug 2024 20:14:15 -0400 Subject: Lots a changes --- render/src/instance.rs | 19 +------ render/src/lib.rs | 1 - render/src/renderer.rs | 22 +++----- render/src/texture.rs | 137 +++---------------------------------------------- 4 files changed, 16 insertions(+), 163 deletions(-) (limited to 'render/src') diff --git a/render/src/instance.rs b/render/src/instance.rs index e346cae..15317c7 100644 --- a/render/src/instance.rs +++ b/render/src/instance.rs @@ -18,12 +18,6 @@ pub struct Instance { pub texture_coordinates: [f32; 2], /// The size of the sprite's texture pub texture_size: [f32; 2], - /// The index of the texture atlas to use - pub texture_atlas_index: u32, - /// Rotation, in radians - pub rotation: f32, - /// z-index - pub z_index: f32, } impl Default for Instance { @@ -31,11 +25,8 @@ impl Default for Instance { Self { position: [0.0; 2], size: [1.0; 2], - rotation: 0.0, - z_index: 0.0, texture_coordinates: [0.0; 2], texture_size: [1.0; 2], - texture_atlas_index: 0, } } } @@ -150,18 +141,10 @@ impl InstanceBuffer { self.expand_buffer(device); } - // the instances must be sorted by z-index before being handed to the GPU - let sorted = { - profiling::scope!("depth sorting"); - let mut sorted = self.instances.clone(); - sorted.sort_by(|a, b| a.z_index.total_cmp(&b.z_index)); - sorted - }; - queue.write_buffer( &self.instance_buffer, 0 as wgpu::BufferAddress, - bytemuck::cast_slice(&sorted), + bytemuck::cast_slice(&self.instances), ); } } diff --git a/render/src/lib.rs b/render/src/lib.rs index 0d76cc8..6f96fc2 100644 --- a/render/src/lib.rs +++ b/render/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(nonzero_min_max)] #![feature(type_alias_impl_trait)] #![warn(clippy::pedantic)] #![warn(clippy::nursery)] diff --git a/render/src/renderer.rs b/render/src/renderer.rs index f5b486d..4b4f60d 100644 --- a/render/src/renderer.rs +++ b/render/src/renderer.rs @@ -4,7 +4,6 @@ use std::{convert::TryInto, sync::Arc}; use crate::{ vertex::SQUARE, Camera, Instance, InstanceBuffer, RenderWindowConfig, TextureAtlas, Vertex, }; -use alligator_resources::texture::TextureManager; use pollster::FutureExt; use thiserror::Error; use wgpu::{include_wgsl, util::DeviceExt}; @@ -90,7 +89,7 @@ fn get_adapter( let adapter = adapter.or_else(|| { instance - .enumerate_adapters(wgpu::Backends::PRIMARY) + .enumerate_adapters(wgpu::Backends::VULKAN) .find(|adapter| !surface.get_capabilities(adapter).formats.is_empty()) }); @@ -148,20 +147,14 @@ impl Renderer { /// panic on some platforms. // TODO make it possible to use without a window (ie, use a bitmap in memory as a surface) // TODO this function needs to be smaller - pub fn new( - config: &RenderWindowConfig, - textures: Arc, - ) -> Result { + pub fn new(config: &RenderWindowConfig) -> Result { // build the window let event_loop = EventLoop::new(); let window = config.to_window().build(&event_loop)?; let event_loop = Some(event_loop); // the instance's main purpose is to create an adapter and a surface - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: wgpu::Backends::VULKAN, - dx12_shader_compiler: wgpu::Dx12Compiler::Fxc, // TODO support DXC - }); + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::default()); // the surface is the part of the screen we'll draw to let surface = @@ -220,7 +213,6 @@ impl Renderer { // TODO make this configurable let (textures, texture_layout) = TextureAtlas::new( &device, - textures, window.inner_size().width, window.inner_size().height, ); @@ -311,7 +303,7 @@ impl Renderer { } /// Get a reference to the texture atlas - pub const fn textures(&self) -> &TextureAtlas { + pub const fn texture_atlas(&self) -> &TextureAtlas { &self.textures } @@ -358,10 +350,12 @@ impl Renderer { resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), - store: true, + store: wgpu::StoreOp::Discard, }, })], depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, }); render_pass.set_pipeline(&self.render_pipeline); @@ -421,7 +415,7 @@ impl Renderer { // https://github.com/gfx-rs/wgpu/issues/1783#issuecomment-1328463201 if self.window.inner_size().width != 0 && self.window.inner_size().height != 0 { match self.render() { - Ok(_) => {} + Ok(()) => {} // reconfigure the surface if it's been lost Err(wgpu::SurfaceError::Lost) => { self.reconfigure(); diff --git a/render/src/texture.rs b/render/src/texture.rs index 76e77a8..90d23d1 100644 --- a/render/src/texture.rs +++ b/render/src/texture.rs @@ -1,30 +1,10 @@ use std::error::Error; -use std::num::NonZeroU32; -use std::sync::Arc; -use alligator_resources::texture::{LoadError, Rgba16Texture, TextureId, TextureManager}; -use image::{EncodableLayout, GenericImage, RgbaImage}; -use texture_packer::TexturePacker; -use texture_packer::{ - exporter::{ExportResult, ImageExporter}, - TexturePackerConfig, -}; +use image::{EncodableLayout, RgbaImage}; use thiserror::Error; -/// The texture did not fit in the texture atlas -#[derive(Debug, Error)] -#[error("{:?}", .0)] -pub struct PackError(PackErrorInternal); - -// TODO this can be removed when a new texture packer is made -type PackErrorInternal = impl std::fmt::Debug; - #[derive(Error, Debug)] pub enum TextureError { - #[error("{:?}", .0)] - TextureTooLarge(#[from] PackError), - #[error("{}", .0)] - BadImage(#[from] LoadError), #[error("Unexpected Error (this is a bug in alligator_render): {}", .0)] Unexpected(#[source] Box), } @@ -39,46 +19,18 @@ const fn extent_3d(width: u32, height: u32) -> wgpu::Extent3d { } /// A texture atlas, usable by the renderer -// TODO make this Debug // TODO make these resizable +#[derive(Debug)] pub struct TextureAtlas { - textures: Arc, - packer: TexturePacker<'static, Rgba16Texture, TextureId>, diffuse_texture: wgpu::Texture, diffuse_bind_group: wgpu::BindGroup, image: RgbaImage, - width: u32, - height: u32, - changed: bool, -} - -macro_rules! texture_info { - ($name: ident, $prop: ident, $divisor: ident) => { - pub fn $name(&mut self, id: TextureId) -> Result { - let frame = match self.texture_frame(id) { - Some(frame) => frame, - None => { - self.load_texture(id)?; - self.texture_frame(id).unwrap() - } - }; - let property = frame.frame.$prop; - let value = property as f32 / self.$divisor as f32; - Ok(value) - } - }; } impl TextureAtlas { /// Creates a new texture atlas, with the given size - // TODO why is this u32? // TODO this is still too large - pub fn new( - device: &wgpu::Device, - textures: Arc, - width: u32, - height: u32, - ) -> (Self, wgpu::BindGroupLayout) { + pub fn new(device: &wgpu::Device, width: u32, height: u32) -> (Self, wgpu::BindGroupLayout) { let atlas_size = extent_3d(width, height); let diffuse_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("Diffuse Texture"), @@ -137,26 +89,14 @@ impl TextureAtlas { ( Self { - textures, - packer: TexturePacker::new_skyline(TexturePackerConfig { - max_width: width, - max_height: height, - allow_rotation: false, - trim: false, - texture_padding: 0, - ..Default::default() - }), diffuse_texture, diffuse_bind_group, - width, - height, image: RgbaImage::from_raw( width, height, vec![0; 4 * width as usize * height as usize], ) .unwrap(), - changed: true, }, texture_bind_group_layout, ) @@ -167,68 +107,7 @@ impl TextureAtlas { &self.diffuse_bind_group } - /// Load a new subtexture from memory - pub fn load_texture(&mut self, id: TextureId) -> Result { - self.changed = true; - let img = self.textures.load_texture(id)?; - self.packer.pack_own(id, img).map_err(PackError)?; - Ok(id) - } - - /// Get the frame for s particular subtexture - fn texture_frame(&self, id: TextureId) -> Option<&texture_packer::Frame> { - self.packer.get_frame(&id) - } - - texture_info!(texture_width, w, width); - texture_info!(texture_height, h, height); - texture_info!(texture_x, x, width); - texture_info!(texture_y, y, height); - - /// Fill the cached image - fn fill_image(&mut self) -> ExportResult<()> { - let atlas = { - profiling::scope!("export atlas"); - ImageExporter::export(&self.packer)? - }; - profiling::scope!("copy image"); - self.image - .copy_from(&atlas, 0, 0) - .expect("image cache is too small"); - Ok(()) - } - - /// Clear the texture atlas, and give it a new size - pub fn clear(&mut self, width: u32, height: u32) { - self.changed = true; - self.width = width; - self.height = height; - self.packer = TexturePacker::new_skyline(TexturePackerConfig { - max_width: self.width, - max_height: self.height, - ..Default::default() - }); - } - - /// Fill the GPU texture atlas - #[profiling::function] - pub(crate) fn fill_textures(&mut self, queue: &wgpu::Queue) { - // saves time if nothing changed since the last time we did this - // FIXME This doesn't do much good once we get procedurally generated animation - // We'll have to create our own texture packer, with mutable subtextures, - // and more efficient algorithms. This'll also make frame times more consistent - if !self.changed { - return; - } - - let atlas_size = extent_3d(self.width, self.height); - - // put the packed texture into the base image - if let Err(e) = self.fill_image() { - log::error!("{}", e); - } - - // copy that to the gpu + pub(crate) fn fill_textures(&self, queue: &wgpu::Queue) { queue.write_texture( wgpu::ImageCopyTexture { texture: &self.diffuse_texture, @@ -239,12 +118,10 @@ impl TextureAtlas { self.image.as_bytes(), wgpu::ImageDataLayout { offset: 0, - bytes_per_row: NonZeroU32::new(atlas_size.width * 4), - rows_per_image: NonZeroU32::new(atlas_size.height), + bytes_per_row: Some(self.image.width() * 4), + rows_per_image: Some(self.image.height()), }, - atlas_size, + extent_3d(self.image.width(), self.image.height()), ); - - self.changed = false; } } -- cgit v1.2.3