Skip to content

Commit

Permalink
Expose type erased draw data that can be consumed directly (#2300)
Browse files Browse the repository at this point in the history
<!--
Open the PR up as a draft until you feel it is ready for a proper
review.

Do not make PR:s from your own `main` branch, as that makes it difficult
for reviewers to add their own fixes.

Add any improvements to the branch as new commits to make it easier for
reviewers to follow the progress. All commits will be squashed to a
single commit once the PR is merged into `main`.

Make sure you mention any issues that this PR closes in the description,
as well as any other related issues.

To get an auto-generated PR description you can put "copilot:summary" or
"copilot:walkthrough" anywhere.
-->

### What

Split out of ongoing scene traitification refactor: The `SceneElement`
trait should be able to emit draw data directly and this smaller
refactor allows that. This happens to avoid a lot of copy operations we
had and makes use of DrawData safer as it enforces the "single frame"
assumption a bit better.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [ ] I've included a screenshot or gif (if applicable)

<!-- This line will get updated when the PR build summary job finishes.
-->
PR Build Summary: https://build.rerun.io/pr/2300

<!-- pr-link-docs:start -->
Docs preview: https://rerun.io/preview/c0c317e/docs
<!-- pr-link-docs:end -->
  • Loading branch information
Wumpf authored Jun 2, 2023
1 parent 0abb3d3 commit cd95a96
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 87 deletions.
12 changes: 6 additions & 6 deletions crates/re_renderer/examples/2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,9 @@ impl framework::Example for Render2D {
..Default::default()
},
);
view_builder.queue_draw(&line_strip_draw_data);
view_builder.queue_draw(&point_draw_data);
view_builder.queue_draw(&rectangle_draw_data);
view_builder.queue_draw(line_strip_draw_data.clone());
view_builder.queue_draw(point_draw_data.clone());
view_builder.queue_draw(rectangle_draw_data.clone());
let command_buffer = view_builder
.draw(re_ctx, ecolor::Rgba::TRANSPARENT)
.unwrap();
Expand Down Expand Up @@ -315,9 +315,9 @@ impl framework::Example for Render2D {
},
);
let command_buffer = view_builder
.queue_draw(&line_strip_draw_data)
.queue_draw(&point_draw_data)
.queue_draw(&rectangle_draw_data)
.queue_draw(line_strip_draw_data)
.queue_draw(point_draw_data)
.queue_draw(rectangle_draw_data)
.draw(re_ctx, ecolor::Rgba::TRANSPARENT)
.unwrap();
framework::ViewDrawResult {
Expand Down
24 changes: 12 additions & 12 deletions crates/re_renderer/examples/depth_cloud.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ impl RenderDepthClouds {
pixels_from_point: f32,
resolution_in_pixel: [u32; 2],
target_location: glam::Vec2,
frame_draw_data: &FD,
image_draw_data: &ID,
frame_draw_data: FD,
image_draw_data: ID,
) -> framework::ViewDrawResult
where
FD: DrawData + Sync + Send + Clone + 'static,
Expand Down Expand Up @@ -131,8 +131,8 @@ impl RenderDepthClouds {
);

let command_buffer = view_builder
.queue_draw(&GenericSkyboxDrawData::new(re_ctx))
.queue_draw(&point_cloud_draw_data)
.queue_draw(GenericSkyboxDrawData::new(re_ctx))
.queue_draw(point_cloud_draw_data)
.queue_draw(frame_draw_data)
.queue_draw(image_draw_data)
.draw(re_ctx, ecolor::Rgba::TRANSPARENT)
Expand All @@ -152,8 +152,8 @@ impl RenderDepthClouds {
pixels_from_point: f32,
resolution_in_pixel: [u32; 2],
target_location: glam::Vec2,
frame_draw_data: &FD,
image_draw_data: &ID,
frame_draw_data: FD,
image_draw_data: ID,
) -> framework::ViewDrawResult
where
FD: DrawData + Sync + Send + Clone + 'static,
Expand Down Expand Up @@ -211,8 +211,8 @@ impl RenderDepthClouds {
);

let command_buffer = view_builder
.queue_draw(&GenericSkyboxDrawData::new(re_ctx))
.queue_draw(&depth_cloud_draw_data)
.queue_draw(GenericSkyboxDrawData::new(re_ctx))
.queue_draw(depth_cloud_draw_data)
.queue_draw(frame_draw_data)
.queue_draw(image_draw_data)
.draw(re_ctx, ecolor::Rgba::TRANSPARENT)
Expand Down Expand Up @@ -333,16 +333,16 @@ impl framework::Example for RenderDepthClouds {
pixels_from_point,
splits[0].resolution_in_pixel,
splits[0].target_location,
&frame_draw_data,
&image_draw_data,
frame_draw_data.clone(),
image_draw_data.clone(),
),
self.draw_depth_cloud(
re_ctx,
pixels_from_point,
splits[1].resolution_in_pixel,
splits[1].target_location,
&frame_draw_data,
&image_draw_data,
frame_draw_data,
image_draw_data,
),
]
}
Expand Down
2 changes: 1 addition & 1 deletion crates/re_renderer/examples/depth_offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl framework::Example for Render2D {
},
);
let command_buffer = view_builder
.queue_draw(&RectangleDrawData::new(re_ctx, &rectangles).unwrap())
.queue_draw(RectangleDrawData::new(re_ctx, &rectangles).unwrap())
.draw(re_ctx, ecolor::Rgba::TRANSPARENT)
.unwrap();

