Switch to index rendering for most quad-like things

This commit is contained in:
Imbris 2021-03-01 01:13:51 -05:00 committed by Avi Weinstock
parent d1748884b9
commit 5de8099bd3
12 changed files with 255 additions and 29 deletions

View File

@ -86,6 +86,8 @@ const float SCALE = 1.0 / 11.0;
const float SCALE_FACTOR = pow(SCALE, 1.3) * 0.2;
const int EXTRA_NEG_Z = 32768;
//const int VERT_EXTRA_NEG_Z = 128;
//const int VERT_PAGE_SIZE = 256;
void main() {
// vec3 inst_chunk_pos = vec3(ivec3((uvec3(inst_pos_ori) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z));

View File

@ -42,31 +42,48 @@ impl<V: Vertex> Mesh<V> {
pub fn push_quad(&mut self, quad: Quad<V>) {
// A quad is composed of two triangles. The code below converts the former to
// the latter.
if V::QUADS_INDEX.is_some() {
// 0, 1, 2, 2, 1, 3
// b, c, a, a, c, d
self.verts.push(quad.b);
self.verts.push(quad.c);
self.verts.push(quad.a);
self.verts.push(quad.d);
} else {
// Tri 1
self.verts.push(quad.a.clone());
self.verts.push(quad.b);
self.verts.push(quad.c.clone());
// Tri 1
self.verts.push(quad.a.clone());
self.verts.push(quad.b);
self.verts.push(quad.c.clone());
// Tri 2
self.verts.push(quad.c);
self.verts.push(quad.d);
self.verts.push(quad.a);
// Tri 2
self.verts.push(quad.c);
self.verts.push(quad.d);
self.verts.push(quad.a);
}
}
/// Overwrite a quad
pub fn replace_quad(&mut self, index: usize, quad: Quad<V>) {
debug_assert!(index % 3 == 0);
assert!(index + 5 < self.verts.len());
// Tri 1
self.verts[index] = quad.a.clone();
self.verts[index + 1] = quad.b;
self.verts[index + 2] = quad.c.clone();
if V::QUADS_INDEX.is_some() {
debug_assert!(index % 4 == 0);
assert!(index + 3 < self.verts.len());
self.verts[index] = quad.b;
self.verts[index + 1] = quad.c;
self.verts[index + 2] = quad.a;
self.verts[index + 3] = quad.d;
} else {
debug_assert!(index % 3 == 0);
assert!(index + 5 < self.verts.len());
// Tri 1
self.verts[index] = quad.a.clone();
self.verts[index + 1] = quad.b;
self.verts[index + 2] = quad.c.clone();
// Tri 2
self.verts[index + 3] = quad.c;
self.verts[index + 4] = quad.d;
self.verts[index + 5] = quad.a;
// Tri 2
self.verts[index + 3] = quad.c;
self.verts[index + 4] = quad.d;
self.verts[index + 5] = quad.a;
}
}
/// Push the vertices of another mesh onto the end of this mesh.

View File

@ -55,6 +55,8 @@ pub use wgpu::{AddressMode, FilterMode};
pub trait Vertex: Clone + bytemuck::Pod {
const STRIDE: wgpu::BufferAddress;
// Whether these types of verts use the quad index buffer for drawing them
const QUADS_INDEX: Option<wgpu::IndexFormat>;
}
use serde::{Deserialize, Serialize};

View File

@ -43,6 +43,7 @@ impl Vertex {
}
impl VertexTrait for Vertex {
const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint16);
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}

View File

@ -27,6 +27,7 @@ impl Vertex {
}
impl VertexTrait for Vertex {
const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint32);
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}

View File

@ -44,6 +44,7 @@ impl Vertex {
}
impl VertexTrait for Vertex {
const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint16);
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}

View File

@ -23,6 +23,7 @@ impl Vertex {
}
impl VertexTrait for Vertex {
const QUADS_INDEX: Option<wgpu::IndexFormat> = None;
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}

View File

