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 66ed2c704e
commit f736c180b8
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 = 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 = 13) uniform sampler s_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 = 12) restrict readonly buffer sprite_verts {
uvec2 verts[];
};
layout (std140, set = 2, binding = 0)
uniform u_terrain_locals {
@ -69,9 +72,10 @@ void main() {
// 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);
const int WIDTH = 8192; // TODO: temp
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;
//const int WIDTH = 8192; // TODO: temp
//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 = verts[vertex_index];
uint v_pos_norm = pos_atlas_pos_norm_ao.x;
uint v_atlas_pos = pos_atlas_pos_norm_ao.y;

View File

@ -14,6 +14,7 @@ pub mod texture;
// Reexports
pub use self::{
bound::Bound,
buffer::Buffer,
consts::Consts,
error::RenderError,
instances::Instances,
@ -32,7 +33,7 @@ pub use self::{
shadow::{Locals as ShadowLocals, PointLightMatrix},
skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex},
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,
VERT_PAGE_SIZE as SPRITE_VERT_PAGE_SIZE,
},

View File

@ -1,7 +1,7 @@
use super::{
super::{
AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout, Texture,
Vertex as VertexTrait,
buffer::Buffer, AaMode, Bound, Consts, GlobalsLayouts, Mesh, Renderer, TerrainLayout,
Texture, Vertex as VertexTrait,
},
lod_terrain, GlobalModel,
};
@ -88,24 +88,24 @@ impl VertexTrait for Vertex {
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);
// TODO: type buffer by Usage
/*Buffer::new(
Buffer::new(
&renderer.device,
wgpu::BufferUsage::STORAGE,
mesh.vertices(),
)*/
let mut verts = mesh.vertices_mut_vec();
let format = wgpu::TextureFormat::Rg32Uint;
)
//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;
//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);
//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"),
size: wgpu::Extent3d {
width: WIDTH,
@ -146,7 +146,7 @@ pub fn create_verts_texture(renderer: &mut Renderer, mut mesh: Mesh<Vertex>) ->
&view_info,
&sampler_info,
bytemuck::cast_slice(verts),
)
)*/
}
#[repr(C)]
@ -263,8 +263,21 @@ impl SpriteLayout {
let mut entries = GlobalsLayouts::base_globals_layout();
debug_assert_eq!(12, entries.len()); // To remember to adjust the bindings below
entries.extend_from_slice(&[
// sprite verts (t_sprite_verts)
// sprite_verts
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,
visibility: wgpu::ShaderStage::VERTEX,
ty: wgpu::BindingType::Texture {
@ -282,7 +295,7 @@ impl SpriteLayout {
comparison: false,
},
count: None,
},
},*/
]);
Self {
@ -323,20 +336,26 @@ impl SpriteLayout {
global_model: &GlobalModel,
lod_data: &lod_terrain::LodData,
noise: &Texture,
sprite_verts: &Texture,
//sprite_verts: &Texture,
sprite_verts: &Buffer<Vertex>,
) -> wgpu::BindGroup {
let mut entries = GlobalsLayouts::bind_base_globals(global_model, lod_data, noise);
entries.extend_from_slice(&[
// sprite verts (t_sprite_verts)
// sprite_verts
wgpu::BindGroupEntry {
binding: 12,
resource: sprite_verts.buf.as_entire_binding(),
},
/* sprite verts (t_sprite_verts) */
/*wgpu::BindGroupEntry {
binding: 12,
resource: wgpu::BindingResource::TextureView(&sprite_verts.view),
},
wgpu::BindGroupEntry {
binding: 13,
resource: wgpu::BindingResource::Sampler(&sprite_verts.sampler),
},
},*/
]);
device.create_bind_group(&wgpu::BindGroupDescriptor {
@ -352,7 +371,8 @@ impl SpriteLayout {
global_model: &GlobalModel,
lod_data: &lod_terrain::LodData,
noise: &Texture,
sprite_verts: &Texture,
//sprite_verts: &Texture,
sprite_verts: &Buffer<Vertex>,
) -> SpriteGlobalsBindGroup {
let bind_group =
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
/// kinds of models to the screen.
pub struct Renderer {
device: wgpu::Device,
// TODO: remove pub(super)
pub(super) device: wgpu::Device,
queue: wgpu::Queue,
surface: wgpu::Surface,
swap_chain: wgpu::SwapChain,
@ -1975,7 +1976,7 @@ fn create_pipelines(
let mut compiler = Compiler::new().ok_or(RenderError::ErrorInitializingCompiler)?;
let mut options = CompileOptions::new().ok_or(RenderError::ErrorInitializingCompiler)?;
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, _| {
Ok(ResolvedInclude {
resolved_name: name.to_string(),

View File

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

View File

@ -9,12 +9,12 @@ use crate::{
terrain::{generate_mesh, SUNLIGHT},
},
render::{
create_sprite_verts_texture,
create_sprite_verts_buffer,
pipelines::{self, ColLights},
ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel,
Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteGlobalsBindGroup,
SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture,
SPRITE_VERT_PAGE_SIZE,
Buffer, ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves,
GlobalModel, Instances, LodData, Mesh, Model, RenderError, Renderer,
SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, TerrainLocals, TerrainShadowDrawer,
TerrainVertex, Texture, SPRITE_VERT_PAGE_SIZE,
},
};
@ -351,7 +351,7 @@ pub struct SpriteRenderContext {
// Maps sprite kind + variant to data detailing how to render it
sprite_data: Arc<HashMap<(SpriteKind, usize), [SpriteData; SPRITE_LOD_LEVELS]>>,
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>;
@ -520,14 +520,14 @@ impl SpriteRenderContext {
let sprite_col_lights = renderer.sprite_bind_col_light(sprite_col_lights);
// 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 {
// TODO: this are all Arcs, would it makes sense to factor out the Arc?
sprite_config: Arc::clone(&sprite_config),
sprite_data: Arc::new(sprite_data),
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())
@ -562,7 +562,7 @@ impl<V: RectRasterableVol> Terrain<V> {
sprite_globals: renderer.bind_sprite_globals(
global_model,
lod_data,
&sprite_render_context.sprite_verts_texture,
&sprite_render_context.sprite_verts_buffer,
),
col_lights: Arc::new(col_lights),
waves: {