Expand Down
8 changes: 4 additions & 4 deletions crates/re_renderer/examples/multiview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ impl Multiview {
&mut self,
re_ctx: &mut RenderContext,
target_cfg: TargetConfiguration,
skybox: &GenericSkyboxDrawData,
draw_data: &D,
skybox: GenericSkyboxDrawData,
draw_data: D,
index: u32,
) -> (ViewBuilder, wgpu::CommandBuffer) {
let mut view_builder = ViewBuilder::new(re_ctx, target_cfg);
Expand Down Expand Up @@ -372,8 +372,8 @@ impl Example for Multiview {
pixels_from_point,
..Default::default()
},
&skybox,
&$name,
skybox.clone(),
$name,
$n,
);
framework::ViewDrawResult {
Expand Down
4 changes: 2 additions & 2 deletions crates/re_renderer/examples/outlines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ impl framework::Example for Outlines {
})
.collect_vec();

view_builder.queue_draw(&re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx));
view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx));
view_builder
.queue_draw(&re_renderer::renderer::MeshDrawData::new(re_ctx, &instances).unwrap());
.queue_draw(re_renderer::renderer::MeshDrawData::new(re_ctx, &instances).unwrap());

let command_buffer = view_builder
.draw(re_ctx, ecolor::Rgba::TRANSPARENT)
Expand Down
8 changes: 4 additions & 4 deletions crates/re_renderer/examples/picking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl framework::Example for Picking {
point_set.picking_ids.iter().cloned(),
);
}
view_builder.queue_draw(&point_builder.to_draw_data(re_ctx).unwrap());
view_builder.queue_draw(point_builder.to_draw_data(re_ctx).unwrap());

let instances = self
.model_mesh_instances
Expand All @@ -186,11 +186,11 @@ impl framework::Example for Picking {
})
.collect_vec();

view_builder.queue_draw(&re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx));
view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx));
view_builder
.queue_draw(&re_renderer::renderer::MeshDrawData::new(re_ctx, &instances).unwrap());
.queue_draw(re_renderer::renderer::MeshDrawData::new(re_ctx, &instances).unwrap());

view_builder.queue_draw(&re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx));
view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx));

let command_buffer = view_builder
.draw(re_ctx, ecolor::Rgba::TRANSPARENT)
Expand Down
2 changes: 2 additions & 0 deletions crates/re_renderer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mod depth_offset;
mod global_bindings;
mod line_strip_builder;
mod point_cloud_builder;
mod queuable_draw_data;
mod size;
mod transform;
mod wgpu_buffer_types;
Expand All @@ -42,6 +43,7 @@ pub use debug_label::DebugLabel;
pub use depth_offset::DepthOffset;
pub use line_strip_builder::{LineStripBuilder, LineStripSeriesBuilder};
pub use point_cloud_builder::{PointCloudBatchBuilder, PointCloudBuilder};
pub use queuable_draw_data::QueueableDrawData;
pub use rect::{RectF32, RectInt};
pub use size::Size;
pub use transform::RectTransform;
Expand Down
58 changes: 58 additions & 0 deletions crates/re_renderer/src/queuable_draw_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::{
draw_phases::DrawPhase,
renderer::{DrawData, Renderer},
RenderContext,
};

