Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce wgpu based re_renderer (experimental!) #175

Merged
merged 19 commits into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>,
Wumpf marked this conversation as resolved.
Show resolved Hide resolved
};

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