@ -4,6 +4,8 @@ use core::fmt;
use std::mem;
use vek::*;
// pub const VERT_PAGE_SIZE: u32 = 256;
#[repr(C)]
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
pub struct Vertex {
@ -72,9 +74,72 @@ impl Vertex {
}
impl VertexTrait for Vertex {
const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint16);
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}
/* pub fn create_verts_buffer(renderer: &mut Renderer, mut mesh: Mesh<Vertex>) -> Buffer<Vertex> {
renderer.ensure_sufficient_index_length::<Vertex>(VERT_PAGE_SIZE as usize);
// TODO: type buffer by Usage
Buffer::new(
&renderer.device,
wgpu::BufferUsage::STORAGE,
mesh.vertices(),
)
//let mut verts = mesh.vertices_mut_vec();
//let format = wgpu::TextureFormat::Rg32Uint;
// TODO: temp
//const WIDTH: u32 = 8192;
//let height = verts.len() as u32 / WIDTH;
// Fill in verts to full texture size
//verts.resize_with(height as usize * WIDTH as usize, Vertex::default);
/*let texture_info = wgpu::TextureDescriptor {
label: Some("Sprite verts"),
size: wgpu::Extent3d {
width: WIDTH,
height,
depth: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
};
let sampler_info = wgpu::SamplerDescriptor {
label: None,
address_mode_u: wgpu::AddressMode::Repeat,
address_mode_v: wgpu::AddressMode::Repeat,
address_mode_w: wgpu::AddressMode::Repeat,
mag_filter: wgpu::FilterMode::Nearest,
min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest,
..Default::default()
};
let view_info = wgpu::TextureViewDescriptor {
label: None,
format: Some(format),
dimension: Some(wgpu::TextureViewDimension::D2),
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
level_count: None,
base_array_layer: 0,
array_layer_count: None,
};
renderer.create_texture_with_data_raw::<8>(
&texture_info,
&view_info,
&sampler_info,
bytemuck::cast_slice(verts),
)*/
}
*/
#[repr(C)]
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
pub struct Instance {

View File

@ -131,6 +131,9 @@ impl Vertex {
}
impl VertexTrait for Vertex {
// Note: I think it's u32 due to figures??
// potentiall optimize by splitting
const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint32);
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}

View File

@ -27,6 +27,7 @@ impl Vertex {
}
impl VertexTrait for Vertex {
const QUADS_INDEX: Option<wgpu::IndexFormat> = None;
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
}

View File

