Skip to content

Commit

Permalink
Introduce wgpu based re_renderer (experimental!) (#175)
Browse files Browse the repository at this point in the history
Only renders a placeholder triangle for now
  • Loading branch information
Wumpf authored Oct 11, 2022
1 parent d2dc378 commit 65572c3
Show file tree
Hide file tree
Showing 19 changed files with 346 additions and 61 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

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

16 changes: 16 additions & 0 deletions crates/re_renderer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "re_renderer"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
publish = false

[dependencies]
parking_lot = "0.12"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
wgpu = { version = "0.14", default-features = false }

[target.'cfg(target_arch = "wasm32")'.dependencies]
wgpu = { version = "0.14", default-features = false, features = ["webgl"] }
3 changes: 3 additions & 0 deletions crates/re_renderer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The Rerun renderer

A [wgpu](https://github.com/gfx-rs/wgpu/) based renderer for all your visualization needs.
32 changes: 32 additions & 0 deletions crates/re_renderer/shader/test_triangle.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

struct VertexOut {
@location(0) color: vec4<f32>,
@builtin(position) position: vec4<f32>,
};

var<private> v_positions: array<vec2<f32>, 3> = array<vec2<f32>, 3>(
vec2<f32>(0.0, 1.0),
vec2<f32>(1.0, -1.0),
vec2<f32>(-1.0, -1.0),
);

var<private> v_colors: array<vec4<f32>, 3> = array<vec4<f32>, 3>(
vec4<f32>(1.0, 0.0, 0.0, 1.0),
vec4<f32>(0.0, 1.0, 0.0, 1.0),
vec4<f32>(0.0, 0.0, 1.0, 1.0),
);

@vertex
fn vs_main(@builtin(vertex_index) v_idx: u32) -> VertexOut {
var out: VertexOut;

out.position = vec4<f32>(v_positions[v_idx], 0.0, 1.0);
out.color = v_colors[v_idx];

return out;
}

@fragment
fn fs_main(in: VertexOut) -> @location(0) vec4<f32> {
return in.color;
}
102 changes: 102 additions & 0 deletions crates/re_renderer/src/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/// Any resource involving wgpu rendering which can be re-used accross different scenes.
/// I.e. render pipelines, resource pools, etc.
pub struct RenderContext {
/// The color format used by the eframe output buffer.
output_format_color: wgpu::TextureFormat,

/// The depth format used by the eframe output buffer.
/// TODO(andreas): Should we maintain depth buffers per view and ask for no depth from eframe?
output_format_depth: Option<wgpu::TextureFormat>,

// TODO(andreas): Introduce a pipeline manager
test_triangle: Option<wgpu::RenderPipeline>,
// TODO(andreas): Strongly consider https://docs.rs/slotmap/latest/slotmap/ for resource pools
}

/// Render pipeline handle that needs to be requested from the `RenderContext` and can be resolved to a `wgpu::RenderPipeline` before drawing.
#[derive(Clone, Copy)]
pub(crate) struct RenderPipelineHandle;

impl RenderContext {
pub fn new(
_device: &wgpu::Device,
_queue: &wgpu::Queue,
output_format_color: wgpu::TextureFormat,
output_format_depth: Option<wgpu::TextureFormat>,
) -> Self {
RenderContext {
output_format_color,
output_format_depth,
test_triangle: None,
}
}

/// Requests a render pipeline and returns a handle to it.
///
/// Internally, this ensures the requested pipeline is created and tracked.
/// Returns a handle even if creating the pipeline fails!
/// (this might be due to shader compilation error that might be fixed later)
pub(crate) fn request_render_pipeline(
&mut self,
device: &wgpu::Device,
) -> RenderPipelineHandle {
self.test_triangle.get_or_insert_with(|| {
// TODO(andreas): Standardize bind group and render pipeline layouts so we only ever have a handful.
// (is this feasable?)
// let bind_group_layout =
// device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
// label: Some("custom3d"),
// entries: &[],
// });
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("custom3d"),
bind_group_layouts: &[],
push_constant_ranges: &[],
});
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("custom3d"),
source: wgpu::ShaderSource::Wgsl(
include_str!("../shader/test_triangle.wgsl").into(),
),
});
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("test triangle"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
targets: &[Some(self.output_format_color.into())],
}),
primitive: wgpu::PrimitiveState::default(),
depth_stencil: self
.output_format_depth
.map(|format| wgpu::DepthStencilState {
format,
depth_compare: wgpu::CompareFunction::Always,
depth_write_enabled: false,
stencil: Default::default(),
bias: Default::default(),
}),
multisample: wgpu::MultisampleState::default(),
multiview: None,
})
});