#[derive(thiserror::Error, Debug)]
pub enum QueueableDrawDataError {
#[error("Failed to retrieve renderer of type {0}")]
FailedToRetrieveRenderer(&'static str),

#[error("Mismatching draw data type, expected {0}")]
UnexpectedDrawDataType(&'static str),

#[error(transparent)]
DrawError(#[from] anyhow::Error),
}

type DrawFn = dyn for<'a, 'b> Fn(
&'b RenderContext,
DrawPhase,
&'a mut wgpu::RenderPass<'b>,
&'b dyn std::any::Any,
) -> Result<(), QueueableDrawDataError>
+ Sync
+ Send;

/// Type erased draw data that can be submitted directly to the view builder.
pub struct QueueableDrawData {
pub(crate) draw_func: Box<DrawFn>,
pub(crate) draw_data: Box<dyn std::any::Any + std::marker::Send + std::marker::Sync>,
pub(crate) renderer_name: &'static str,
pub(crate) participated_phases: &'static [DrawPhase],
}

impl<D: DrawData + Sync + Send + 'static> From<D> for QueueableDrawData {
fn from(draw_data: D) -> Self {
QueueableDrawData {
draw_func: Box::new(move |ctx, phase, pass, draw_data| {
let renderers = ctx.renderers.read();
let renderer = renderers.get::<D::Renderer>().ok_or(
QueueableDrawDataError::FailedToRetrieveRenderer(std::any::type_name::<
D::Renderer,
>()),
)?;
let draw_data = draw_data.downcast_ref::<D>().ok_or(
QueueableDrawDataError::UnexpectedDrawDataType(std::any::type_name::<D>()),
)?;
renderer
.draw(&ctx.gpu_resources, phase, pass, draw_data)
.map_err(QueueableDrawDataError::from)
}),
draw_data: Box::new(draw_data),
renderer_name: std::any::type_name::<D::Renderer>(),
participated_phases: D::Renderer::participated_phases(),
}
}
}
1 change: 0 additions & 1 deletion crates/re_renderer/src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ use crate::{
/// GPU sided data used by a [`Renderer`] to draw things to the screen.
///
/// Valid only for the frame in which it was created (typically uses temp allocations!).
/// TODO(andreas): Add a mechanism to validate this.
pub trait DrawData {
type Renderer: Renderer<RendererDrawData = Self> + Send + Sync;
}
Expand Down
56 changes: 9 additions & 47 deletions crates/re_renderer/src/view_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,13 @@ use crate::{
ScreenshotProcessor,
},
global_bindings::FrameUniformBuffer,
renderer::{CompositorDrawData, DebugOverlayDrawData, DrawData, Renderer},
queuable_draw_data::QueueableDrawData,
renderer::{CompositorDrawData, DebugOverlayDrawData},
transform::RectTransform,
wgpu_resources::{GpuBindGroup, GpuTexture, PoolError, TextureDesc},
DebugLabel, RectInt, Rgba, Size,
};

type DrawFn = dyn for<'a, 'b> Fn(
&'b RenderContext,
DrawPhase,
&'a mut wgpu::RenderPass<'b>,
&'b dyn std::any::Any,
) -> anyhow::Result<()>
+ Sync
+ Send;

struct QueuedDraw {
draw_func: Box<DrawFn>,
draw_data: Box<dyn std::any::Any + std::marker::Send + std::marker::Sync>,
renderer_name: &'static str,
participated_phases: &'static [DrawPhase],
}

#[derive(thiserror::Error, Debug)]
pub enum ViewBuilderError {
#[error("Screenshot was already scheduled.")]
Expand All @@ -48,7 +33,7 @@ pub enum ViewBuilderError {
/// Used to build up/collect various resources and then send them off for rendering of a single view.
pub struct ViewBuilder {
setup: ViewTargetSetup,
queued_draws: Vec<QueuedDraw>,
queued_draws: Vec<QueueableDrawData>,

// TODO(andreas): Consider making "render processors" a "thing" by establishing a form of hardcoded/limited-flexibility render-graph
outline_mask_processor: Option<OutlineMaskProcessor>,
Expand Down Expand Up @@ -480,14 +465,14 @@ impl ViewBuilder {
)
});

let composition_draw = queued_draw(&CompositorDrawData::new(
let composition_draw = CompositorDrawData::new(
ctx,
&main_target_resolved,
outline_mask_processor
.as_ref()
.map(|p| p.final_voronoi_texture()),
&config.outline_config,
));
);

let setup = ViewTargetSetup {
name: config.name,
Expand All @@ -501,7 +486,7 @@ impl ViewBuilder {

Self {
setup,
queued_draws: vec![composition_draw],
queued_draws: vec![composition_draw.into()],
outline_mask_processor,
screenshot_processor: Default::default(),
picking_processor: Default::default(),
Expand All @@ -528,13 +513,8 @@ impl ViewBuilder {
}
}

pub fn queue_draw<D: DrawData + Sync + Send + Clone + 'static>(
&mut self,
draw_data: &D,
) -> &mut Self {
re_tracing::profile_function!();
self.queued_draws.push(queued_draw(draw_data));

pub fn queue_draw(&mut self, draw_data: impl Into<QueueableDrawData>) -> &mut Self {
self.queued_draws.push(draw_data.into());
self
}

Expand Down Expand Up @@ -745,7 +725,7 @@ impl ViewBuilder {
);

if show_debug_view {
self.queue_draw(&DebugOverlayDrawData::new(
self.queue_draw(DebugOverlayDrawData::new(
ctx,
&picking_processor.picking_target,
self.setup.resolution_in_pixel.into(),
Expand Down Expand Up @@ -783,21 +763,3 @@ impl ViewBuilder {
self.draw_phase(ctx, DrawPhase::Compositing, pass);
}
}

fn queued_draw<D: DrawData + Sync + Send + Clone + 'static>(draw_data: &D) -> QueuedDraw {
QueuedDraw {
draw_func: Box::new(move |ctx, phase, pass, draw_data| {
let renderers = ctx.renderers.read();
let renderer = renderers
.get::<D::Renderer>()
.context("failed to retrieve renderer")?;
let draw_data = draw_data
.downcast_ref::<D>()
.expect("passed wrong type of draw data");
renderer.draw(&ctx.gpu_resources, phase, pass, draw_data)
}),
draw_data: Box::new(draw_data.clone()),
renderer_name: std::any::type_name::<D::Renderer>(),
participated_phases: D::Renderer::participated_phases(),
}
}
15 changes: 6 additions & 9 deletions crates/re_space_view_spatial/src/ui_renderer_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,14 @@ pub fn fill_view_builder(
re_tracing::profile_function!();

view_builder
.queue_draw(&DepthCloudDrawData::new(
.queue_draw(DepthCloudDrawData::new(
render_ctx,
&primitives.depth_clouds,
)?)
.queue_draw(&MeshDrawData::new(
render_ctx,
&primitives.mesh_instances(),
)?)
.queue_draw(&primitives.line_strips.to_draw_data(render_ctx)?)
.queue_draw(&primitives.points.to_draw_data(render_ctx)?)
.queue_draw(&RectangleDrawData::new(
.queue_draw(MeshDrawData::new(render_ctx, &primitives.mesh_instances())?)
.queue_draw(primitives.line_strips.to_draw_data(render_ctx)?)
.queue_draw(primitives.points.to_draw_data(render_ctx)?)
.queue_draw(RectangleDrawData::new(
render_ctx,
&primitives
.images
Expand All @@ -40,7 +37,7 @@ pub fn fill_view_builder(
)?);

if matches!(background, ScreenBackground::GenericSkybox) {
view_builder.queue_draw(&GenericSkyboxDrawData::new(render_ctx));
view_builder.queue_draw(GenericSkyboxDrawData::new(render_ctx));
}

let command_buffer = view_builder.draw(
Expand Down
2 changes: 1 addition & 1 deletion crates/re_viewer_context/src/gpu_bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub fn render_image(

let mut view_builder = ViewBuilder::new(render_ctx, target_config);

view_builder.queue_draw(&re_renderer::renderer::RectangleDrawData::new(
view_builder.queue_draw(re_renderer::renderer::RectangleDrawData::new(
render_ctx,
&[textured_rectangle],
)?);
Expand Down

0 comments on commit cd95a96

Please sign in to comment.