@ -10,6 +10,7 @@ use shaders::Shaders;
use shadow_map::{ShadowMap, ShadowMapRenderer};
use super::{
buffer::Buffer,
consts::Consts,
instances::Instances,
mesh::Mesh,
@ -34,6 +35,9 @@ use vek::*;
// TODO: revert to u16
pub type ColLightInfo = (Vec<[u8; 4]>, Vec2<u32>);
const QUAD_INDEX_BUFFER_U16_START_VERT_LEN: u16 = 3000;
const QUAD_INDEX_BUFFER_U32_START_VERT_LEN: u32 = 3000;
/// A type that stores all the layouts associated with this renderer.
struct Layouts {
global: GlobalsLayouts,
@ -104,6 +108,9 @@ pub struct Renderer {
views: Views,
noise_tex: Texture,
quad_index_buffer_u16: Buffer<u16>,
quad_index_buffer_u32: Buffer<u32>,
shaders: AssetHandle<Shaders>,
mode: RenderMode,
@ -330,6 +337,10 @@ impl Renderer {
&depth_sampler,
);
let quad_index_buffer_u16 =
create_quad_index_buffer_u16(&device, QUAD_INDEX_BUFFER_U16_START_VERT_LEN as usize);
let quad_index_buffer_u32 =
create_quad_index_buffer_u32(&device, QUAD_INDEX_BUFFER_U32_START_VERT_LEN as usize);
let mut profiler = wgpu_profiler::GpuProfiler::new(1, queue.get_timestamp_period());
profiler.enable_timer = mode.profiler_enabled;
profiler.enable_debug_marker = mode.profiler_enabled;
@ -351,6 +362,9 @@ impl Renderer {
depth_sampler,
noise_tex,
quad_index_buffer_u16,
quad_index_buffer_u32,
shaders,
mode,
@ -927,8 +941,50 @@ impl Renderer {
Ok(instances)
}
/// Ensure that the quad index buffer is large enough for a quad vertex
/// buffer with this many vertices
pub(super) fn ensure_sufficient_index_length<V: Vertex>(
&mut self,
// Length of the vert buffer with 4 verts per quad
length: usize,
) {
match V::QUADS_INDEX {
Some(wgpu::IndexFormat::Uint16) => {
// Make sure the global quad index buffer is large enough
if self.quad_index_buffer_u16.len() < length {
// Make sure we aren't over the max
if length > u16::MAX as usize {
panic!(
"Vertex type: {} needs to use a larger index type, length: {}",
core::any::type_name::<V>(),
length
);
}
self.quad_index_buffer_u16 = create_quad_index_buffer_u16(&self.device, length);
}
},
Some(wgpu::IndexFormat::Uint32) => {
// Make sure the global quad index buffer is large enough
if self.quad_index_buffer_u32.len() < length {
// Make sure we aren't over the max
if length > u32::MAX as usize {
panic!(
"More than u32::MAX({}) verts({}) for type({}) using an index buffer!",
u32::MAX,
length,
core::any::type_name::<V>()
);
}
self.quad_index_buffer_u32 = create_quad_index_buffer_u32(&self.device, length);
}
},
None => {},
}
}
/// Create a new model from the provided mesh.
pub fn create_model<V: Vertex>(&mut self, mesh: &Mesh<V>) -> Result<Model<V>, RenderError> {
self.ensure_sufficient_index_length::<V>(mesh.vertices().len());
Ok(Model::new(&self.device, mesh))
}
@ -2171,3 +2227,31 @@ fn create_shader_module(
flags: wgpu::ShaderFlags::empty(), // TODO: renable wgpu::ShaderFlags::VALIDATION,
}))
}
fn create_quad_index_buffer_u16(device: &wgpu::Device, vert_length: usize) -> Buffer<u16> {
assert!(vert_length <= u16::MAX as usize);
let indices = [0, 1, 2, 2, 1, 3]
.iter()
.cycle()
.copied()
.take(vert_length / 4 * 6)
.enumerate()
.map(|(i, b)| (i / 6 * 4 + b) as u16)
.collect::<Vec<_>>();
Buffer::new(device, wgpu::BufferUsage::INDEX, &indices)
}
fn create_quad_index_buffer_u32(device: &wgpu::Device, vert_length: usize) -> Buffer<u32> {
assert!(vert_length <= u32::MAX as usize);
let indices = [0, 1, 2, 2, 1, 3]
.iter()
.cycle()
.copied()
.take(vert_length / 4 * 6)
.enumerate()
.map(|(i, b)| (i / 6 * 4 + b) as u32)
.collect::<Vec<_>>();
Buffer::new(device, wgpu::BufferUsage::INDEX, &indices)
}

View File

@ -26,6 +26,8 @@ struct RendererBorrow<'frame> {
locals: &'frame super::locals::Locals,
views: &'frame super::Views,
mode: &'frame super::super::RenderMode,
quad_index_buffer_u16: &'frame Buffer<u16>,
quad_index_buffer_u32: &'frame Buffer<u32>,
}
pub struct Drawer<'frame> {
@ -50,6 +52,8 @@ impl<'frame> Drawer<'frame> {
locals: &renderer.locals,
views: &renderer.views,
mode: &renderer.mode,
quad_index_buffer_u16: &renderer.quad_index_buffer_u16,
quad_index_buffer_u32: &renderer.quad_index_buffer_u32,
};
let mut encoder =
@ -233,6 +237,7 @@ impl<'frame> Drawer<'frame> {
});
render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline);
set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, &self.borrow);
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
(0../*20*/1).for_each(|point_light| {
@ -245,7 +250,7 @@ impl<'frame> Drawer<'frame> {
chunks.clone().for_each(|(model, locals)| {
render_pass.set_bind_group(1, &locals.bind_group, &[]);
render_pass.set_vertex_buffer(0, model.buf().slice(..));
render_pass.draw(0..model.len() as u32, 0..1);
render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
});
});
}
@ -346,6 +351,7 @@ impl<'pass> ShadowPassDrawer<'pass> {
.scope(self.borrow.device, "direcred_figure_shadows");
render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, &self.borrow);
FigureShadowDrawer { render_pass }
}
@ -356,6 +362,7 @@ impl<'pass> ShadowPassDrawer<'pass> {
.scope(self.borrow.device, "direcred_terrain_shadows");
render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, &self.borrow);
TerrainShadowDrawer { render_pass }
}
@ -373,7 +380,8 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
) {
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, model.buf());
self.render_pass.draw(0..model.len(), 0..1);
self.render_pass
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
}
}
@ -389,7 +397,8 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
) {
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass.draw(0..model.len() as u32, 0..1);
self.render_pass
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
}
}
@ -404,6 +413,7 @@ impl<'pass> FirstPassDrawer<'pass> {
let mut render_pass = self.render_pass.scope(self.borrow.device, "skybox");
render_pass.set_pipeline(&self.borrow.pipelines.skybox.pipeline);
set_quad_index_buffer::<skybox::Vertex>(&mut render_pass, &self.borrow);
render_pass.set_vertex_buffer(0, model.buf().slice(..));
render_pass.draw(0..model.len() as u32, 0..1);
}
@ -412,14 +422,16 @@ impl<'pass> FirstPassDrawer<'pass> {
let mut render_pass = self.render_pass.scope(self.borrow.device, "lod_terrain");
render_pass.set_pipeline(&self.borrow.pipelines.lod_terrain.pipeline);
set_quad_index_buffer::<lod_terrain::Vertex>(&mut render_pass, &self.borrow);
render_pass.set_vertex_buffer(0, model.buf().slice(..));
render_pass.draw(0..model.len() as u32, 0..1);
render_pass.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
}
pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> {
let mut render_pass = self.render_pass.scope(self.borrow.device, "figures");
render_pass.set_pipeline(&self.borrow.pipelines.figure.pipeline);
set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, &self.borrow);
FigureDrawer { render_pass }
}
@ -428,6 +440,7 @@ impl<'pass> FirstPassDrawer<'pass> {
let mut render_pass = self.render_pass.scope(self.borrow.device, "terrain");
render_pass.set_pipeline(&self.borrow.pipelines.terrain.pipeline);
set_quad_index_buffer::<terrain::Vertex>(&mut render_pass, &self.borrow);
TerrainDrawer {
render_pass,
@ -439,6 +452,7 @@ impl<'pass> FirstPassDrawer<'pass> {
let mut render_pass = self.render_pass.scope(self.borrow.device, "particles");
render_pass.set_pipeline(&self.borrow.pipelines.particle.pipeline);
set_quad_index_buffer::<particle::Vertex>(&mut render_pass, &self.borrow);
ParticleDrawer { render_pass }
}
@ -450,6 +464,7 @@ impl<'pass> FirstPassDrawer<'pass> {
let mut render_pass = self.render_pass.scope(self.borrow.device, "sprites");
render_pass.set_pipeline(&self.borrow.pipelines.sprite.pipeline);
set_quad_index_buffer::<particle::Vertex>(&mut render_pass, &self.borrow);
render_pass.set_bind_group(4, &col_lights.bind_group, &[]);
SpriteDrawer { render_pass }
@ -462,6 +477,7 @@ impl<'pass> FirstPassDrawer<'pass> {
let mut render_pass = self.render_pass.scope(self.borrow.device, "fluid");
render_pass.set_pipeline(&self.borrow.pipelines.fluid.pipeline);
set_quad_index_buffer::<fluid::Vertex>(&mut render_pass, &self.borrow);
render_pass.set_bind_group(2, &waves.bind_group, &[]);
FluidDrawer { render_pass }
@ -484,7 +500,8 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
self.render_pass
.set_bind_group(3, &col_lights.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, model.buf());
self.render_pass.draw(0..model.len(), 0..1);
self.render_pass
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
}
}
@ -516,7 +533,8 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> {
self.render_pass.set_bind_group(2, &locals.bind_group, &[]); // TODO: put this in slot 3
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass.draw(0..model.len() as u32, 0..1)
self.render_pass
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
}
}
@ -537,7 +555,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
.set_vertex_buffer(1, instances.buf().slice(..));
self.render_pass
// TODO: since we cast to u32 maybe this should returned by the len/count functions?
.draw(0..model.len() as u32, 0..instances.count() as u32);
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..instances.count() as u32);
}
}
@ -556,6 +574,14 @@ impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> {
ChunkSpriteDrawer {
render_pass: &mut self.render_pass,
}
/* //self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass
.set_vertex_buffer(0, instances.buf().slice(..));
self.render_pass.draw_indexed(
0..sprite::VERT_PAGE_SIZE / 4 * 6,
0,
0..instances.count() as u32,
); */
}
}
pub struct ChunkSpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
@ -573,8 +599,11 @@ impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> {
self.render_pass
.set_vertex_buffer(1, instances.buf().slice(..));
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
self.render_pass
.draw(0..model.len() as u32, 0..instances.count() as u32);
self.render_pass.draw_indexed(
0..model.len() as u32 / 4 * 6,
0,
0..instances.count() as u32,
);
}
}
@ -590,7 +619,8 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
) {
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
self.render_pass.draw(0..model.len() as u32, 0..1);
self.render_pass
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..1);
}
}
@ -627,6 +657,7 @@ impl<'pass> ThirdPassDrawer<'pass> {
pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> {
let mut render_pass = self.render_pass.scope(self.borrow.device, "ui");
render_pass.set_pipeline(&self.borrow.pipelines.ui.pipeline);
set_quad_index_buffer::<ui::Vertex>(&mut render_pass, &self.borrow);
UiDrawer { render_pass }
}
@ -695,3 +726,20 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
self.render_pass.draw(verts, 0..1);
}
}
fn set_quad_index_buffer<'a, V: super::super::Vertex>(
pass: &mut wgpu::RenderPass<'a>,
borrow: &RendererBorrow<'a>,
) {
match V::QUADS_INDEX {
Some(format) => {
let slice = match format {
wgpu::IndexFormat::Uint16 => borrow.quad_index_buffer_u16.buf.slice(..),
wgpu::IndexFormat::Uint32 => borrow.quad_index_buffer_u32.buf.slice(..),
};
pass.set_index_buffer(slice, format);
},
None => {},
}
}