mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Implement toggleable gpu profiling that saves the timings from a recent frame with the screenshot key, rebase fixes
This commit is contained in:
parent
5cdce0635d
commit
d2e2580df4
544
Cargo.lock
generated
544
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -110,3 +110,5 @@ nativeBuildInputs = ["pkg-config"]
|
|||||||
# macos CI fix isn't merged yet
|
# macos CI fix isn't merged yet
|
||||||
winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" }
|
winit = { git = "https://gitlab.com/veloren/winit.git", branch = "macos-test-spiffed" }
|
||||||
vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" }
|
vek = { git = "https://gitlab.com/veloren/vek.git", branch = "fix_intrinsics2" }
|
||||||
|
# patch wgpu so we can use wgpu-profiler crate
|
||||||
|
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "1f1a7e5dd47a1610733bbc3989414acb62395359" }
|
||||||
|
@ -46,6 +46,7 @@ i18n = {package = "veloren-i18n", path = "i18n"}
|
|||||||
# Graphics
|
# Graphics
|
||||||
winit = {version = "0.24.0", features = ["serde"]}
|
winit = {version = "0.24.0", features = ["serde"]}
|
||||||
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "1f1a7e5dd47a1610733bbc3989414acb62395359" }
|
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "1f1a7e5dd47a1610733bbc3989414acb62395359" }
|
||||||
|
wgpu-profiler = "0.2.1"
|
||||||
bytemuck = { version="1.4", features=["derive"] }
|
bytemuck = { version="1.4", features=["derive"] }
|
||||||
shaderc = "0.6.2"
|
shaderc = "0.6.2"
|
||||||
|
|
||||||
@ -95,8 +96,7 @@ rand = "0.8"
|
|||||||
rodio = {version = "0.13", default-features = false, features = ["vorbis"]}
|
rodio = {version = "0.13", default-features = false, features = ["vorbis"]}
|
||||||
ron = {version = "0.6", default-features = false}
|
ron = {version = "0.6", default-features = false}
|
||||||
serde = {version = "1.0", features = [ "rc", "derive" ]}
|
serde = {version = "1.0", features = [ "rc", "derive" ]}
|
||||||
# strum = "0.20"
|
strum = "0.20"
|
||||||
strum = { version = "0.20.0", features = ["derive"] }
|
|
||||||
strum_macros = "0.20"
|
strum_macros = "0.20"
|
||||||
treeculler = "0.2"
|
treeculler = "0.2"
|
||||||
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
|
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
|
||||||
|
@ -82,6 +82,9 @@ widget_ids! {
|
|||||||
refresh_rate,
|
refresh_rate,
|
||||||
refresh_rate_label,
|
refresh_rate_label,
|
||||||
//
|
//
|
||||||
|
gpu_profiler_button,
|
||||||
|
gpu_profiler_label,
|
||||||
|
//
|
||||||
particles_button,
|
particles_button,
|
||||||
particles_label,
|
particles_label,
|
||||||
lossy_terrain_compression_button,
|
lossy_terrain_compression_button,
|
||||||
@ -902,11 +905,37 @@ impl<'a> Widget for Video<'a> {
|
|||||||
.set(state.ids.shadow_mode_map_resolution_value, ui);
|
.set(state.ids.shadow_mode_map_resolution_value, ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GPU Profiler
|
||||||
|
Text::new(&self.localized_strings.get("hud.settings.gpu_profiler"))
|
||||||
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.down_from(state.ids.shadow_mode_list, 8.0)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.gpu_profiler_label, ui);
|
||||||
|
|
||||||
|
let gpu_profiler_enabled = ToggleButton::new(
|
||||||
|
render_mode.profiler_enabled,
|
||||||
|
self.imgs.checkbox,
|
||||||
|
self.imgs.checkbox_checked,
|
||||||
|
)
|
||||||
|
.w_h(18.0, 18.0)
|
||||||
|
.right_from(state.ids.gpu_profiler_label, 10.0)
|
||||||
|
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||||
|
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||||
|
.set(state.ids.gpu_profiler_button, ui);
|
||||||
|
|
||||||
|
if render_mode.profiler_enabled != gpu_profiler_enabled {
|
||||||
|
events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode {
|
||||||
|
profiler_enabled: gpu_profiler_enabled,
|
||||||
|
..render_mode.clone()
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
// Particles
|
// Particles
|
||||||
Text::new(&self.localized_strings.get("hud.settings.particles"))
|
Text::new(&self.localized_strings.get("hud.settings.particles"))
|
||||||
.font_size(self.fonts.cyri.scale(14))
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
.font_id(self.fonts.cyri.conrod_id)
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
.down_from(state.ids.shadow_mode_list, 8.0)
|
.down_from(state.ids.gpu_profiler_label, 8.0)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.particles_label, ui);
|
.set(state.ids.particles_label, ui);
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
const_generics,
|
const_generics,
|
||||||
drain_filter,
|
drain_filter,
|
||||||
once_cell,
|
once_cell,
|
||||||
trait_alias
|
trait_alias,
|
||||||
|
or_patterns
|
||||||
)]
|
)]
|
||||||
#![recursion_limit = "2048"]
|
#![recursion_limit = "2048"]
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ pub mod mesh;
|
|||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod pipelines;
|
pub mod pipelines;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
|
mod scope;
|
||||||
pub mod texture;
|
pub mod texture;
|
||||||
mod time;
|
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
pub use self::{
|
pub use self::{
|
||||||
@ -271,4 +271,5 @@ pub struct RenderMode {
|
|||||||
pub shadow: ShadowMode,
|
pub shadow: ShadowMode,
|
||||||
pub upscale_mode: UpscaleMode,
|
pub upscale_mode: UpscaleMode,
|
||||||
pub present_mode: PresentMode,
|
pub present_mode: PresentMode,
|
||||||
|
pub profiler_enabled: bool,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
mod binding;
|
mod binding;
|
||||||
pub(super) mod drawer;
|
pub(super) mod drawer;
|
||||||
mod spans;
|
// Consts and bind groups for post-process and clouds
|
||||||
|
mod locals;
|
||||||
|
mod shaders;
|
||||||
|
mod shadow_map;
|
||||||
|
|
||||||
|
use locals::Locals;
|
||||||
|
use shaders::Shaders;
|
||||||
|
use shadow_map::{ShadowMap, ShadowMapRenderer};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
consts::Consts,
|
consts::Consts,
|
||||||
@ -18,141 +25,15 @@ use super::{
|
|||||||
use common::assets::{self, AssetExt, AssetHandle};
|
use common::assets::{self, AssetExt, AssetHandle};
|
||||||
use common_base::span;
|
use common_base::span;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use hashbrown::HashMap;
|
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
// TODO: yeet this somewhere else
|
||||||
/// A type representing data that can be converted to an immutable texture map
|
/// A type representing data that can be converted to an immutable texture map
|
||||||
/// of ColLight data (used for texture atlases created during greedy meshing).
|
/// of ColLight data (used for texture atlases created during greedy meshing).
|
||||||
// TODO: revert to u16
|
// TODO: revert to u16
|
||||||
pub type ColLightInfo = (Vec<[u8; 4]>, Vec2<u32>);
|
pub type ColLightInfo = (Vec<[u8; 4]>, Vec2<u32>);
|
||||||
|
|
||||||
/// Load from a GLSL file.
|
|
||||||
pub struct Glsl(String);
|
|
||||||
|
|
||||||
impl From<String> for Glsl {
|
|
||||||
fn from(s: String) -> Glsl { Glsl(s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl assets::Asset for Glsl {
|
|
||||||
type Loader = assets::LoadFrom<String, assets::StringLoader>;
|
|
||||||
|
|
||||||
const EXTENSION: &'static str = "glsl";
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Shaders {
|
|
||||||
shaders: HashMap<String, AssetHandle<Glsl>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl assets::Compound for Shaders {
|
|
||||||
// TODO: Taking the specifier argument as a base for shaders specifiers
|
|
||||||
// would allow to use several shaders groups easily
|
|
||||||
fn load<S: assets::source::Source>(
|
|
||||||
_: &assets::AssetCache<S>,
|
|
||||||
_: &str,
|
|
||||||
) -> Result<Shaders, assets::Error> {
|
|
||||||
let shaders = [
|
|
||||||
"include.constants",
|
|
||||||
"include.globals",
|
|
||||||
"include.sky",
|
|
||||||
"include.light",
|
|
||||||
"include.srgb",
|
|
||||||
"include.random",
|
|
||||||
"include.lod",
|
|
||||||
"include.shadows",
|
|
||||||
"antialias.none",
|
|
||||||
"antialias.fxaa",
|
|
||||||
"antialias.msaa-x4",
|
|
||||||
"antialias.msaa-x8",
|
|
||||||
"antialias.msaa-x16",
|
|
||||||
"include.cloud.none",
|
|
||||||
"include.cloud.regular",
|
|
||||||
"figure-vert",
|
|
||||||
"light-shadows-figure-vert",
|
|
||||||
"light-shadows-directed-vert",
|
|
||||||
"light-shadows-directed-frag",
|
|
||||||
"point-light-shadows-vert",
|
|
||||||
"skybox-vert",
|
|
||||||
"skybox-frag",
|
|
||||||
"figure-frag",
|
|
||||||
"terrain-vert",
|
|
||||||
"terrain-frag",
|
|
||||||
"fluid-vert",
|
|
||||||
"fluid-frag.cheap",
|
|
||||||
"fluid-frag.shiny",
|
|
||||||
"sprite-vert",
|
|
||||||
"sprite-frag",
|
|
||||||
"particle-vert",
|
|
||||||
"particle-frag",
|
|
||||||
"ui-vert",
|
|
||||||
"ui-frag",
|
|
||||||
"lod-terrain-vert",
|
|
||||||
"lod-terrain-frag",
|
|
||||||
"clouds-vert",
|
|
||||||
"clouds-frag",
|
|
||||||
"postprocess-vert",
|
|
||||||
"postprocess-frag",
|
|
||||||
"player-shadow-frag",
|
|
||||||
"light-shadows-geom",
|
|
||||||
"light-shadows-frag",
|
|
||||||
];
|
|
||||||
|
|
||||||
let shaders = shaders
|
|
||||||
.iter()
|
|
||||||
.map(|shader| {
|
|
||||||
let full_specifier = ["voxygen.shaders.", shader].concat();
|
|
||||||
let asset = AssetExt::load(&full_specifier)?;
|
|
||||||
Ok((String::from(*shader), asset))
|
|
||||||
})
|
|
||||||
.collect::<Result<HashMap<_, _>, assets::Error>>()?;
|
|
||||||
|
|
||||||
Ok(Self { shaders })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Shaders {
|
|
||||||
fn get(&self, shader: &str) -> Option<impl std::ops::Deref<Target = Glsl>> {
|
|
||||||
self.shaders.get(shader).map(|a| a.read())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type that holds shadow map data. Since shadow mapping may not be
|
|
||||||
/// supported on all platforms, we try to keep it separate.
|
|
||||||
struct ShadowMapRenderer {
|
|
||||||
// directed_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
|
||||||
// point_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
|
||||||
directed_depth: Texture,
|
|
||||||
|
|
||||||
point_depth: Texture,
|
|
||||||
|
|
||||||
point_pipeline: shadow::PointShadowPipeline,
|
|
||||||
terrain_directed_pipeline: shadow::ShadowPipeline,
|
|
||||||
figure_directed_pipeline: shadow::ShadowFigurePipeline,
|
|
||||||
layout: shadow::ShadowLayout,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ShadowMap {
|
|
||||||
Enabled(ShadowMapRenderer),
|
|
||||||
Disabled {
|
|
||||||
dummy_point: Texture, // Cube texture
|
|
||||||
dummy_directed: Texture,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ShadowMap {
|
|
||||||
fn textures(&self) -> (&Texture, &Texture) {
|
|
||||||
match self {
|
|
||||||
Self::Enabled(renderer) => (&renderer.point_depth, &renderer.directed_depth),
|
|
||||||
Self::Disabled {
|
|
||||||
dummy_point,
|
|
||||||
dummy_directed,
|
|
||||||
} => (dummy_point, dummy_directed),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_enabled(&self) -> bool { matches!(self, Self::Enabled(_)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type that stores all the layouts associated with this renderer.
|
/// A type that stores all the layouts associated with this renderer.
|
||||||
struct Layouts {
|
struct Layouts {
|
||||||
global: GlobalsLayouts,
|
global: GlobalsLayouts,
|
||||||
@ -167,72 +48,37 @@ struct Layouts {
|
|||||||
ui: ui::UiLayout,
|
ui: ui::UiLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Locals {
|
/// A type that stores all the pipelines associated with this renderer.
|
||||||
clouds: Consts<clouds::Locals>,
|
struct Pipelines {
|
||||||
clouds_bind: clouds::BindGroup,
|
figure: figure::FigurePipeline,
|
||||||
|
fluid: fluid::FluidPipeline,
|
||||||
postprocess: Consts<postprocess::Locals>,
|
lod_terrain: lod_terrain::LodTerrainPipeline,
|
||||||
postprocess_bind: postprocess::BindGroup,
|
particle: particle::ParticlePipeline,
|
||||||
|
clouds: clouds::CloudsPipeline,
|
||||||
|
postprocess: postprocess::PostProcessPipeline,
|
||||||
|
// Consider reenabling at some time
|
||||||
|
// player_shadow: figure::FigurePipeline,
|
||||||
|
skybox: skybox::SkyboxPipeline,
|
||||||
|
sprite: sprite::SpritePipeline,
|
||||||
|
terrain: terrain::TerrainPipeline,
|
||||||
|
ui: ui::UiPipeline,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Locals {
|
/// Render target views
|
||||||
fn new(
|
struct Views {
|
||||||
device: &wgpu::Device,
|
// NOTE: unused for now
|
||||||
layouts: &Layouts,
|
win_depth: wgpu::TextureView,
|
||||||
clouds_locals: Consts<clouds::Locals>,
|
|
||||||
postprocess_locals: Consts<postprocess::Locals>,
|
|
||||||
tgt_color_view: &wgpu::TextureView,
|
|
||||||
tgt_depth_view: &wgpu::TextureView,
|
|
||||||
tgt_color_pp_view: &wgpu::TextureView,
|
|
||||||
sampler: &wgpu::Sampler,
|
|
||||||
depth_sampler: &wgpu::Sampler,
|
|
||||||
) -> Self {
|
|
||||||
let clouds_bind = layouts.clouds.bind(
|
|
||||||
device,
|
|
||||||
tgt_color_view,
|
|
||||||
tgt_depth_view,
|
|
||||||
sampler,
|
|
||||||
depth_sampler,
|
|
||||||
&clouds_locals,
|
|
||||||
);
|
|
||||||
let postprocess_bind =
|
|
||||||
layouts
|
|
||||||
.postprocess
|
|
||||||
.bind(device, tgt_color_pp_view, sampler, &postprocess_locals);
|
|
||||||
|
|
||||||
Self {
|
tgt_color: wgpu::TextureView,
|
||||||
clouds: clouds_locals,
|
tgt_depth: wgpu::TextureView,
|
||||||
clouds_bind,
|
// TODO: rename
|
||||||
postprocess: postprocess_locals,
|
tgt_color_pp: wgpu::TextureView,
|
||||||
postprocess_bind,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rebind(
|
/// Shadow rendering textures, layouts, pipelines, and bind groups
|
||||||
&mut self,
|
struct Shadow {
|
||||||
device: &wgpu::Device,
|
map: ShadowMap,
|
||||||
layouts: &Layouts,
|
bind: ShadowTexturesBindGroup,
|
||||||
// Call when these are recreated and need to be rebound
|
|
||||||
// e.g. resizing
|
|
||||||
tgt_color_view: &wgpu::TextureView,
|
|
||||||
tgt_depth_view: &wgpu::TextureView,
|
|
||||||
tgt_color_pp_view: &wgpu::TextureView,
|
|
||||||
sampler: &wgpu::Sampler,
|
|
||||||
depth_sampler: &wgpu::Sampler,
|
|
||||||
) {
|
|
||||||
self.clouds_bind = layouts.clouds.bind(
|
|
||||||
device,
|
|
||||||
tgt_color_view,
|
|
||||||
tgt_depth_view,
|
|
||||||
sampler,
|
|
||||||
depth_sampler,
|
|
||||||
&self.clouds,
|
|
||||||
);
|
|
||||||
self.postprocess_bind =
|
|
||||||
layouts
|
|
||||||
.postprocess
|
|
||||||
.bind(device, tgt_color_pp_view, sampler, &self.postprocess);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that encapsulates rendering state. `Renderer` is central to Voxygen's
|
/// A type that encapsulates rendering state. `Renderer` is central to Voxygen's
|
||||||
@ -242,51 +88,28 @@ impl Locals {
|
|||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
device: wgpu::Device,
|
device: wgpu::Device,
|
||||||
queue: wgpu::Queue,
|
queue: wgpu::Queue,
|
||||||
|
surface: wgpu::Surface,
|
||||||
swap_chain: wgpu::SwapChain,
|
swap_chain: wgpu::SwapChain,
|
||||||
sc_desc: wgpu::SwapChainDescriptor,
|
sc_desc: wgpu::SwapChainDescriptor,
|
||||||
surface: wgpu::Surface,
|
|
||||||
|
|
||||||
win_depth_view: wgpu::TextureView,
|
|
||||||
|
|
||||||
tgt_color_view: wgpu::TextureView,
|
|
||||||
tgt_depth_view: wgpu::TextureView,
|
|
||||||
// TODO: rename
|
|
||||||
tgt_color_pp_view: wgpu::TextureView,
|
|
||||||
|
|
||||||
sampler: wgpu::Sampler,
|
sampler: wgpu::Sampler,
|
||||||
depth_sampler: wgpu::Sampler,
|
depth_sampler: wgpu::Sampler,
|
||||||
|
|
||||||
shadow_map: ShadowMap,
|
|
||||||
shadow_bind: ShadowTexturesBindGroup,
|
|
||||||
|
|
||||||
layouts: Layouts,
|
layouts: Layouts,
|
||||||
|
pipelines: Pipelines,
|
||||||
figure_pipeline: figure::FigurePipeline,
|
shadow: Shadow,
|
||||||
fluid_pipeline: fluid::FluidPipeline,
|
|
||||||
lod_terrain_pipeline: lod_terrain::LodTerrainPipeline,
|
|
||||||
particle_pipeline: particle::ParticlePipeline,
|
|
||||||
clouds_pipeline: clouds::CloudsPipeline,
|
|
||||||
postprocess_pipeline: postprocess::PostProcessPipeline,
|
|
||||||
// Consider reenabling at some time
|
|
||||||
// player_shadow_pipeline: figure::FigurePipeline,
|
|
||||||
skybox_pipeline: skybox::SkyboxPipeline,
|
|
||||||
sprite_pipeline: sprite::SpritePipeline,
|
|
||||||
terrain_pipeline: terrain::TerrainPipeline,
|
|
||||||
ui_pipeline: ui::UiPipeline,
|
|
||||||
|
|
||||||
shaders: AssetHandle<Shaders>,
|
|
||||||
|
|
||||||
// Note: we keep these here since their bind groups need to be updated if we resize the
|
// Note: we keep these here since their bind groups need to be updated if we resize the
|
||||||
// color/depth textures
|
// color/depth textures
|
||||||
locals: Locals,
|
locals: Locals,
|
||||||
|
views: Views,
|
||||||
noise_tex: Texture,
|
noise_tex: Texture,
|
||||||
|
|
||||||
mode: RenderMode,
|
shaders: AssetHandle<Shaders>,
|
||||||
|
|
||||||
|
mode: RenderMode,
|
||||||
resolution: Vec2<u32>,
|
resolution: Vec2<u32>,
|
||||||
|
|
||||||
tracer: super::time::GpuTracer<spans::Id>,
|
profiler: wgpu_profiler::GpuProfiler,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
@ -334,7 +157,10 @@ impl Renderer {
|
|||||||
features: wgpu::Features::DEPTH_CLAMPING
|
features: wgpu::Features::DEPTH_CLAMPING
|
||||||
| wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER
|
| wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER
|
||||||
| wgpu::Features::PUSH_CONSTANTS
|
| wgpu::Features::PUSH_CONSTANTS
|
||||||
| super::time::required_features(),
|
// TODO: make optional based on enabling profiling
|
||||||
|
// NOTE: requires recreating the device/queue is this setting changes
|
||||||
|
// alternatively it could be a compile time feature toggle
|
||||||
|
| super::scope::required_features(),
|
||||||
limits,
|
limits,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
@ -399,16 +225,7 @@ impl Renderer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (
|
let (
|
||||||
skybox_pipeline,
|
pipelines,
|
||||||
figure_pipeline,
|
|
||||||
terrain_pipeline,
|
|
||||||
fluid_pipeline,
|
|
||||||
sprite_pipeline,
|
|
||||||
particle_pipeline,
|
|
||||||
ui_pipeline,
|
|
||||||
lod_terrain_pipeline,
|
|
||||||
clouds_pipeline,
|
|
||||||
postprocess_pipeline,
|
|
||||||
//player_shadow_pipeline,
|
//player_shadow_pipeline,
|
||||||
point_shadow_pipeline,
|
point_shadow_pipeline,
|
||||||
terrain_directed_shadow_pipeline,
|
terrain_directed_shadow_pipeline,
|
||||||
@ -422,8 +239,7 @@ impl Renderer {
|
|||||||
shadow_views.is_some(),
|
shadow_views.is_some(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (tgt_color_view, tgt_depth_view, tgt_color_pp_view, win_depth_view) =
|
let views = Self::create_rt_views(&device, (dims.width, dims.height), &mode)?;
|
||||||
Self::create_rt_views(&device, (dims.width, dims.height), &mode)?;
|
|
||||||
|
|
||||||
let shadow_map = if let (
|
let shadow_map = if let (
|
||||||
Some(point_pipeline),
|
Some(point_pipeline),
|
||||||
@ -467,6 +283,11 @@ impl Renderer {
|
|||||||
.bind_shadow_textures(&device, point, directed)
|
.bind_shadow_textures(&device, point, directed)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let shadow = Shadow {
|
||||||
|
map: shadow_map,
|
||||||
|
bind: shadow_bind,
|
||||||
|
};
|
||||||
|
|
||||||
let create_sampler = |filter| {
|
let create_sampler = |filter| {
|
||||||
device.create_sampler(&wgpu::SamplerDescriptor {
|
device.create_sampler(&wgpu::SamplerDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
@ -502,78 +323,52 @@ impl Renderer {
|
|||||||
&layouts,
|
&layouts,
|
||||||
clouds_locals,
|
clouds_locals,
|
||||||
postprocess_locals,
|
postprocess_locals,
|
||||||
&tgt_color_view,
|
&views.tgt_color,
|
||||||
&tgt_depth_view,
|
&views.tgt_depth,
|
||||||
&tgt_color_pp_view,
|
&views.tgt_color_pp,
|
||||||
&sampler,
|
&sampler,
|
||||||
&depth_sampler,
|
&depth_sampler,
|
||||||
);
|
);
|
||||||
|
|
||||||
let tracer =
|
let mut profiler = wgpu_profiler::GpuProfiler::new(4, queue.get_timestamp_period());
|
||||||
super::time::GpuTracer::new(&device, &queue, "voxygen_gpu_chrome_trace.json").unwrap();
|
profiler.enable_timer = mode.profiler_enabled;
|
||||||
|
profiler.enable_debug_marker = mode.profiler_enabled;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
device,
|
device,
|
||||||
queue,
|
queue,
|
||||||
|
surface,
|
||||||
swap_chain,
|
swap_chain,
|
||||||
sc_desc,
|
sc_desc,
|
||||||
surface,
|
|
||||||
|
|
||||||
win_depth_view,
|
layouts,
|
||||||
|
pipelines,
|
||||||
tgt_color_view,
|
shadow,
|
||||||
tgt_depth_view,
|
locals,
|
||||||
tgt_color_pp_view,
|
views,
|
||||||
|
|
||||||
sampler,
|
sampler,
|
||||||
depth_sampler,
|
depth_sampler,
|
||||||
|
|
||||||
shadow_map,
|
|
||||||
shadow_bind,
|
|
||||||
|
|
||||||
layouts,
|
|
||||||
|
|
||||||
skybox_pipeline,
|
|
||||||
figure_pipeline,
|
|
||||||
terrain_pipeline,
|
|
||||||
fluid_pipeline,
|
|
||||||
sprite_pipeline,
|
|
||||||
particle_pipeline,
|
|
||||||
ui_pipeline,
|
|
||||||
lod_terrain_pipeline,
|
|
||||||
clouds_pipeline,
|
|
||||||
postprocess_pipeline,
|
|
||||||
shaders,
|
|
||||||
//player_shadow_pipeline,
|
|
||||||
locals,
|
|
||||||
|
|
||||||
noise_tex,
|
noise_tex,
|
||||||
|
|
||||||
mode,
|
shaders,
|
||||||
|
|
||||||
|
mode,
|
||||||
resolution: Vec2::new(dims.width, dims.height),
|
resolution: Vec2::new(dims.width, dims.height),
|
||||||
|
|
||||||
tracer,
|
profiler,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get references to the internal render target views that get rendered to
|
|
||||||
/// before post-processing.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn tgt_views(&self) -> (&wgpu::TextureView, &wgpu::TextureView) {
|
|
||||||
(&self.tgt_color_view, &self.tgt_depth_view)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get references to the internal render target views that get displayed
|
|
||||||
/// directly by the window.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn win_views(&self) -> &wgpu::TextureView { &self.win_depth_view }
|
|
||||||
|
|
||||||
/// Change the render mode.
|
/// Change the render mode.
|
||||||
pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> {
|
pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> {
|
||||||
self.mode = mode;
|
self.mode = mode;
|
||||||
self.sc_desc.present_mode = self.mode.present_mode.into();
|
self.sc_desc.present_mode = self.mode.present_mode.into();
|
||||||
|
|
||||||
|
// Enable/disable profiler
|
||||||
|
self.profiler.enable_timer = self.mode.profiler_enabled;
|
||||||
|
self.profiler.enable_debug_marker = self.mode.profiler_enabled;
|
||||||
|
|
||||||
// Recreate render target
|
// Recreate render target
|
||||||
self.on_resize(self.resolution)?;
|
self.on_resize(self.resolution)?;
|
||||||
|
|
||||||
@ -597,31 +392,26 @@ impl Renderer {
|
|||||||
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
|
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
|
||||||
|
|
||||||
// Resize other render targets
|
// Resize other render targets
|
||||||
let (tgt_color_view, tgt_depth_view, tgt_color_pp_view, win_depth_view) =
|
self.views = Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?;
|
||||||
Self::create_rt_views(&mut self.device, (dims.x, dims.y), &self.mode)?;
|
|
||||||
self.win_depth_view = win_depth_view;
|
|
||||||
self.tgt_color_view = tgt_color_view;
|
|
||||||
self.tgt_depth_view = tgt_depth_view;
|
|
||||||
self.tgt_color_pp_view = tgt_color_pp_view;
|
|
||||||
// Rebind views to clouds/postprocess bind groups
|
// Rebind views to clouds/postprocess bind groups
|
||||||
self.locals.rebind(
|
self.locals.rebind(
|
||||||
&self.device,
|
&self.device,
|
||||||
&self.layouts,
|
&self.layouts,
|
||||||
&self.tgt_color_view,
|
&self.views.tgt_color,
|
||||||
&self.tgt_depth_view,
|
&self.views.tgt_depth,
|
||||||
&self.tgt_color_pp_view,
|
&self.views.tgt_color_pp,
|
||||||
&self.sampler,
|
&self.sampler,
|
||||||
&self.depth_sampler,
|
&self.depth_sampler,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let (ShadowMap::Enabled(shadow_map), ShadowMode::Map(mode)) =
|
if let (ShadowMap::Enabled(shadow_map), ShadowMode::Map(mode)) =
|
||||||
(&mut self.shadow_map, self.mode.shadow)
|
(&mut self.shadow.map, self.mode.shadow)
|
||||||
{
|
{
|
||||||
match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) {
|
match Self::create_shadow_views(&mut self.device, (dims.x, dims.y), &mode) {
|
||||||
Ok((point_depth, directed_depth)) => {
|
Ok((point_depth, directed_depth)) => {
|
||||||
shadow_map.point_depth = point_depth;
|
shadow_map.point_depth = point_depth;
|
||||||
shadow_map.directed_depth = directed_depth;
|
shadow_map.directed_depth = directed_depth;
|
||||||
self.shadow_bind = self.layouts.global.bind_shadow_textures(
|
self.shadow.bind = self.layouts.global.bind_shadow_textures(
|
||||||
&self.device,
|
&self.device,
|
||||||
&shadow_map.point_depth,
|
&shadow_map.point_depth,
|
||||||
&shadow_map.directed_depth,
|
&shadow_map.directed_depth,
|
||||||
@ -637,19 +427,12 @@ impl Renderer {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create render target views
|
||||||
fn create_rt_views(
|
fn create_rt_views(
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
size: (u32, u32),
|
size: (u32, u32),
|
||||||
mode: &RenderMode,
|
mode: &RenderMode,
|
||||||
) -> Result<
|
) -> Result<Views, RenderError> {
|
||||||
(
|
|
||||||
wgpu::TextureView,
|
|
||||||
wgpu::TextureView,
|
|
||||||
wgpu::TextureView,
|
|
||||||
wgpu::TextureView,
|
|
||||||
),
|
|
||||||
RenderError,
|
|
||||||
> {
|
|
||||||
let upscaled = Vec2::<u32>::from(size)
|
let upscaled = Vec2::<u32>::from(size)
|
||||||
.map(|e| (e as f32 * mode.upscale_mode.factor) as u32)
|
.map(|e| (e as f32 * mode.upscale_mode.factor) as u32)
|
||||||
.into_tuple();
|
.into_tuple();
|
||||||
@ -743,12 +526,12 @@ impl Renderer {
|
|||||||
array_layer_count: None,
|
array_layer_count: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok((
|
Ok(Views {
|
||||||
tgt_color_view,
|
tgt_color: tgt_color_view,
|
||||||
tgt_depth_view,
|
tgt_depth: tgt_depth_view,
|
||||||
tgt_color_pp_view,
|
tgt_color_pp: tgt_color_pp_view,
|
||||||
win_depth_view,
|
win_depth: win_depth_view,
|
||||||
))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_dummy_shadow_tex(device: &wgpu::Device, queue: &wgpu::Queue) -> (Texture, Texture) {
|
fn create_dummy_shadow_tex(device: &wgpu::Device, queue: &wgpu::Queue) -> (Texture, Texture) {
|
||||||
@ -959,7 +742,7 @@ impl Renderer {
|
|||||||
|
|
||||||
/// Get the resolution of the shadow render target.
|
/// Get the resolution of the shadow render target.
|
||||||
pub fn get_shadow_resolution(&self) -> (Vec2<u32>, Vec2<u32>) {
|
pub fn get_shadow_resolution(&self) -> (Vec2<u32>, Vec2<u32>) {
|
||||||
if let ShadowMap::Enabled(shadow_map) = &self.shadow_map {
|
if let ShadowMap::Enabled(shadow_map) = &self.shadow.map {
|
||||||
(
|
(
|
||||||
shadow_map.point_depth.get_dimensions().xy(),
|
shadow_map.point_depth.get_dimensions().xy(),
|
||||||
shadow_map.directed_depth.get_dimensions().xy(),
|
shadow_map.directed_depth.get_dimensions().xy(),
|
||||||
@ -993,7 +776,6 @@ impl Renderer {
|
|||||||
/// there may be some GPUs that don't quite support it correctly, the
|
/// there may be some GPUs that don't quite support it correctly, the
|
||||||
/// impact is relatively small, so there is no reason not to enable it where
|
/// impact is relatively small, so there is no reason not to enable it where
|
||||||
/// available.
|
/// available.
|
||||||
#[allow(unsafe_code)]
|
|
||||||
fn enable_seamless_cube_maps() {
|
fn enable_seamless_cube_maps() {
|
||||||
todo!()
|
todo!()
|
||||||
// unsafe {
|
// unsafe {
|
||||||
@ -1072,34 +854,16 @@ impl Renderer {
|
|||||||
&self.shaders.read(),
|
&self.shaders.read(),
|
||||||
&self.mode,
|
&self.mode,
|
||||||
&self.sc_desc,
|
&self.sc_desc,
|
||||||
self.shadow_map.is_enabled(),
|
self.shadow.map.is_enabled(),
|
||||||
) {
|
) {
|
||||||
Ok((
|
Ok((
|
||||||
skybox_pipeline,
|
pipelines,
|
||||||
figure_pipeline,
|
|
||||||
terrain_pipeline,
|
|
||||||
fluid_pipeline,
|
|
||||||
sprite_pipeline,
|
|
||||||
particle_pipeline,
|
|
||||||
ui_pipeline,
|
|
||||||
lod_terrain_pipeline,
|
|
||||||
clouds_pipeline,
|
|
||||||
postprocess_pipeline,
|
|
||||||
//player_shadow_pipeline,
|
//player_shadow_pipeline,
|
||||||
point_shadow_pipeline,
|
point_shadow_pipeline,
|
||||||
terrain_directed_shadow_pipeline,
|
terrain_directed_shadow_pipeline,
|
||||||
figure_directed_shadow_pipeline,
|
figure_directed_shadow_pipeline,
|
||||||
)) => {
|
)) => {
|
||||||
self.skybox_pipeline = skybox_pipeline;
|
self.pipelines = pipelines;
|
||||||
self.figure_pipeline = figure_pipeline;
|
|
||||||
self.terrain_pipeline = terrain_pipeline;
|
|
||||||
self.fluid_pipeline = fluid_pipeline;
|
|
||||||
self.sprite_pipeline = sprite_pipeline;
|
|
||||||
self.particle_pipeline = particle_pipeline;
|
|
||||||
self.ui_pipeline = ui_pipeline;
|
|
||||||
self.lod_terrain_pipeline = lod_terrain_pipeline;
|
|
||||||
self.clouds_pipeline = clouds_pipeline;
|
|
||||||
self.postprocess_pipeline = postprocess_pipeline;
|
|
||||||
//self.player_shadow_pipeline = player_shadow_pipeline;
|
//self.player_shadow_pipeline = player_shadow_pipeline;
|
||||||
if let (
|
if let (
|
||||||
Some(point_pipeline),
|
Some(point_pipeline),
|
||||||
@ -1110,7 +874,7 @@ impl Renderer {
|
|||||||
point_shadow_pipeline,
|
point_shadow_pipeline,
|
||||||
terrain_directed_shadow_pipeline,
|
terrain_directed_shadow_pipeline,
|
||||||
figure_directed_shadow_pipeline,
|
figure_directed_shadow_pipeline,
|
||||||
&mut self.shadow_map,
|
&mut self.shadow.map,
|
||||||
) {
|
) {
|
||||||
shadow_map.point_pipeline = point_pipeline;
|
shadow_map.point_pipeline = point_pipeline;
|
||||||
shadow_map.terrain_directed_pipeline = terrain_directed_pipeline;
|
shadow_map.terrain_directed_pipeline = terrain_directed_pipeline;
|
||||||
@ -1275,9 +1039,34 @@ impl Renderer {
|
|||||||
|
|
||||||
/// Creates a download buffer, downloads the win_color_view, and converts to
|
/// Creates a download buffer, downloads the win_color_view, and converts to
|
||||||
/// a image::DynamicImage.
|
/// a image::DynamicImage.
|
||||||
#[allow(clippy::map_clone)] // TODO: Pending review in #587
|
//pub fn create_screenshot(&mut self) -> Result<image::DynamicImage,
|
||||||
pub fn create_screenshot(&mut self) -> Result<image::DynamicImage, RenderError> {
|
// RenderError> {
|
||||||
todo!()
|
pub fn create_screenshot(&mut self) {
|
||||||
|
// TODO: check if enabled
|
||||||
|
// TODO: save alongside a screenshot
|
||||||
|
// Take profiler snapshot
|
||||||
|
let profiling_data = if let Some(data) = self.profiler.process_finished_frame() {
|
||||||
|
data
|
||||||
|
} else {
|
||||||
|
error!("Failed to retrieve profiling data");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let file_name = format!(
|
||||||
|
"frame-trace_{}.json",
|
||||||
|
std::time::SystemTime::now()
|
||||||
|
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||||
|
.map(|d| d.as_millis())
|
||||||
|
.unwrap_or(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
wgpu_profiler::chrometrace::write_chrometrace(
|
||||||
|
std::path::Path::new(&file_name),
|
||||||
|
&profiling_data,
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("{}", file_name);
|
||||||
|
//todo!()
|
||||||
// let (width, height) = self.get_resolution().into_tuple();
|
// let (width, height) = self.get_resolution().into_tuple();
|
||||||
|
|
||||||
// let download_buf = self
|
// let download_buf = self
|
||||||
@ -2042,7 +1831,6 @@ impl Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates all the pipelines used to render.
|
/// Creates all the pipelines used to render.
|
||||||
#[allow(clippy::type_complexity)] // TODO: Pending review in #587
|
|
||||||
fn create_pipelines(
|
fn create_pipelines(
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
layouts: &Layouts,
|
layouts: &Layouts,
|
||||||
@ -2052,16 +1840,7 @@ fn create_pipelines(
|
|||||||
has_shadow_views: bool,
|
has_shadow_views: bool,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
skybox::SkyboxPipeline,
|
Pipelines,
|
||||||
figure::FigurePipeline,
|
|
||||||
terrain::TerrainPipeline,
|
|
||||||
fluid::FluidPipeline,
|
|
||||||
sprite::SpritePipeline,
|
|
||||||
particle::ParticlePipeline,
|
|
||||||
ui::UiPipeline,
|
|
||||||
lod_terrain::LodTerrainPipeline,
|
|
||||||
clouds::CloudsPipeline,
|
|
||||||
postprocess::PostProcessPipeline,
|
|
||||||
//figure::FigurePipeline,
|
//figure::FigurePipeline,
|
||||||
Option<shadow::PointShadowPipeline>,
|
Option<shadow::PointShadowPipeline>,
|
||||||
Option<shadow::ShadowPipeline>,
|
Option<shadow::ShadowPipeline>,
|
||||||
@ -2351,16 +2130,18 @@ fn create_pipelines(
|
|||||||
);
|
);
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
skybox_pipeline,
|
Pipelines {
|
||||||
figure_pipeline,
|
skybox: skybox_pipeline,
|
||||||
terrain_pipeline,
|
figure: figure_pipeline,
|
||||||
fluid_pipeline,
|
terrain: terrain_pipeline,
|
||||||
sprite_pipeline,
|
fluid: fluid_pipeline,
|
||||||
particle_pipeline,
|
sprite: sprite_pipeline,
|
||||||
ui_pipeline,
|
particle: particle_pipeline,
|
||||||
lod_terrain_pipeline,
|
ui: ui_pipeline,
|
||||||
clouds_pipeline,
|
lod_terrain: lod_terrain_pipeline,
|
||||||
postprocess_pipeline,
|
clouds: clouds_pipeline,
|
||||||
|
postprocess: postprocess_pipeline,
|
||||||
|
},
|
||||||
// player_shadow_pipeline,
|
// player_shadow_pipeline,
|
||||||
Some(point_shadow_pipeline),
|
Some(point_shadow_pipeline),
|
||||||
Some(terrain_directed_shadow_pipeline),
|
Some(terrain_directed_shadow_pipeline),
|
||||||
|
@ -8,45 +8,70 @@ use super::{
|
|||||||
clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite,
|
clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite,
|
||||||
terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow,
|
terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow,
|
||||||
},
|
},
|
||||||
|
scope::{ManualOwningScope, OwningScope, Scope},
|
||||||
},
|
},
|
||||||
spans::{self, OwningSpan, Span},
|
|
||||||
Renderer, ShadowMap, ShadowMapRenderer,
|
Renderer, ShadowMap, ShadowMapRenderer,
|
||||||
};
|
};
|
||||||
use core::{num::NonZeroU32, ops::Range};
|
use core::{num::NonZeroU32, ops::Range};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vek::Aabr;
|
use vek::Aabr;
|
||||||
|
|
||||||
|
// Borrow the fields we need from the renderer so that the GpuProfiler can be
|
||||||
|
// dijointly borrowed mutably
|
||||||
|
struct RendererBorrow<'frame> {
|
||||||
|
queue: &'frame wgpu::Queue,
|
||||||
|
device: &'frame wgpu::Device,
|
||||||
|
shadow: &'frame super::Shadow,
|
||||||
|
pipelines: &'frame super::Pipelines,
|
||||||
|
locals: &'frame super::locals::Locals,
|
||||||
|
views: &'frame super::Views,
|
||||||
|
mode: &'frame super::super::RenderMode,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Drawer<'frame> {
|
pub struct Drawer<'frame> {
|
||||||
encoder: Option<wgpu::CommandEncoder>,
|
encoder: Option<ManualOwningScope<'frame, wgpu::CommandEncoder>>,
|
||||||
pub renderer: &'frame mut Renderer,
|
borrow: RendererBorrow<'frame>,
|
||||||
tex: wgpu::SwapChainTexture,
|
swap_tex: wgpu::SwapChainTexture,
|
||||||
globals: &'frame GlobalsBindGroup,
|
globals: &'frame GlobalsBindGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'frame> Drawer<'frame> {
|
impl<'frame> Drawer<'frame> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mut encoder: wgpu::CommandEncoder,
|
encoder: wgpu::CommandEncoder,
|
||||||
renderer: &'frame mut Renderer,
|
renderer: &'frame mut Renderer,
|
||||||
tex: wgpu::SwapChainTexture,
|
swap_tex: wgpu::SwapChainTexture,
|
||||||
globals: &'frame GlobalsBindGroup,
|
globals: &'frame GlobalsBindGroup,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
renderer.tracer.start_span(&mut encoder, &spans::Id::Frame);
|
let borrow = RendererBorrow {
|
||||||
|
queue: &renderer.queue,
|
||||||
|
device: &renderer.device,
|
||||||
|
shadow: &renderer.shadow,
|
||||||
|
pipelines: &renderer.pipelines,
|
||||||
|
locals: &renderer.locals,
|
||||||
|
views: &renderer.views,
|
||||||
|
mode: &renderer.mode,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut encoder =
|
||||||
|
ManualOwningScope::start(&mut renderer.profiler, encoder, borrow.device, "frame");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
encoder: Some(encoder),
|
encoder: Some(encoder),
|
||||||
renderer,
|
borrow,
|
||||||
tex,
|
swap_tex,
|
||||||
globals,
|
globals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the render mode.
|
||||||
|
pub fn render_mode(&self) -> &super::super::RenderMode { self.borrow.mode }
|
||||||
|
|
||||||
pub fn shadow_pass(&mut self) -> Option<ShadowPassDrawer> {
|
pub fn shadow_pass(&mut self) -> Option<ShadowPassDrawer> {
|
||||||
if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map {
|
if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map {
|
||||||
|
let encoder = self.encoder.as_mut().unwrap();
|
||||||
|
let device = self.borrow.device;
|
||||||
let mut render_pass =
|
let mut render_pass =
|
||||||
self.encoder
|
encoder.scoped_render_pass(device, "shadow_pass", &wgpu::RenderPassDescriptor {
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
||||||
label: Some("shadow pass"),
|
label: Some("shadow pass"),
|
||||||
color_attachments: &[],
|
color_attachments: &[],
|
||||||
depth_stencil_attachment: Some(
|
depth_stencil_attachment: Some(
|
||||||
@ -61,16 +86,11 @@ impl<'frame> Drawer<'frame> {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut render_pass = OwningSpan::start(
|
|
||||||
&self.renderer.tracer,
|
|
||||||
render_pass,
|
|
||||||
spans::Id::DirectedShadows,
|
|
||||||
);
|
|
||||||
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
|
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
|
||||||
|
|
||||||
Some(ShadowPassDrawer {
|
Some(ShadowPassDrawer {
|
||||||
render_pass,
|
render_pass,
|
||||||
renderer: &self.renderer,
|
borrow: &self.borrow,
|
||||||
shadow_renderer,
|
shadow_renderer,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -79,54 +99,46 @@ impl<'frame> Drawer<'frame> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn first_pass(&mut self) -> FirstPassDrawer {
|
pub fn first_pass(&mut self) -> FirstPassDrawer {
|
||||||
let render_pass =
|
let encoder = self.encoder.as_mut().unwrap();
|
||||||
self.encoder
|
let device = self.borrow.device;
|
||||||
.as_mut()
|
let mut render_pass =
|
||||||
.unwrap()
|
encoder.scoped_render_pass(device, "first_pass", &wgpu::RenderPassDescriptor {
|
||||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
||||||
label: Some("first pass"),
|
label: Some("first pass"),
|
||||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
attachment: &self.renderer.tgt_color_view,
|
attachment: &self.borrow.views.tgt_color,
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
||||||
store: true,
|
store: true,
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
depth_stencil_attachment: Some(
|
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||||
wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
attachment: &self.borrow.views.tgt_depth,
|
||||||
attachment: &self.renderer.tgt_depth_view,
|
|
||||||
depth_ops: Some(wgpu::Operations {
|
depth_ops: Some(wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(0.0),
|
load: wgpu::LoadOp::Clear(0.0),
|
||||||
store: true,
|
store: true,
|
||||||
}),
|
}),
|
||||||
stencil_ops: None,
|
stencil_ops: None,
|
||||||
},
|
}),
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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(0, &self.globals.bind_group, &[]);
|
||||||
render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]);
|
render_pass.set_bind_group(1, &self.borrow.shadow.bind.bind_group, &[]);
|
||||||
|
|
||||||
FirstPassDrawer {
|
FirstPassDrawer {
|
||||||
render_pass,
|
render_pass,
|
||||||
renderer: &self.renderer,
|
borrow: &self.borrow,
|
||||||
figures_called: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn second_pass(&mut self) -> SecondPassDrawer {
|
pub fn second_pass(&mut self) -> SecondPassDrawer {
|
||||||
let render_pass =
|
let encoder = self.encoder.as_mut().unwrap();
|
||||||
self.encoder
|
let device = self.borrow.device;
|
||||||
.as_mut()
|
let mut render_pass =
|
||||||
.unwrap()
|
encoder.scoped_render_pass(device, "second_pass", &wgpu::RenderPassDescriptor {
|
||||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
||||||
label: Some("second pass (clouds)"),
|
label: Some("second pass (clouds)"),
|
||||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
attachment: &self.renderer.tgt_color_pp_view,
|
attachment: &self.borrow.views.tgt_color_pp,
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
||||||
@ -136,27 +148,23 @@ impl<'frame> Drawer<'frame> {
|
|||||||
depth_stencil_attachment: None,
|
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(0, &self.globals.bind_group, &[]);
|
||||||
render_pass.set_bind_group(1, &self.renderer.shadow_bind.bind_group, &[]);
|
render_pass.set_bind_group(1, &self.borrow.shadow.bind.bind_group, &[]);
|
||||||
|
|
||||||
SecondPassDrawer {
|
SecondPassDrawer {
|
||||||
render_pass,
|
render_pass,
|
||||||
renderer: &self.renderer,
|
borrow: &self.borrow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn third_pass(&mut self) -> ThirdPassDrawer {
|
pub fn third_pass(&mut self) -> ThirdPassDrawer {
|
||||||
let render_pass =
|
let encoder = self.encoder.as_mut().unwrap();
|
||||||
self.encoder
|
let device = self.borrow.device;
|
||||||
.as_mut()
|
let mut render_pass =
|
||||||
.unwrap()
|
encoder.scoped_render_pass(device, "third_pass", &wgpu::RenderPassDescriptor {
|
||||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
||||||
label: Some("third pass (postprocess + ui)"),
|
label: Some("third pass (postprocess + ui)"),
|
||||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
attachment: &self.tex.view,
|
attachment: &self.swap_tex.view,
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: wgpu::Operations {
|
ops: wgpu::Operations {
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
|
||||||
@ -166,14 +174,11 @@ impl<'frame> Drawer<'frame> {
|
|||||||
depth_stencil_attachment: None,
|
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, &[]);
|
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
|
||||||
|
|
||||||
ThirdPassDrawer {
|
ThirdPassDrawer {
|
||||||
render_pass,
|
render_pass,
|
||||||
renderer: &self.renderer,
|
borrow: &self.borrow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,10 +188,13 @@ impl<'frame> Drawer<'frame> {
|
|||||||
chunks: impl Clone
|
chunks: impl Clone
|
||||||
+ Iterator<Item = (&'data Model<terrain::Vertex>, &'data terrain::BoundLocals)>,
|
+ Iterator<Item = (&'data Model<terrain::Vertex>, &'data terrain::BoundLocals)>,
|
||||||
) {
|
) {
|
||||||
if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map {
|
if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map {
|
||||||
self.renderer
|
let device = self.borrow.device;
|
||||||
.tracer
|
let mut encoder = self
|
||||||
.start_span(self.encoder.as_mut().unwrap(), &spans::Id::PointShadows);
|
.encoder
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.scope(device, "point shadows");
|
||||||
const STRIDE: usize = std::mem::size_of::<shadow::PointLightMatrix>();
|
const STRIDE: usize = std::mem::size_of::<shadow::PointLightMatrix>();
|
||||||
let data = bytemuck::cast_slice(matrices);
|
let data = bytemuck::cast_slice(matrices);
|
||||||
|
|
||||||
@ -209,10 +217,7 @@ impl<'frame> Drawer<'frame> {
|
|||||||
|
|
||||||
let label = format!("point shadow face-{} pass", face);
|
let label = format!("point shadow face-{} pass", face);
|
||||||
let mut render_pass =
|
let mut render_pass =
|
||||||
self.encoder
|
encoder.scoped_render_pass(device, &label, &wgpu::RenderPassDescriptor {
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
||||||
label: Some(&label),
|
label: Some(&label),
|
||||||
color_attachments: &[],
|
color_attachments: &[],
|
||||||
depth_stencil_attachment: Some(
|
depth_stencil_attachment: Some(
|
||||||
@ -244,9 +249,6 @@ impl<'frame> Drawer<'frame> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.renderer
|
|
||||||
.tracer
|
|
||||||
.end_span(self.encoder.as_mut().unwrap(), &spans::Id::PointShadows);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,11 +260,13 @@ impl<'frame> Drawer<'frame> {
|
|||||||
/// requires an array of matrices that could be a pain to construct
|
/// requires an array of matrices that could be a pain to construct
|
||||||
/// simply for clearing
|
/// simply for clearing
|
||||||
pub fn clear_shadows(&mut self) {
|
pub fn clear_shadows(&mut self) {
|
||||||
if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map {
|
if let ShadowMap::Enabled(ref shadow_renderer) = self.borrow.shadow.map {
|
||||||
self.encoder
|
let device = self.borrow.device;
|
||||||
.as_mut()
|
let encoder = self.encoder.as_mut().unwrap();
|
||||||
.unwrap()
|
encoder.scoped_render_pass(
|
||||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
device,
|
||||||
|
"clear_directed_shadow",
|
||||||
|
&wgpu::RenderPassDescriptor {
|
||||||
label: Some("clear directed shadow pass"),
|
label: Some("clear directed shadow pass"),
|
||||||
color_attachments: &[],
|
color_attachments: &[],
|
||||||
depth_stencil_attachment: Some(
|
depth_stencil_attachment: Some(
|
||||||
@ -275,7 +279,8 @@ impl<'frame> Drawer<'frame> {
|
|||||||
stencil_ops: None,
|
stencil_ops: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
for face in 0..6 {
|
for face in 0..6 {
|
||||||
// TODO: view creation cost?
|
// TODO: view creation cost?
|
||||||
@ -295,10 +300,7 @@ impl<'frame> Drawer<'frame> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let label = format!("clear point shadow face-{} pass", face);
|
let label = format!("clear point shadow face-{} pass", face);
|
||||||
self.encoder
|
encoder.scoped_render_pass(device, &label, &wgpu::RenderPassDescriptor {
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
||||||
label: Some(&label),
|
label: Some(&label),
|
||||||
color_attachments: &[],
|
color_attachments: &[],
|
||||||
depth_stencil_attachment: Some(
|
depth_stencil_attachment: Some(
|
||||||
@ -321,47 +323,38 @@ impl<'frame> Drop for Drawer<'frame> {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// TODO: submitting things to the queue can let the gpu start on them sooner
|
// 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?
|
// maybe we should submit each render pass to the queue as they are produced?
|
||||||
self.renderer
|
let (mut encoder, profiler) = self.encoder.take().unwrap().end_scope();
|
||||||
.tracer
|
profiler.resolve_queries(&mut encoder);
|
||||||
.end_span(self.encoder.as_mut().unwrap(), &spans::Id::Frame);
|
self.borrow.queue.submit(std::iter::once(encoder.finish()));
|
||||||
self.renderer
|
profiler
|
||||||
.tracer
|
.end_frame()
|
||||||
.resolve_timestamps(self.encoder.as_mut().unwrap());
|
.expect("Gpu profiler error! Maybe there was an unclosed scope?");
|
||||||
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
|
// Shadow pass
|
||||||
pub struct ShadowPassDrawer<'pass> {
|
pub struct ShadowPassDrawer<'pass> {
|
||||||
render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>,
|
render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
|
||||||
pub renderer: &'pass Renderer,
|
borrow: &'pass RendererBorrow<'pass>,
|
||||||
shadow_renderer: &'pass ShadowMapRenderer,
|
shadow_renderer: &'pass ShadowMapRenderer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass> ShadowPassDrawer<'pass> {
|
impl<'pass> ShadowPassDrawer<'pass> {
|
||||||
pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> {
|
pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self
|
||||||
&self.renderer.tracer,
|
.render_pass
|
||||||
&mut *self.render_pass,
|
.scope(self.borrow.device, "direcred_figure_shadows");
|
||||||
spans::Id::DirectedFigureShadows,
|
|
||||||
);
|
|
||||||
render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
|
render_pass.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
|
||||||
|
|
||||||
FigureShadowDrawer { render_pass }
|
FigureShadowDrawer { render_pass }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> {
|
pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self
|
||||||
&self.renderer.tracer,
|
.render_pass
|
||||||
&mut *self.render_pass,
|
.scope(self.borrow.device, "direcred_terrain_shadows");
|
||||||
spans::Id::DirectedTerrainShadows,
|
|
||||||
);
|
|
||||||
render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
|
render_pass.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
|
||||||
|
|
||||||
TerrainShadowDrawer { render_pass }
|
TerrainShadowDrawer { render_pass }
|
||||||
@ -369,7 +362,7 @@ impl<'pass> ShadowPassDrawer<'pass> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
|
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
|
impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
|
||||||
@ -385,7 +378,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
|
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
|
impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
|
||||||
@ -402,73 +395,50 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
|
|||||||
|
|
||||||
// First pass
|
// First pass
|
||||||
pub struct FirstPassDrawer<'pass> {
|
pub struct FirstPassDrawer<'pass> {
|
||||||
pub(super) render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>,
|
pub(super) render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
|
||||||
pub renderer: &'pass Renderer,
|
borrow: &'pass RendererBorrow<'pass>,
|
||||||
// TODO: hack
|
|
||||||
figures_called: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass> FirstPassDrawer<'pass> {
|
impl<'pass> FirstPassDrawer<'pass> {
|
||||||
pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model<skybox::Vertex>) {
|
pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model<skybox::Vertex>) {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "skybox");
|
||||||
&self.renderer.tracer,
|
|
||||||
&mut *self.render_pass,
|
render_pass.set_pipeline(&self.borrow.pipelines.skybox.pipeline);
|
||||||
spans::Id::Skybox,
|
|
||||||
);
|
|
||||||
render_pass.set_pipeline(&self.renderer.skybox_pipeline.pipeline);
|
|
||||||
render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||||
render_pass.draw(0..model.len() as u32, 0..1);
|
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>) {
|
pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model<lod_terrain::Vertex>) {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "lod_terrain");
|
||||||
&self.renderer.tracer,
|
|
||||||
&mut *self.render_pass,
|
render_pass.set_pipeline(&self.borrow.pipelines.lod_terrain.pipeline);
|
||||||
spans::Id::Lod,
|
|
||||||
);
|
|
||||||
render_pass.set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline);
|
|
||||||
render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||||
render_pass.draw(0..model.len() as u32, 0..1);
|
render_pass.draw(0..model.len() as u32, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> {
|
pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "figures");
|
||||||
&self.renderer.tracer,
|
|
||||||
&mut *self.render_pass,
|
render_pass.set_pipeline(&self.borrow.pipelines.figure.pipeline);
|
||||||
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 }
|
FigureDrawer { render_pass }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> {
|
pub fn draw_terrain<'data: 'pass>(&mut self) -> TerrainDrawer<'_, 'pass> {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "terrain");
|
||||||
&self.renderer.tracer,
|
|
||||||
&mut *self.render_pass,
|
render_pass.set_pipeline(&self.borrow.pipelines.terrain.pipeline);
|
||||||
spans::Id::Terrain,
|
|
||||||
);
|
|
||||||
render_pass.set_pipeline(&self.renderer.terrain_pipeline.pipeline);
|
|
||||||
|
|
||||||
TerrainDrawer {
|
TerrainDrawer {
|
||||||
render_pass,
|
render_pass,
|
||||||
|
|
||||||
col_lights: None,
|
col_lights: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> {
|
pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "particles");
|
||||||
&self.renderer.tracer,
|
|
||||||
&mut *self.render_pass,
|
render_pass.set_pipeline(&self.borrow.pipelines.particle.pipeline);
|
||||||
spans::Id::Particles,
|
|
||||||
);
|
|
||||||
render_pass.set_pipeline(&self.renderer.particle_pipeline.pipeline);
|
|
||||||
|
|
||||||
ParticleDrawer { render_pass }
|
ParticleDrawer { render_pass }
|
||||||
}
|
}
|
||||||
@ -477,15 +447,10 @@ impl<'pass> FirstPassDrawer<'pass> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
col_lights: &'data ColLights<sprite::Locals>,
|
col_lights: &'data ColLights<sprite::Locals>,
|
||||||
) -> SpriteDrawer<'_, 'pass> {
|
) -> SpriteDrawer<'_, 'pass> {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "sprites");
|
||||||
&self.renderer.tracer,
|
|
||||||
&mut *self.render_pass,
|
render_pass.set_pipeline(&self.borrow.pipelines.sprite.pipeline);
|
||||||
spans::Id::Sprites,
|
render_pass.set_bind_group(4, &col_lights.bind_group, &[]);
|
||||||
);
|
|
||||||
self.render_pass
|
|
||||||
.set_pipeline(&self.renderer.sprite_pipeline.pipeline);
|
|
||||||
self.render_pass
|
|
||||||
.set_bind_group(4, &col_lights.bind_group, &[]);
|
|
||||||
|
|
||||||
SpriteDrawer { render_pass }
|
SpriteDrawer { render_pass }
|
||||||
}
|
}
|
||||||
@ -494,12 +459,9 @@ impl<'pass> FirstPassDrawer<'pass> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
waves: &'data fluid::BindGroup,
|
waves: &'data fluid::BindGroup,
|
||||||
) -> FluidDrawer<'_, 'pass> {
|
) -> FluidDrawer<'_, 'pass> {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "fluid");
|
||||||
&self.renderer.tracer,
|
|
||||||
&mut *self.render_pass,
|
render_pass.set_pipeline(&self.borrow.pipelines.fluid.pipeline);
|
||||||
spans::Id::Fluid,
|
|
||||||
);
|
|
||||||
render_pass.set_pipeline(&self.renderer.fluid_pipeline.pipeline);
|
|
||||||
render_pass.set_bind_group(2, &waves.bind_group, &[]);
|
render_pass.set_bind_group(2, &waves.bind_group, &[]);
|
||||||
|
|
||||||
FluidDrawer { render_pass }
|
FluidDrawer { render_pass }
|
||||||
@ -507,7 +469,7 @@ impl<'pass> FirstPassDrawer<'pass> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
|
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
|
impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
|
||||||
@ -527,7 +489,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
|
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||||
col_lights: Option<&'pass_ref Arc<ColLights<terrain::Locals>>>,
|
col_lights: Option<&'pass_ref Arc<ColLights<terrain::Locals>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +521,7 @@ impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
|
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
|
impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
|
||||||
@ -580,7 +542,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
|
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> {
|
impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> {
|
||||||
@ -617,7 +579,7 @@ impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
|
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
|
impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
|
||||||
@ -634,49 +596,44 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
|
|||||||
|
|
||||||
// Second pass: clouds
|
// Second pass: clouds
|
||||||
pub struct SecondPassDrawer<'pass> {
|
pub struct SecondPassDrawer<'pass> {
|
||||||
render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>,
|
render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
|
||||||
renderer: &'pass Renderer,
|
borrow: &'pass RendererBorrow<'pass>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass> SecondPassDrawer<'pass> {
|
impl<'pass> SecondPassDrawer<'pass> {
|
||||||
pub fn draw_clouds(&mut self) {
|
pub fn draw_clouds(&mut self) {
|
||||||
self.render_pass
|
self.render_pass
|
||||||
.set_pipeline(&self.renderer.clouds_pipeline.pipeline);
|
.set_pipeline(&self.borrow.pipelines.clouds.pipeline);
|
||||||
self.render_pass
|
self.render_pass
|
||||||
.set_bind_group(2, &self.renderer.locals.clouds_bind.bind_group, &[]);
|
.set_bind_group(2, &self.borrow.locals.clouds_bind.bind_group, &[]);
|
||||||
self.render_pass.draw(0..3, 0..1);
|
self.render_pass.draw(0..3, 0..1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Third pass: postprocess + ui
|
// Third pass: postprocess + ui
|
||||||
pub struct ThirdPassDrawer<'pass> {
|
pub struct ThirdPassDrawer<'pass> {
|
||||||
render_pass: OwningSpan<'pass, wgpu::RenderPass<'pass>>,
|
render_pass: OwningScope<'pass, wgpu::RenderPass<'pass>>,
|
||||||
renderer: &'pass Renderer,
|
borrow: &'pass RendererBorrow<'pass>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'pass> ThirdPassDrawer<'pass> {
|
impl<'pass> ThirdPassDrawer<'pass> {
|
||||||
pub fn draw_post_process(&mut self) {
|
pub fn draw_post_process(&mut self) {
|
||||||
let mut render_pass = Span::start(
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "postprocess");
|
||||||
&self.renderer.tracer,
|
render_pass.set_pipeline(&self.borrow.pipelines.postprocess.pipeline);
|
||||||
&mut *self.render_pass,
|
render_pass.set_bind_group(1, &self.borrow.locals.postprocess_bind.bind_group, &[]);
|
||||||
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);
|
render_pass.draw(0..3, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> {
|
pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> {
|
||||||
let mut render_pass =
|
let mut render_pass = self.render_pass.scope(self.borrow.device, "ui");
|
||||||
Span::start(&self.renderer.tracer, &mut *self.render_pass, spans::Id::Ui);
|
render_pass.set_pipeline(&self.borrow.pipelines.ui.pipeline);
|
||||||
render_pass.set_pipeline(&self.renderer.ui_pipeline.pipeline);
|
|
||||||
|
|
||||||
UiDrawer { render_pass }
|
UiDrawer { render_pass }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct UiDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: Span<'pass_ref, wgpu::RenderPass<'pass>>,
|
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> {
|
pub struct PreparedUiDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
|
75
voxygen/src/render/renderer/locals.rs
Normal file
75
voxygen/src/render/renderer/locals.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use super::{
|
||||||
|
super::{
|
||||||
|
consts::Consts,
|
||||||
|
pipelines::{clouds, postprocess},
|
||||||
|
},
|
||||||
|
Layouts,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Locals {
|
||||||
|
pub clouds: Consts<clouds::Locals>,
|
||||||
|
pub clouds_bind: clouds::BindGroup,
|
||||||
|
|
||||||
|
pub postprocess: Consts<postprocess::Locals>,
|
||||||
|
pub postprocess_bind: postprocess::BindGroup,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Locals {
|
||||||
|
pub(super) fn new(
|
||||||
|
device: &wgpu::Device,
|
||||||
|
layouts: &Layouts,
|
||||||
|
clouds_locals: Consts<clouds::Locals>,
|
||||||
|
postprocess_locals: Consts<postprocess::Locals>,
|
||||||
|
tgt_color_view: &wgpu::TextureView,
|
||||||
|
tgt_depth_view: &wgpu::TextureView,
|
||||||
|
tgt_color_pp_view: &wgpu::TextureView,
|
||||||
|
sampler: &wgpu::Sampler,
|
||||||
|
depth_sampler: &wgpu::Sampler,
|
||||||
|
) -> Self {
|
||||||
|
let clouds_bind = layouts.clouds.bind(
|
||||||
|
device,
|
||||||
|
tgt_color_view,
|
||||||
|
tgt_depth_view,
|
||||||
|
sampler,
|
||||||
|
depth_sampler,
|
||||||
|
&clouds_locals,
|
||||||
|
);
|
||||||
|
let postprocess_bind =
|
||||||
|
layouts
|
||||||
|
.postprocess
|
||||||
|
.bind(device, tgt_color_pp_view, sampler, &postprocess_locals);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
clouds: clouds_locals,
|
||||||
|
clouds_bind,
|
||||||
|
postprocess: postprocess_locals,
|
||||||
|
postprocess_bind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn rebind(
|
||||||
|
&mut self,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
layouts: &Layouts,
|
||||||
|
// Call when these are recreated and need to be rebound
|
||||||
|
// e.g. resizing
|
||||||
|
tgt_color_view: &wgpu::TextureView,
|
||||||
|
tgt_depth_view: &wgpu::TextureView,
|
||||||
|
tgt_color_pp_view: &wgpu::TextureView,
|
||||||
|
sampler: &wgpu::Sampler,
|
||||||
|
depth_sampler: &wgpu::Sampler,
|
||||||
|
) {
|
||||||
|
self.clouds_bind = layouts.clouds.bind(
|
||||||
|
device,
|
||||||
|
tgt_color_view,
|
||||||
|
tgt_depth_view,
|
||||||
|
sampler,
|
||||||
|
depth_sampler,
|
||||||
|
&self.clouds,
|
||||||
|
);
|
||||||
|
self.postprocess_bind =
|
||||||
|
layouts
|
||||||
|
.postprocess
|
||||||
|
.bind(device, tgt_color_pp_view, sampler, &self.postprocess);
|
||||||
|
}
|
||||||
|
}
|
91
voxygen/src/render/renderer/shaders.rs
Normal file
91
voxygen/src/render/renderer/shaders.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use common::assets::{self, AssetExt, AssetHandle};
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
|
/// Load from a GLSL file.
|
||||||
|
pub struct Glsl(pub String);
|
||||||
|
|
||||||
|
impl From<String> for Glsl {
|
||||||
|
fn from(s: String) -> Glsl { Glsl(s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl assets::Asset for Glsl {
|
||||||
|
type Loader = assets::LoadFrom<String, assets::StringLoader>;
|
||||||
|
|
||||||
|
const EXTENSION: &'static str = "glsl";
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Shaders {
|
||||||
|
shaders: HashMap<String, AssetHandle<Glsl>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl assets::Compound for Shaders {
|
||||||
|
// TODO: Taking the specifier argument as a base for shaders specifiers
|
||||||
|
// would allow to use several shaders groups easily
|
||||||
|
fn load<S: assets::source::Source>(
|
||||||
|
_: &assets::AssetCache<S>,
|
||||||
|
_: &str,
|
||||||
|
) -> Result<Shaders, assets::Error> {
|
||||||
|
let shaders = [
|
||||||
|
"include.constants",
|
||||||
|
"include.globals",
|
||||||
|
"include.sky",
|
||||||
|
"include.light",
|
||||||
|
"include.srgb",
|
||||||
|
"include.random",
|
||||||
|
"include.lod",
|
||||||
|
"include.shadows",
|
||||||
|
"antialias.none",
|
||||||
|
"antialias.fxaa",
|
||||||
|
"antialias.msaa-x4",
|
||||||
|
"antialias.msaa-x8",
|
||||||
|
"antialias.msaa-x16",
|
||||||
|
"include.cloud.none",
|
||||||
|
"include.cloud.regular",
|
||||||
|
"figure-vert",
|
||||||
|
"light-shadows-figure-vert",
|
||||||
|
"light-shadows-directed-vert",
|
||||||
|
"light-shadows-directed-frag",
|
||||||
|
"point-light-shadows-vert",
|
||||||
|
"skybox-vert",
|
||||||
|
"skybox-frag",
|
||||||
|
"figure-frag",
|
||||||
|
"terrain-vert",
|
||||||
|
"terrain-frag",
|
||||||
|
"fluid-vert",
|
||||||
|
"fluid-frag.cheap",
|
||||||
|
"fluid-frag.shiny",
|
||||||
|
"sprite-vert",
|
||||||
|
"sprite-frag",
|
||||||
|
"particle-vert",
|
||||||
|
"particle-frag",
|
||||||
|
"ui-vert",
|
||||||
|
"ui-frag",
|
||||||
|
"lod-terrain-vert",
|
||||||
|
"lod-terrain-frag",
|
||||||
|
"clouds-vert",
|
||||||
|
"clouds-frag",
|
||||||
|
"postprocess-vert",
|
||||||
|
"postprocess-frag",
|
||||||
|
"player-shadow-frag",
|
||||||
|
"light-shadows-geom",
|
||||||
|
"light-shadows-frag",
|
||||||
|
];
|
||||||
|
|
||||||
|
let shaders = shaders
|
||||||
|
.iter()
|
||||||
|
.map(|shader| {
|
||||||
|
let full_specifier = ["voxygen.shaders.", shader].concat();
|
||||||
|
let asset = AssetExt::load(&full_specifier)?;
|
||||||
|
Ok((String::from(*shader), asset))
|
||||||
|
})
|
||||||
|
.collect::<Result<HashMap<_, _>, assets::Error>>()?;
|
||||||
|
|
||||||
|
Ok(Self { shaders })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shaders {
|
||||||
|
pub fn get(&self, shader: &str) -> Option<impl core::ops::Deref<Target = Glsl>> {
|
||||||
|
self.shaders.get(shader).map(|a| a.read())
|
||||||
|
}
|
||||||
|
}
|
38
voxygen/src/render/renderer/shadow_map.rs
Normal file
38
voxygen/src/render/renderer/shadow_map.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use super::super::{pipelines::shadow, texture::Texture};
|
||||||
|
|
||||||
|
/// A type that holds shadow map data. Since shadow mapping may not be
|
||||||
|
/// supported on all platforms, we try to keep it separate.
|
||||||
|
pub struct ShadowMapRenderer {
|
||||||
|
// directed_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||||
|
// point_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||||
|
pub directed_depth: Texture,
|
||||||
|
|
||||||
|
pub point_depth: Texture,
|
||||||
|
|
||||||
|
pub point_pipeline: shadow::PointShadowPipeline,
|
||||||
|
pub terrain_directed_pipeline: shadow::ShadowPipeline,
|
||||||
|
pub figure_directed_pipeline: shadow::ShadowFigurePipeline,
|
||||||
|
pub layout: shadow::ShadowLayout,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ShadowMap {
|
||||||
|
Enabled(ShadowMapRenderer),
|
||||||
|
Disabled {
|
||||||
|
dummy_point: Texture, // Cube texture
|
||||||
|
dummy_directed: Texture,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShadowMap {
|
||||||
|
pub fn textures(&self) -> (&Texture, &Texture) {
|
||||||
|
match self {
|
||||||
|
Self::Enabled(renderer) => (&renderer.point_depth, &renderer.directed_depth),
|
||||||
|
Self::Disabled {
|
||||||
|
dummy_point,
|
||||||
|
dummy_directed,
|
||||||
|
} => (dummy_point, dummy_directed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_enabled(&self) -> bool { matches!(self, Self::Enabled(_)) }
|
||||||
|
}
|
165
voxygen/src/render/scope.rs
Normal file
165
voxygen/src/render/scope.rs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
use wgpu_profiler::{GpuProfiler, ProfilerCommandRecorder};
|
||||||
|
|
||||||
|
pub fn required_features() -> wgpu::Features { wgpu::Features::TIMESTAMP_QUERY }
|
||||||
|
|
||||||
|
pub struct Scope<'a, W: ProfilerCommandRecorder> {
|
||||||
|
profiler: &'a mut GpuProfiler,
|
||||||
|
wgpu_thing: &'a mut W,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OwningScope<'a, W: ProfilerCommandRecorder> {
|
||||||
|
profiler: &'a mut GpuProfiler,
|
||||||
|
wgpu_thing: W,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separate type since we can't destructure types that impl Drop :/
|
||||||
|
pub struct ManualOwningScope<'a, W: ProfilerCommandRecorder> {
|
||||||
|
profiler: &'a mut GpuProfiler,
|
||||||
|
wgpu_thing: W,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> Scope<'a, W> {
|
||||||
|
pub fn start(
|
||||||
|
profiler: &'a mut GpuProfiler,
|
||||||
|
wgpu_thing: &'a mut W,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
label: &str,
|
||||||
|
) -> Self {
|
||||||
|
profiler.begin_scope(label, wgpu_thing, device);
|
||||||
|
Self {
|
||||||
|
profiler,
|
||||||
|
wgpu_thing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Starts a scope nested within this one
|
||||||
|
pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> {
|
||||||
|
Scope::start(self.profiler, self.wgpu_thing, device, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> OwningScope<'a, W> {
|
||||||
|
pub fn start(
|
||||||
|
profiler: &'a mut GpuProfiler,
|
||||||
|
mut wgpu_thing: W,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
label: &str,
|
||||||
|
) -> Self {
|
||||||
|
profiler.begin_scope(label, &mut wgpu_thing, device);
|
||||||
|
Self {
|
||||||
|
profiler,
|
||||||
|
wgpu_thing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Starts a scope nested within this one
|
||||||
|
pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> {
|
||||||
|
Scope::start(self.profiler, &mut self.wgpu_thing, device, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> ManualOwningScope<'a, W> {
|
||||||
|
pub fn start(
|
||||||
|
profiler: &'a mut GpuProfiler,
|
||||||
|
mut wgpu_thing: W,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
label: &str,
|
||||||
|
) -> Self {
|
||||||
|
profiler.begin_scope(label, &mut wgpu_thing, device);
|
||||||
|
Self {
|
||||||
|
profiler,
|
||||||
|
wgpu_thing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Starts a scope nested within this one
|
||||||
|
pub fn scope(&mut self, device: &wgpu::Device, label: &str) -> Scope<'_, W> {
|
||||||
|
Scope::start(self.profiler, &mut self.wgpu_thing, device, label)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ends the scope allowing the extraction of owned the wgpu thing
|
||||||
|
/// and the mutable reference to the GpuProfiler
|
||||||
|
pub fn end_scope(mut self) -> (W, &'a mut GpuProfiler) {
|
||||||
|
self.profiler.end_scope(&mut self.wgpu_thing);
|
||||||
|
(self.wgpu_thing, self.profiler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Scope<'a, wgpu::CommandEncoder> {
|
||||||
|
/// Start a render pass wrapped in an OwnedScope
|
||||||
|
pub fn scoped_render_pass<'b>(
|
||||||
|
&'b mut self,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
label: &str,
|
||||||
|
pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>,
|
||||||
|
) -> OwningScope<'b, wgpu::RenderPass> {
|
||||||
|
let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor);
|
||||||
|
OwningScope::start(self.profiler, render_pass, device, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> OwningScope<'a, wgpu::CommandEncoder> {
|
||||||
|
/// Start a render pass wrapped in an OwnedScope
|
||||||
|
pub fn scoped_render_pass<'b>(
|
||||||
|
&'b mut self,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
label: &str,
|
||||||
|
pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>,
|
||||||
|
) -> OwningScope<'b, wgpu::RenderPass> {
|
||||||
|
let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor);
|
||||||
|
OwningScope::start(self.profiler, render_pass, device, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ManualOwningScope<'a, wgpu::CommandEncoder> {
|
||||||
|
/// Start a render pass wrapped in an OwnedScope
|
||||||
|
pub fn scoped_render_pass<'b>(
|
||||||
|
&'b mut self,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
label: &str,
|
||||||
|
pass_descriptor: &wgpu::RenderPassDescriptor<'b, '_>,
|
||||||
|
) -> OwningScope<'b, wgpu::RenderPass> {
|
||||||
|
let render_pass = self.wgpu_thing.begin_render_pass(pass_descriptor);
|
||||||
|
OwningScope::start(self.profiler, render_pass, device, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scope
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for Scope<'a, W> {
|
||||||
|
type Target = W;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target { self.wgpu_thing }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for Scope<'a, W> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target { self.wgpu_thing }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> Drop for Scope<'a, W> {
|
||||||
|
fn drop(&mut self) { self.profiler.end_scope(self.wgpu_thing); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// OwningScope
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for OwningScope<'a, W> {
|
||||||
|
type Target = W;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target { &self.wgpu_thing }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for OwningScope<'a, W> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.wgpu_thing }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> Drop for OwningScope<'a, W> {
|
||||||
|
fn drop(&mut self) { self.profiler.end_scope(&mut self.wgpu_thing); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ManualOwningScope
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> std::ops::Deref for ManualOwningScope<'a, W> {
|
||||||
|
type Target = W;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target { &self.wgpu_thing }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W: ProfilerCommandRecorder> std::ops::DerefMut for ManualOwningScope<'a, W> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.wgpu_thing }
|
||||||
|
}
|
@ -1048,9 +1048,7 @@ impl Scene {
|
|||||||
let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
|
let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
|
||||||
|
|
||||||
// would instead have this as an extension.
|
// would instead have this as an extension.
|
||||||
if drawer.renderer.render_mode().shadow.is_map()
|
if drawer.render_mode().shadow.is_map() && (is_daylight || !self.light_data.is_empty()) {
|
||||||
&& (is_daylight || !self.light_data.is_empty())
|
|
||||||
{
|
|
||||||
if is_daylight {
|
if is_daylight {
|
||||||
if let Some(mut shadow_pass) = drawer.shadow_pass() {
|
if let Some(mut shadow_pass) = drawer.shadow_pass() {
|
||||||
// Render terrain directed shadows.
|
// Render terrain directed shadows.
|
||||||
|
@ -516,7 +516,7 @@ impl SpriteRenderContext {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(
|
.map(
|
||||||
|SpriteDataResponse {
|
|SpriteDataResponse {
|
||||||
locals,
|
locals: locals_buffer,
|
||||||
model,
|
model,
|
||||||
offset,
|
offset,
|
||||||
}| {
|
}| {
|
||||||
|
@ -10,7 +10,6 @@ use gilrs::{EventType, Gilrs};
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use keyboard_keynames::key_layout::KeyLayout;
|
use keyboard_keynames::key_layout::KeyLayout;
|
||||||
use old_school_gfx_glutin_ext::{ContextBuilderExt, WindowInitExt, WindowUpdateExt};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::{error, warn};
|
use tracing::{error, warn};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -941,6 +940,9 @@ impl Window {
|
|||||||
let winit::dpi::PhysicalSize { width, height } = physical;
|
let winit::dpi::PhysicalSize { width, height } = physical;
|
||||||
self.events
|
self.events
|
||||||
.push(Event::Resize(Vec2::new(width as u32, height as u32)));
|
.push(Event::Resize(Vec2::new(width as u32, height as u32)));
|
||||||
|
// TODO: can get invalid scissor rect
|
||||||
|
// panic with this + resize several times
|
||||||
|
// std::thread::sleep_ms(500);
|
||||||
},
|
},
|
||||||
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
|
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
|
||||||
// TODO: is window resized event emitted? or do we need to handle that here?
|
// TODO: is window resized event emitted? or do we need to handle that here?
|
||||||
@ -1342,7 +1344,9 @@ impl Window {
|
|||||||
pub fn send_event(&mut self, event: Event) { self.events.push(event) }
|
pub fn send_event(&mut self, event: Event) { self.events.push(event) }
|
||||||
|
|
||||||
pub fn take_screenshot(&mut self, settings: &Settings) {
|
pub fn take_screenshot(&mut self, settings: &Settings) {
|
||||||
match self.renderer.create_screenshot() {
|
let _ = self.renderer.create_screenshot();
|
||||||
|
// TODO
|
||||||
|
/*match self.renderer.create_screenshot() {
|
||||||
Ok(img) => {
|
Ok(img) => {
|
||||||
let mut path = settings.screenshots_path.clone();
|
let mut path = settings.screenshots_path.clone();
|
||||||
let sender = self.message_sender.clone();
|
let sender = self.message_sender.clone();
|
||||||
@ -1377,7 +1381,7 @@ impl Window {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
},
|
},
|
||||||
Err(e) => error!(?e, "Couldn't create screenshot due to renderer error"),
|
Err(e) => error!(?e, "Couldn't create screenshot due to renderer error"),
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_pressed(
|
fn is_pressed(
|
||||||
|
Loading…
Reference in New Issue
Block a user