WIP gpu timer thing (not for squashing!)

This commit is contained in:
Imbris 2021-02-26 23:18:01 -05:00 committed by Avi Weinstock
parent 40d420e868
commit 5cdce0635d
6 changed files with 163 additions and 79 deletions

3
Cargo.lock generated
View File

@ -5110,6 +5110,9 @@ name = "strum"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"

View File

@ -95,7 +95,8 @@ rand = "0.8"
rodio = {version = "0.13", default-features = false, features = ["vorbis"]}
ron = {version = "0.6", default-features = false}
serde = {version = "1.0", features = [ "rc", "derive" ]}
strum = "0.20"
# strum = "0.20"
strum = { version = "0.20.0", features = ["derive"] }
strum_macros = "0.20"
treeculler = "0.2"
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }

View File

@ -9,6 +9,7 @@ pub mod model;
pub mod pipelines;
pub mod renderer;
pub mod texture;
mod time;
// Reexports
pub use self::{

View File

@ -1,5 +1,6 @@
mod binding;
pub(super) mod drawer;
mod spans;
use super::{
consts::Consts,
@ -284,6 +285,8 @@ pub struct Renderer {
mode: RenderMode,
resolution: Vec2<u32>,
tracer: super::time::GpuTracer<spans::Id>,
}
impl Renderer {
@ -330,7 +333,8 @@ impl Renderer {
label: None,
features: wgpu::Features::DEPTH_CLAMPING
| wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER
| wgpu::Features::PUSH_CONSTANTS,
| wgpu::Features::PUSH_CONSTANTS
| super::time::required_features(),
limits,
},
None,
@ -505,6 +509,9 @@ impl Renderer {
&depth_sampler,
);
let tracer =
super::time::GpuTracer::new(&device, &queue, "voxygen_gpu_chrome_trace.json").unwrap();
Ok(Self {
device,
queue,
@ -545,6 +552,8 @@ impl Renderer {
mode,
resolution: Vec2::new(dims.width, dims.height),
tracer,
})
}
@ -1037,7 +1046,7 @@ impl Renderer {
Err(wgpu::SwapChainError::Timeout) => {
// This will probably be resolved on the next frame
// NOTE: we don't log this because it happens very frequently with
// PresentMode::Fifo and unlimited FPS
// PresentMode::Fifo on certain machines
return Ok(None);
},
Err(err @ wgpu::SwapChainError::Outdated) => {

View File

@ -9,26 +9,29 @@ use super::{
terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow,
},
},
spans::{self, OwningSpan, Span},
Renderer, ShadowMap, ShadowMapRenderer,
};
use core::{num::NonZeroU32, ops::Range};
use std::sync::Arc;
use vek::Aabr;
pub struct Drawer<'a> {
pub struct Drawer<'frame> {
encoder: Option<wgpu::CommandEncoder>,
pub renderer: &'a mut Renderer,
pub renderer: &'frame mut Renderer,
tex: wgpu::SwapChainTexture,
globals: &'a GlobalsBindGroup,
globals: &'frame GlobalsBindGroup,
}
impl<'a> Drawer<'a> {
impl<'frame> Drawer<'frame> {
pub fn new(
encoder: wgpu::CommandEncoder,
renderer: &'a mut Renderer,
mut encoder: wgpu::CommandEncoder,
renderer: &'frame mut Renderer,
tex: wgpu::SwapChainTexture,
globals: &'a GlobalsBindGroup,
globals: &'frame GlobalsBindGroup,
) -> Self {
renderer.tracer.start_span(&mut encoder, &spans::Id::Frame);
Self {
encoder: Some(encoder),
renderer,
@ -58,6 +61,11 @@ impl<'a> Drawer<'a> {
),
});
let mut render_pass = OwningSpan::start(
&self.renderer.tracer,
render_pass,
spans::Id::DirectedShadows,
);
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
Some(ShadowPassDrawer {
@ -71,7 +79,7 @@ impl<'a> Drawer<'a> {
}
pub fn first_pass(&mut self) -> FirstPassDrawer {
let mut render_pass =
let render_pass =
self.encoder
.as_mut()
.unwrap()
@ -97,17 +105,21 @@ impl<'a> Drawer<'a> {
),
});
let mut render_pass =
OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassOne);
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]);
FirstPassDrawer {
render_pass,
renderer: &self.renderer,
figures_called: false,
}
}
pub fn second_pass(&mut self) -> SecondPassDrawer {
let mut render_pass =
let render_pass =
self.encoder
.as_mut()
.unwrap()
@ -124,6 +136,9 @@ impl<'a> Drawer<'a> {
depth_stencil_attachment: None,
});
let mut render_pass =
OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassTwo);
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]);
@ -134,7 +149,7 @@ impl<'a> Drawer<'a> {
}
pub fn third_pass(&mut self) -> ThirdPassDrawer {
let mut render_pass =
let render_pass =
self.encoder
.as_mut()
.unwrap()
@ -151,6 +166,9 @@ impl<'a> Drawer<'a> {
depth_stencil_attachment: None,
});
let mut render_pass =
OwningSpan::start(&self.renderer.tracer, render_pass, spans::Id::PassThree);
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
ThirdPassDrawer {
@ -159,13 +177,16 @@ impl<'a> Drawer<'a> {
}
}
pub fn draw_point_shadows<'data: 'a>(
pub fn draw_point_shadows<'data: 'frame>(
&mut self,
matrices: &[shadow::PointLightMatrix; 126],
chunks: impl Clone
+ Iterator<Item = (&'data Model<terrain::Vertex>, &'data terrain::BoundLocals)>,
) {
if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map {
self.renderer
.tracer
.start_span(self.encoder.as_mut().unwrap(), &spans::Id::PointShadows);
const STRIDE: usize = std::mem::size_of::<shadow::PointLightMatrix>();
let data = bytemuck::cast_slice(matrices);
@ -223,6 +244,9 @@ impl<'a> Drawer<'a> {
});
});
}
self.renderer
.tracer
.end_span(self.encoder.as_mut().unwrap(), &spans::Id::PointShadows);
}
}
@ -293,45 +317,59 @@ impl<'a> Drawer<'a> {
}
}
impl<'a> Drop for Drawer<'a> {
impl<'frame> Drop for Drawer<'frame> {
fn drop(&mut self) {
// TODO: submitting things to the queue can let the gpu start on them sooner
// maybe we should submit each render pass to the queue as they are produced?
self.renderer
.tracer
.end_span(self.encoder.as_mut().unwrap(), &spans::Id::Frame);
self.renderer
.tracer
.resolve_timestamps(self.encoder.as_mut().unwrap());
self.renderer
.queue
.submit(std::iter::once(self.encoder.take().unwrap().finish()));
// NOTE: this introduces blocking on GPU work
self.renderer
.tracer
.record_timestamps(&self.renderer.device)
}
}
// Shadow pass
pub struct ShadowPassDrawer<'pass> {
render_pass: wgpu::RenderPass<'pass>,
render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>,
pub renderer: &'pass Renderer,
shadow_renderer: &'pass ShadowMapRenderer,
}
impl<'pass> ShadowPassDrawer<'pass> {
pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> {
self.render_pass
.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::DirectedFigureShadows,
);
render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
FigureShadowDrawer {
render_pass: &mut self.render_pass,
}
FigureShadowDrawer { render_pass }
}
pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> {
self.render_pass
.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::DirectedTerrainShadows,
);
render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
TerrainShadowDrawer {
render_pass: &mut self.render_pass,
}
TerrainShadowDrawer { render_pass }
}
}
pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
}
impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
@ -347,7 +385,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
}
pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
}
impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
@ -364,83 +402,112 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
// First pass
pub struct FirstPassDrawer<'pass> {
pub(super) render_pass: wgpu::RenderPass<'pass>,
pub(super) render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>,
pub renderer: &'pass Renderer,
// TODO: hack
figures_called: bool,
}
impl<'pass> FirstPassDrawer<'pass> {
pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model<skybox::Vertex>) {
self.render_pass
.set_pipeline(&self.renderer.skybox_pipeline.pipeline);
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass.draw(0..model.len() as u32, 0..1);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::Skybox,
);
render_pass.set_pipeline(&self.renderer.skybox_pipeline.pipeline);
render_pass.set_vertex_buffer(0, model.buf().slice(..));
render_pass.draw(0..model.len() as u32, 0..1);
}
pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model<lod_terrain::Vertex>) {
self.render_pass
.set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline);
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass.draw(0..model.len() as u32, 0..1);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::Lod,
);
render_pass.set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline);
render_pass.set_vertex_buffer(0, model.buf().slice(..));
render_pass.draw(0..model.len() as u32, 0..1);
}
pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> {
self.render_pass
.set_pipeline(&self.renderer.figure_pipeline.pipeline);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
if !self.figures_called {
spans::Id::Figures1
} else {
spans::Id::Figures2
},
);
self.figures_called = true;
render_pass.set_pipeline(&self.renderer.figure_pipeline.pipeline);
FigureDrawer {
render_pass: &mut self.render_pass,
}
FigureDrawer { render_pass }
}
pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> {
self.render_pass
.set_pipeline(&self.renderer.terrain_pipeline.pipeline);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::Terrain,
);
render_pass.set_pipeline(&self.renderer.terrain_pipeline.pipeline);
TerrainDrawer {
render_pass: &mut self.render_pass,
render_pass,
col_lights: None,
}
}
pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> {
self.render_pass
.set_pipeline(&self.renderer.particle_pipeline.pipeline);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::Particles,
);
render_pass.set_pipeline(&self.renderer.particle_pipeline.pipeline);
ParticleDrawer {
render_pass: &mut self.render_pass,
}
ParticleDrawer { render_pass }
}
pub fn draw_sprites<'data: 'pass>(
&mut self,
col_lights: &'data ColLights<sprite::Locals>,
) -> SpriteDrawer<'_, 'pass> {
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::Sprites,
);
self.render_pass
.set_pipeline(&self.renderer.sprite_pipeline.pipeline);
self.render_pass
.set_bind_group(4, &col_lights.bind_group, &[]);
SpriteDrawer {
render_pass: &mut self.render_pass,
}
SpriteDrawer { render_pass }
}
pub fn draw_fluid<'data: 'pass>(
&mut self,
waves: &'data fluid::BindGroup,
) -> FluidDrawer<'_, 'pass> {
self.render_pass
.set_pipeline(&self.renderer.fluid_pipeline.pipeline);
self.render_pass.set_bind_group(2, &waves.bind_group, &[]);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::Fluid,
);
render_pass.set_pipeline(&self.renderer.fluid_pipeline.pipeline);
render_pass.set_bind_group(2, &waves.bind_group, &[]);
FluidDrawer {
render_pass: &mut self.render_pass,
}
FluidDrawer { render_pass }
}
}
pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
}
impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
@ -460,7 +527,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
}
pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
col_lights: Option<&'pass_ref Arc<ColLights<terrain::Locals>>>,
}
@ -492,7 +559,7 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> {
}
pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
}
impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
@ -513,7 +580,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
}
pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
}
impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> {
@ -550,7 +617,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> {
}
pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
}
impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
@ -567,8 +634,8 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
// Second pass: clouds
pub struct SecondPassDrawer<'pass> {
pub(super) render_pass: wgpu::RenderPass<'pass>,
pub renderer: &'pass Renderer,
render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>,
renderer: &'pass Renderer,
}
impl<'pass> SecondPassDrawer<'pass> {
@ -583,31 +650,33 @@ impl<'pass> SecondPassDrawer<'pass> {
// Third pass: postprocess + ui
pub struct ThirdPassDrawer<'pass> {
render_pass: wgpu::RenderPass<'pass>,
render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>,
renderer: &'pass Renderer,
}
impl<'pass> ThirdPassDrawer<'pass> {
pub fn draw_post_process(&mut self) {
self.render_pass
.set_pipeline(&self.renderer.postprocess_pipeline.pipeline);
self.render_pass
.set_bind_group(1, &self.renderer.locals.postprocess_bind.bind_group, &[]);
self.render_pass.draw(0..3, 0..1);
let mut render_pass = Span::start(
&self.renderer.tracer,
&mut *self.render_pass,
spans::Id::Postprocess,
);
render_pass.set_pipeline(&self.renderer.postprocess_pipeline.pipeline);
render_pass.set_bind_group(1, &self.renderer.locals.postprocess_bind.bind_group, &[]);
render_pass.draw(0..3, 0..1);
}
pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> {
self.render_pass
.set_pipeline(&self.renderer.ui_pipeline.pipeline);
let mut render_pass =
Span::start(&self.renderer.tracer, &mut *self.render_pass, spans::Id::Ui);
render_pass.set_pipeline(&self.renderer.ui_pipeline.pipeline);
UiDrawer {
render_pass: &mut self.render_pass,
}
UiDrawer { render_pass }
}
}
pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
}
pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> {
@ -628,7 +697,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
// Note: not actually prepared yet
// we do this to avoid having to write extra code for the set functions
let mut prepared = PreparedUiDrawer {
render_pass: self.render_pass,
render_pass: &mut *self.render_pass,
};
// Prepare
prepared.set_locals(locals);

View File

@ -381,6 +381,7 @@ impl Scene {
&self.col_lights.texture(model),
);
}
drop(figure_drawer);
drawer.draw_skybox(&self.skybox.model);
}