RenderPipelineHandle
}

/// Retrieves a [`wgpu::RenderPipeline`] given a handle.
/// Returns None if the pipeline does not exist or failed to create.
pub(crate) fn render_pipeline(
&self,
_handle: RenderPipelineHandle,
) -> Option<&wgpu::RenderPipeline> {
// TODO(andreas)render_context
self.test_triangle.as_ref()
}
}
53 changes: 53 additions & 0 deletions crates/re_renderer/src/frame_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use parking_lot::RwLock;
use std::sync::Arc;

use crate::context::{RenderContext, RenderPipelineHandle};

/// Mirrors the GPU contents of a frame-global uniform buffer.
/// Contains information that is constant for a single frame like camera.
/// (does not contain information that is special to a particular renderer or global to the Context)
//struct FrameUniformBuffer {
// TODO(andreas): camera matrix and the like.
//}

/// The highest level rendering block in `re_renderer`.
///
/// They are used to build up/collect various resources and then send them off for rendering.
/// Collecting objects in this fashion allows for re-use of common resources (e.g. camera)
#[derive(Default)]
pub struct FrameBuilder {
render_pipeline: Option<RenderPipelineHandle>,
}

pub type SharedFrameBuilder = Arc<RwLock<FrameBuilder>>;

impl FrameBuilder {
pub fn new() -> Self {
FrameBuilder {
render_pipeline: None,
}
}

pub fn new_shared() -> SharedFrameBuilder {
Arc::new(RwLock::new(FrameBuilder::new()))
}

pub fn test_triangle(&mut self, ctx: &mut RenderContext, device: &wgpu::Device) -> &mut Self {
self.render_pipeline = Some(ctx.request_render_pipeline(device));
self
}

/// Draws the final result of a `FrameBuilder` to a given output `RenderPass`
///
/// The bound surface(s) on the `RenderPass` are expected to be the same format as specified on `Context` creation.
pub fn draw<'a>(&self, ctx: &'a RenderContext, pass: &mut wgpu::RenderPass<'a>) {
if let Some(handle) = self.render_pipeline {
let render_pipeline = ctx.render_pipeline(handle);

if let Some(render_pipeline) = render_pipeline {
pass.set_pipeline(render_pipeline);
pass.draw(0..3, 0..1);
}
}
}
}
7 changes: 7 additions & 0 deletions crates/re_renderer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Rerun's renderer.
//!
//! A wgpu based renderer [wgpu](https://github.com/gfx-rs/wgpu/) for all your visualization needs.
//! Used in `re_runner` to display the contents of any view contents other than pure UI.
pub mod context;
pub mod frame_builder;
6 changes: 3 additions & 3 deletions crates/re_viewer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ glow = [
]

## Enable the [`wgpu`](https://crates.io/crates/wgpu) renderer.
wgpu = ["eframe/wgpu", "dep:egui-wgpu", "dep:wgpu"]
wgpu = ["eframe/wgpu", "dep:egui-wgpu", "dep:re_renderer", "dep:wgpu"]


[dependencies]
Expand All @@ -45,6 +45,7 @@ re_log_types = { path = "../re_log_types", features = ["save", "load"] }
re_string_interner = { path = "../re_string_interner" }
re_tensor_ops = { path = "../re_tensor_ops" }
re_ws_comms = { path = "../re_ws_comms", features = ["client"] }
re_renderer = { path = "../re_renderer", optional = true }

