Try out using storage buffer for sprite vertices

This commit is contained in:
Imbris 2021-02-28 02:40:53 -05:00 committed by Avi Weinstock
parent bed1596985
commit 2de13f3a87
6 changed files with 64 additions and 36 deletions

View File

@ -30,8 +30,11 @@ layout(location = 7) in float inst_glow;
layout(location = 8) in float model_wind_sway; // NOTE: this only varies per model layout(location = 8) in float model_wind_sway; // NOTE: this only varies per model
layout(location = 9) in float model_z_scale; // NOTE: this only varies per model layout(location = 9) in float model_z_scale; // NOTE: this only varies per model
layout(set = 0, binding = 12) uniform utexture2D t_sprite_verts; //layout(set = 0, binding = 12) uniform utexture2D t_sprite_verts;
layout(set = 0, binding = 13) uniform sampler s_sprite_verts; //layout(set = 0, binding = 13) uniform sampler s_sprite_verts;
layout(set = 0, binding = 12) restrict readonly buffer sprite_verts {
uvec2 verts[];
};
layout (std140, set = 2, binding = 0) layout (std140, set = 2, binding = 0)
uniform u_terrain_locals { uniform u_terrain_locals {
@ -69,9 +72,10 @@ void main() {
// Index of the vertex data in the 1D vertex texture // Index of the vertex data in the 1D vertex texture
int vertex_index = int(gl_VertexIndex % VERT_PAGE_SIZE + inst_vert_page * VERT_PAGE_SIZE); int vertex_index = int(gl_VertexIndex % VERT_PAGE_SIZE + inst_vert_page * VERT_PAGE_SIZE);
const int WIDTH = 8192; // TODO: temp //const int WIDTH = 8192; // TODO: temp
ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH); //ivec2 tex_coords = ivec2(vertex_index % WIDTH, vertex_index / WIDTH);
uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy; //uvec2 pos_atlas_pos_norm_ao = texelFetch(usampler2D(t_sprite_verts, s_sprite_verts), tex_coords, 0).xy;
uvec2 pos_atlas_pos_norm_ao = verts[vertex_index];
uint v_pos_norm = pos_atlas_pos_norm_ao.x; uint v_pos_norm = pos_atlas_pos_norm_ao.x;
uint v_atlas_pos = pos_atlas_pos_norm_ao.y; uint v_atlas_pos = pos_atlas_pos_norm_ao.y;

View File

@ -14,6 +14,7 @@ pub mod texture;
// Reexports // Reexports
pub use self::{ pub use self::{
bound::Bound, bound::Bound,
buffer::Buffer,
consts::Consts, consts::Consts,
error::RenderError, error::RenderError,
instances::Instances, instances::Instances,
@ -32,7 +33,7 @@ pub use self::{
shadow::{Locals as ShadowLocals, PointLightMatrix}, shadow::{Locals as ShadowLocals, PointLightMatrix},
skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex}, skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex},
sprite::{ sprite::{
create_verts_texture as create_sprite_verts_texture, Instance as SpriteInstance, create_verts_buffer as create_sprite_verts_buffer, Instance as SpriteInstance,
SpriteGlobalsBindGroup, Vertex as SpriteVertex, SpriteGlobalsBindGroup, Vertex as SpriteVertex,
VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE, VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE,
}, },

View File

@ -1,7 +1,7 @@
use super::{ use super::{
super::{ super::{
AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout, Texture, buffer::Buffer, AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout,
Vertex as VertexTrait, Texture, Vertex as VertexTrait,
}, },
lod_terrain, GlobalModel, lod_terrain, GlobalModel,
}; };
@ -88,24 +88,24 @@ impl VertexTrait for Vertex {
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress; const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
} }
pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh<Vertex>) -> Texture { 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); renderer.ensure_sufficient_index_length::<Vertex>(VERT_PAGE_SIZE as usize);
// TODO: type buffer by Usage // TODO: type buffer by Usage
/*Buffer::new( Buffer::new(
&renderer.device, &renderer.device,
wgpu::BufferUsage::STORAGE, wgpu::BufferUsage::STORAGE,
mesh.vertices(), mesh.vertices(),
)*/ )
let mut verts = mesh.vertices_mut_vec(); //let mut verts = mesh.vertices_mut_vec();
let format = wgpu::TextureFormat::Rg32Uint; //let format = wgpu::TextureFormat::Rg32Uint;
// TODO: temp // TODO: temp
const WIDTH: u32 = 8192; //const WIDTH: u32 = 8192;
let height = verts.len() as u32 / WIDTH; //let height = verts.len() as u32 / WIDTH;
// Fill in verts to full texture size // Fill in verts to full texture size
verts.resize_with(height as usize * WIDTH as usize, Vertex::default); //verts.resize_with(height as usize * WIDTH as usize, Vertex::default);
let texture_info = wgpu::TextureDescriptor { /*let texture_info = wgpu::TextureDescriptor {
label: Some("Sprite verts"), label: Some("Sprite verts"),
size: wgpu::Extent3d { size: wgpu::Extent3d {
width: WIDTH, width: WIDTH,
@ -146,7 +146,7 @@ pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh<Vertex>) ->
&view_info, &view_info,
&sampler_info, &sampler_info,
bytemuck::cast_slice(verts), bytemuck::cast_slice(verts),
) )*/
} }
#[repr(C)] #[repr(C)]
@ -263,8 +263,21 @@ impl SpriteLayout {
let mut entries = GlobalsLayouts::base_globals_layout(); let mut entries = GlobalsLayouts::base_globals_layout();
debug_assert_eq!(12, entries.len()); // To remember to adjust the bindings below debug_assert_eq!(12, entries.len()); // To remember to adjust the bindings below
entries.extend_from_slice(&[ entries.extend_from_slice(&[
// sprite verts (t_sprite_verts) // sprite_verts
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 12,
visibility: wgpu::ShaderStage::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
min_binding_size: core::num::NonZeroU64::new(
core::mem::size_of::<Vertex>() as u64
),
},
count: None,
},
/* sprite verts (t_sprite_verts) */
/*wgpu::BindGroupLayoutEntry {
binding: 12, binding: 12,
visibility: wgpu::ShaderStage::VERTEX, visibility: wgpu::ShaderStage::VERTEX,
ty: wgpu::BindingType::Texture { ty: wgpu::BindingType::Texture {
@ -282,7 +295,7 @@ impl SpriteLayout {
comparison: false, comparison: false,
}, },
count: None, count: None,
}, },*/
]); ]);
Self { Self {
@ -323,20 +336,26 @@ impl SpriteLayout {
global_model: &GlobalModel, global_model: &GlobalModel,
lod_data: &lod_terrain::LodData, lod_data: &lod_terrain::LodData,
noise: &Texture, noise: &Texture,
sprite_verts: &Texture, //sprite_verts: &Texture,
sprite_verts: &Buffer<Vertex>,
) -> wgpu::BindGroup { ) -> wgpu::BindGroup {
let mut entries = GlobalsLayouts::bind_base_globals(global_model, lod_data, noise); let mut entries = GlobalsLayouts::bind_base_globals(global_model, lod_data, noise);
entries.extend_from_slice(&[ entries.extend_from_slice(&[
// sprite verts (t_sprite_verts) // sprite_verts
wgpu::BindGroupEntry { wgpu::BindGroupEntry {
binding: 12,
resource: sprite_verts.buf.as_entire_binding(),
},
/* sprite verts (t_sprite_verts) */
/*wgpu::BindGroupEntry {
binding: 12, binding: 12,
resource: wgpu::BindingResource::TextureView(&sprite_verts.view), resource: wgpu::BindingResource::TextureView(&sprite_verts.view),
}, },
wgpu::BindGroupEntry { wgpu::BindGroupEntry {
binding: 13, binding: 13,
resource: wgpu::BindingResource::Sampler(&sprite_verts.sampler), resource: wgpu::BindingResource::Sampler(&sprite_verts.sampler),
}, },*/
]); ]);
device.create_bind_group(&wgpu::BindGroupDescriptor { device.create_bind_group(&wgpu::BindGroupDescriptor {
@ -352,7 +371,8 @@ impl SpriteLayout {
global_model: &GlobalModel, global_model: &GlobalModel,
lod_data: &lod_terrain::LodData, lod_data: &lod_terrain::LodData,
noise: &Texture, noise: &Texture,
sprite_verts: &Texture, //sprite_verts: &Texture,
sprite_verts: &Buffer<Vertex>,
) -> SpriteGlobalsBindGroup { ) -> SpriteGlobalsBindGroup {
let bind_group = let bind_group =
self.bind_globals_inner(device, global_model, lod_data, noise, sprite_verts); self.bind_globals_inner(device, global_model, lod_data, noise, sprite_verts);

View File

@ -90,7 +90,8 @@ struct Shadow {
/// GPU, along with pipeline state objects (PSOs) needed to renderer different /// GPU, along with pipeline state objects (PSOs) needed to renderer different
/// kinds of models to the screen. /// kinds of models to the screen.
pub struct Renderer { pub struct Renderer {
device: wgpu::Device, // TODO: remove pub(super)
pub(super) device: wgpu::Device,
queue: wgpu::Queue, queue: wgpu::Queue,
surface: wgpu::Surface, surface: wgpu::Surface,
swap_chain: wgpu::SwapChain, swap_chain: wgpu::SwapChain,
@ -1975,7 +1976,7 @@ fn create_pipelines(
let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?; let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?;
let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?; let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?;
options.set_optimization_level(OptimizationLevel::Performance); options.set_optimization_level(OptimizationLevel::Performance);
options.set_forced_version_profile(420, shaderc::GlslProfile::Core); options.set_forced_version_profile(430, shaderc::GlslProfile::Core);
options.set_include_callback(move |name, _, shader_name, _| { options.set_include_callback(move |name, _, shader_name, _| {
Ok(ResolvedInclude { Ok(ResolvedInclude {
resolved_name: name.to_string(), resolved_name: name.to_string(),

View File

@ -1,5 +1,6 @@
use super::{ use super::{
super::{ super::{
buffer::Buffer,
pipelines::{ pipelines::{
figure, fluid, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel, figure, fluid, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel,
GlobalsBindGroup, GlobalsBindGroup,
@ -24,7 +25,8 @@ impl Renderer {
&self, &self,
global_model: &GlobalModel, global_model: &GlobalModel,
lod_data: &lod_terrain::LodData, lod_data: &lod_terrain::LodData,
sprite_verts: &Texture, //sprite_verts: &Texture,
sprite_verts: &Buffer<sprite::Vertex>,
) -> sprite::SpriteGlobalsBindGroup { ) -> sprite::SpriteGlobalsBindGroup {
self.layouts.sprite.bind_globals( self.layouts.sprite.bind_globals(
&self.device, &self.device,

View File

@ -9,12 +9,12 @@ use crate::{
terrain::{generate_mesh, SUNLIGHT}, terrain::{generate_mesh, SUNLIGHT},
}, },
render::{ render::{
create_sprite_verts_texture, create_sprite_verts_buffer,
pipelines::{self, ColLights}, pipelines::{self, ColLights},
ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Buffer, ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves,
Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteGlobalsBindGroup, GlobalModel, Instances, LodData, Mesh, Model, RenderError, Renderer,
SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture, SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer,
SPRITE_VERT_PAGE_SIZE, TerrainVertex, Texture, SPRITE_VERT_PAGE_SIZE,
}, },
}; };
@ -381,7 +381,7 @@ pub struct SpriteRenderContext {
// Maps sprite kind + variant to data detailing how to render it // Maps sprite kind + variant to data detailing how to render it
sprite_data: Arc<HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>>, sprite_data: Arc<HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>>,
sprite_col_lights: Arc<ColLights<pipelines::sprite::Locals>>, sprite_col_lights: Arc<ColLights<pipelines::sprite::Locals>>,
sprite_verts_texture: Arc<Texture>, sprite_verts_buffer: Arc<Buffer<SpriteVertex>>,
} }
pub type SpriteRenderContextLazy = Box<dyn FnMut(&mut Renderer) -> SpriteRenderContext>; pub type SpriteRenderContextLazy = Box<dyn FnMut(&mut Renderer) -> SpriteRenderContext>;
@ -550,14 +550,14 @@ impl SpriteRenderContext {
let sprite_col_lights = renderer.sprite_bind_col_light(sprite_col_lights); let sprite_col_lights = renderer.sprite_bind_col_light(sprite_col_lights);
// Write sprite model to a 1D texture // Write sprite model to a 1D texture
let sprite_verts_texture = create_sprite_verts_texture(renderer, sprite_mesh); let sprite_verts_buffer = create_sprite_verts_buffer(renderer, sprite_mesh);
Self { Self {
// TODO: this are all Arcs, would it makes sense to factor out the Arc? // TODO: this are all Arcs, would it makes sense to factor out the Arc?
sprite_config: Arc::clone(&sprite_config), sprite_config: Arc::clone(&sprite_config),
sprite_data: Arc::new(sprite_data), sprite_data: Arc::new(sprite_data),
sprite_col_lights: Arc::new(sprite_col_lights), sprite_col_lights: Arc::new(sprite_col_lights),
sprite_verts_texture: Arc::new(sprite_verts_texture), sprite_verts_buffer: Arc::new(sprite_verts_buffer),
} }
}; };
Box::new(move |renderer| init.get_or_init(|| closure(renderer)).clone()) Box::new(move |renderer| init.get_or_init(|| closure(renderer)).clone())
@ -593,7 +593,7 @@ impl<V: RectRasterableVol> Terrain<V> {
sprite_globals: renderer.bind_sprite_globals( sprite_globals: renderer.bind_sprite_globals(
global_model, global_model,
lod_data, lod_data,
&sprite_render_context.sprite_verts_texture, &sprite_render_context.sprite_verts_buffer,
), ),
col_lights: Arc::new(col_lights), col_lights: Arc::new(col_lights),
waves: { waves: {