Skip to content
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/re_renderer/examples/2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl framework::Example for Render2D {
// Moving the windows to a high dpi screen makes the second one bigger.
// Also, it looks different under perspective projection.
// The third point is automatic thickness which is determined by the point renderer implementation.
let mut point_cloud_builder = PointCloudBuilder::<()>::default();
let mut point_cloud_builder = PointCloudBuilder::<()>::new(re_ctx, 32, 1);
point_cloud_builder
.batch("points")
.add_points_2d(
Expand Down
4 changes: 3 additions & 1 deletion crates/re_renderer/examples/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl<E: Example + 'static> Application<E> {
self.window.request_redraw();
}
Event::RedrawRequested(_) => {
self.re_ctx.frame_maintenance();
self.re_ctx.begin_frame();

// native debug build
#[cfg(all(not(target_arch = "wasm32"), debug_assertions))]
Expand Down Expand Up @@ -273,6 +273,8 @@ impl<E: Example + 'static> Application<E> {
// drop the pass so we can finish() the main encoder!
};

self.re_ctx.before_submit();

self.re_ctx.queue.submit(
view_cmd_buffers
.into_iter()
Expand Down
24 changes: 11 additions & 13 deletions crates/re_renderer/examples/multiview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use rand::Rng;
use re_renderer::{
renderer::{
GenericSkyboxDrawData, LineDrawData, LineStripFlags, MeshDrawData, MeshInstance,
PointCloudBatchInfo, PointCloudDrawData, PointCloudVertex, TestTriangleDrawData,
PointCloudVertex, TestTriangleDrawData,
},
resource_managers::ResourceLifeTime,
view_builder::{OrthographicCameraMode, Projection, TargetConfiguration, ViewBuilder},
Color32, LineStripSeriesBuilder, RenderContext, Rgba, Size,
Color32, LineStripSeriesBuilder, PointCloudBuilder, RenderContext, Rgba, Size,
};
use winit::event::{ElementState, VirtualKeyCode};

Expand Down Expand Up @@ -254,20 +254,18 @@ impl Example for Multiview {
let view_from_world =
IsoTransform::look_at_rh(self.camera_position, Vec3::ZERO, Vec3::Y).unwrap();

let mut point_cloud_builder =
PointCloudBuilder::<()>::new(re_ctx, self.random_points.len(), 1);
point_cloud_builder
.batch("Random points")
.world_from_obj(glam::Mat4::from_rotation_x(seconds_since_startup))
.add_vertices(self.random_points.iter().cloned())
.colors(self.random_points_colors.iter().cloned());

let triangle = TestTriangleDrawData::new(re_ctx);
let skybox = GenericSkyboxDrawData::new(re_ctx);
let lines = build_lines(re_ctx, seconds_since_startup);
let point_cloud = PointCloudDrawData::new(
re_ctx,
&self.random_points,
&self.random_points_colors,
&[PointCloudBatchInfo {
label: "Random points".into(),
world_from_obj: glam::Mat4::from_rotation_x(seconds_since_startup),
point_count: self.random_points.len() as _,
}],
)
.unwrap();
let point_cloud = point_cloud_builder.to_draw_data(re_ctx).unwrap();
let meshes = build_mesh_instances(
re_ctx,
&self.model_mesh_instances,
Expand Down
72 changes: 53 additions & 19 deletions crates/re_renderer/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::sync::Arc;

use parking_lot::Mutex;
use type_map::concurrent::{self, TypeMap};

use crate::{
config::RenderContextConfig,
global_bindings::GlobalBindings,
renderer::Renderer,
resource_managers::{MeshManager, TextureManager2D},
staging_write_belt::StagingWriteBelt,
wgpu_resources::WgpuResourcePools,
FileResolver, FileServer, FileSystem, RecommendedFileResolver,
};
Expand All @@ -24,12 +26,18 @@ pub struct RenderContext {
pub(crate) resolver: RecommendedFileResolver,
#[cfg(all(not(target_arch = "wasm32"), debug_assertions))] // native debug build
pub(crate) err_tracker: std::sync::Arc<crate::error_tracker::ErrorTracker>,
pub(crate) staging_belt: Mutex<StagingWriteBelt>,

/// Command encoder for all commands that should go in before view builder are submitted.
///
/// This should be used for any gpu copy operation outside of a renderer or view builder.
/// (i.e. typically in [`crate::renderer::DrawData`] creation!)
pub(crate) frame_global_commands: wgpu::CommandEncoder,

pub gpu_resources: WgpuResourcePools,
pub mesh_manager: MeshManager,
pub texture_manager_2d: TextureManager2D,

// TODO(andreas): Add frame/lifetime statistics, shared resources (e.g. "global" uniform buffer), ??
frame_index: u64,
}

Expand Down Expand Up @@ -137,35 +145,44 @@ impl RenderContext {
let texture_manager_2d =
TextureManager2D::new(device.clone(), queue.clone(), &mut gpu_resources.textures);

let before_view_builder_commands = Self::create_frame_global_command_encoder(&device);

RenderContext {
device,
queue,

shared_renderer_data,

renderers,
gpu_resources,
resolver,
#[cfg(all(not(target_arch = "wasm32"), debug_assertions))] // native debug build
err_tracker,
staging_belt: Mutex::new(StagingWriteBelt::new(1024 * 1024 * 32)), // 32mb chunk size (as big as a 2048x1024 float4 texture)

frame_global_commands: before_view_builder_commands,

gpu_resources,
mesh_manager,
texture_manager_2d,

resolver,

#[cfg(all(not(target_arch = "wasm32"), debug_assertions))] // native debug build
err_tracker,

frame_index: 0,
}
}

fn create_frame_global_command_encoder(device: &wgpu::Device) -> wgpu::CommandEncoder {
device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: crate::DebugLabel::from("before view builder commands").get(),
})
}

/// Call this at the beginning of a new frame.
///
/// Updates internal book-keeping, frame allocators and executes delayed events like shader reloading.
pub fn frame_maintenance(&mut self) {
pub fn begin_frame(&mut self) {
self.frame_index += 1;

// Tick the error tracker so that it knows when to reset!
// Note that we're ticking on frame_maintenance rather than raw frames, which
// Note that we're ticking on begin_frame rather than raw frames, which
// makes a world of difference when we're in a poisoned state.
#[cfg(all(not(target_arch = "wasm32"), debug_assertions))] // native debug build
self.err_tracker.tick();
Expand All @@ -178,8 +195,8 @@ impl RenderContext {
re_log::debug!(?modified_paths, "got some filesystem events");
}

self.mesh_manager.frame_maintenance(self.frame_index);
self.texture_manager_2d.frame_maintenance(self.frame_index);
self.mesh_manager.begin_frame(self.frame_index);
self.texture_manager_2d.begin_frame(self.frame_index);

{
let WgpuResourcePools {
Expand All @@ -195,13 +212,13 @@ impl RenderContext {

// Shader module maintenance must come before render pipelines because render pipeline
// recompilation picks up all shaders that have been recompiled this frame.
shader_modules.frame_maintenance(
shader_modules.begin_frame(
&self.device,
&mut self.resolver,
self.frame_index,
&modified_paths,
);
render_pipelines.frame_maintenance(
render_pipelines.begin_frame(
&self.device,
self.frame_index,
shader_modules,
Expand All @@ -210,15 +227,32 @@ impl RenderContext {

// Bind group maintenance must come before texture/buffer maintenance since it
// registers texture/buffer use
bind_groups.frame_maintenance(self.frame_index, textures, buffers, samplers);
bind_groups.begin_frame(self.frame_index, textures, buffers, samplers);

textures.frame_maintenance(self.frame_index);
buffers.frame_maintenance(self.frame_index);
textures.begin_frame(self.frame_index);
buffers.begin_frame(self.frame_index);

pipeline_layouts.frame_maintenance(self.frame_index);
bind_group_layouts.frame_maintenance(self.frame_index);
samplers.frame_maintenance(self.frame_index);
pipeline_layouts.begin_frame(self.frame_index);
bind_group_layouts.begin_frame(self.frame_index);
samplers.begin_frame(self.frame_index);
}

// Retrieve unused staging buffer.
self.staging_belt.lock().after_queue_submit();
}

/// Call this at the end of a frame but before submitting command buffers from [`crate::view_builder::ViewBuilder`]
pub fn before_submit(&mut self) {
// Unmap all staging buffers.
self.staging_belt.lock().before_queue_submit();

let mut command_encoder = Self::create_frame_global_command_encoder(&self.device);
std::mem::swap(&mut self.frame_global_commands, &mut command_encoder);
let command_buffer = command_encoder.finish();

// TODO(andreas): For better performance, we should try to bundle this with the single submit call that is currently happening in eframe.
// How do we hook in there and make sure this buffer is submitted first?
self.queue.submit([command_buffer]);
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/re_renderer/src/error_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl ErrorTracker {
/// Logs a wgpu error, making sure to deduplicate them as needed.
pub fn handle_error(&self, error: wgpu::Error) {
// The pipeline is in a poisoned state, errors are still coming in: we won't be
// clearing the tracker until it had at least 2 complete frame_maintenance cycles
// clearing the tracker until it had at least 2 complete begin_frame cycles
// without any errors (meaning the swapchain surface is stabilized).
self.clear_countdown.store(2, Ordering::Relaxed);

Expand Down
1 change: 1 addition & 0 deletions crates/re_renderer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod global_bindings;
mod line_strip_builder;
mod point_cloud_builder;
mod size;
mod staging_write_belt;
mod wgpu_buffer_types;
mod wgpu_resources;

Expand Down
Loading