eframe = { version = "0.19", default-features = false, features = [
"default_fonts",
Expand All @@ -53,7 +54,6 @@ eframe = { version = "0.19", default-features = false, features = [
egui = { version = "0.19", features = ["extra_debug_asserts", "tracing"] }
egui_extras = { version = "0.19", features = ["tracing"] }


ahash = "0.8"
anyhow = "1.0"
bytemuck = { version = "1.11", features = ["extern_crate_alloc"] }
Expand Down Expand Up @@ -96,7 +96,7 @@ three-d-asset = { version = "0.3.0", optional = true, default-features = false,
] }

egui-wgpu = { version = "0.19", optional = true }
wgpu = { version = "0.14", optional = true, features = ["webgl"] }
wgpu = { version = "0.14", optional = true }


# native dependencies:
Expand Down
3 changes: 1 addition & 2 deletions crates/re_viewer/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use std::sync::mpsc::Receiver;

use crate::misc::{Caches, Options, RecordingConfig, ViewerContext};
use egui_extras::RetainedImage;
use itertools::Itertools as _;
use nohash_hasher::IntMap;
use re_data_store::log_db::LogDb;
use re_log_types::*;

use crate::misc::{Caches, Options, RecordingConfig, ViewerContext};

const WATERMARK: bool = false; // Nice for recording media material

// ----------------------------------------------------------------------------
Expand Down
30 changes: 28 additions & 2 deletions crates/re_viewer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub(crate) use ui::*;
pub use app::App;
pub use remote_viewer_app::RemoteViewerApp;

#[cfg(feature = "wgpu")]
use re_renderer::context::RenderContext;

// ----------------------------------------------------------------------------
// When compiling for native:

Expand Down Expand Up @@ -63,6 +66,29 @@ macro_rules! profile_scope {

// ---------------------------------------------------------------------------

pub(crate) fn customize_egui(ctx: &egui::Context) {
design_tokens::apply_design_tokens(ctx);
pub(crate) fn customize_eframe(cc: &eframe::CreationContext<'_>) {
#[cfg(feature = "wgpu")]
{
let render_state = cc.wgpu_render_state.as_ref().unwrap();
let paint_callback_resources = &mut render_state.renderer.write().paint_callback_resources;

// TODO(andreas): Query used surface format from eframe/renderer.
#[cfg(target_arch = "wasm32")]
let (output_format_color, output_format_depth) =
(wgpu::TextureFormat::Rgba8UnormSrgb, None); // TODO(andreas) fix for not using srgb will be released in `wgpu 0.15`. See https://github.com/gfx-rs/wgpu/pull/3070
#[cfg(not(target_arch = "wasm32"))]
let (output_format_color, output_format_depth) = (
wgpu::TextureFormat::Bgra8Unorm,
Some(wgpu::TextureFormat::Depth32Float),
);

paint_callback_resources.insert(RenderContext::new(
&render_state.device,
&render_state.queue,
output_format_color,
output_format_depth,
));
}

design_tokens::apply_design_tokens(&cc.egui_ctx);
}
2 changes: 0 additions & 2 deletions crates/re_viewer/src/misc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ pub fn calc_bbox_2d(objects: &re_data_store::Objects<'_>) -> emath::Rect {
bbox
}

#[cfg(feature = "glow")]
pub fn calc_bbox_3d(objects: &re_data_store::Objects<'_>) -> macaw::BoundingBox {
crate::profile_function!();

Expand Down Expand Up @@ -163,7 +162,6 @@ pub fn calc_bbox_3d(objects: &re_data_store::Objects<'_>) -> macaw::BoundingBox

// ----------------------------------------------------------------------------

#[cfg(feature = "glow")]
pub mod cam {
use glam::*;
use macaw::Ray3;
Expand Down
2 changes: 1 addition & 1 deletion crates/re_viewer/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub fn run_native_app(app_creator: eframe::AppCreator) {
"Rerun Viewer",
native_options,
Box::new(move |cc| {
crate::customize_egui(&cc.egui_ctx);
crate::customize_eframe(cc);
app_creator(cc)
}),
);
Expand Down
1 change: 0 additions & 1 deletion crates/re_viewer/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pub(crate) mod selection_panel;
pub(crate) mod text_entry_view;
pub(crate) mod time_panel;
pub(crate) mod view2d;
#[cfg(feature = "glow")]
pub(crate) mod view3d;
pub(crate) mod view_tensor;
pub(crate) mod viewport_panel;
Expand Down
Loading

0 comments on commit 65572c3

Please sign in to comment.