summaryrefslogtreecommitdiff
path: root/render/src
diff options
context:
space:
mode:
Diffstat (limited to 'render/src')
-rw-r--r--render/src/instance.rs19
-rw-r--r--render/src/lib.rs1
-rw-r--r--render/src/renderer.rs22
-rw-r--r--render/src/texture.rs137
4 files changed, 16 insertions, 163 deletions
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<TextureManager>,
- ) -> Result<Self, NewRendererError> {
+ pub fn new(config: &RenderWindowConfig) -> Result<Self, NewRendererError> {
// 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<dyn Error>),
}
@@ -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<TextureManager>,
- 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<f32, TextureError> {
- 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<TextureManager>,
- 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<TextureId, TextureError> {
- 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<TextureId>> {
- 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;
}
}