From 3208f2e9dd6b74203b2e52054b2798a3c5c2f08c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 14 Apr 2023 11:44:34 +0200 Subject: [PATCH 1/3] Make infallible version of get_or_create_texture --- crates/re_viewer/src/gpu_bridge/mod.rs | 30 ++++++++++++++++--- .../re_viewer/src/gpu_bridge/tensor_to_gpu.rs | 23 +++++++------- .../src/ui/view_tensor/tensor_slice_to_gpu.rs | 2 +- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/crates/re_viewer/src/gpu_bridge/mod.rs b/crates/re_viewer/src/gpu_bridge/mod.rs index 0a70befc9057..eafaeaac2cd9 100644 --- a/crates/re_viewer/src/gpu_bridge/mod.rs +++ b/crates/re_viewer/src/gpu_bridge/mod.rs @@ -52,7 +52,7 @@ pub fn viewport_resolution_in_pixels(clip_rect: egui::Rect, pixels_from_point: f [resolution.x as u32, resolution.y as u32] } -pub fn get_or_create_texture<'a, Err>( +pub fn try_get_or_create_texture<'a, Err>( render_ctx: &mut RenderContext, texture_key: u64, try_create_texture_desc: impl FnOnce() -> Result, Err>, @@ -64,6 +64,23 @@ pub fn get_or_create_texture<'a, Err>( ) } +pub fn get_or_create_texture<'a>( + render_ctx: &mut RenderContext, + texture_key: u64, + create_texture_desc: impl FnOnce() -> Texture2DCreationDesc<'a>, +) -> GpuTexture2DHandle { + enum Never {} + let result: Result = render_ctx + .texture_manager_2d + .get_or_create_with(texture_key, &mut render_ctx.gpu_resources.textures, || { + Ok(create_texture_desc()) + }); + match result { + Ok(handle) => handle, + Err(never) => match never {}, + } +} + /// Render a `re_render` view using the given clip rectangle. pub fn renderer_paint_callback( render_ctx: &mut re_renderer::RenderContext, @@ -132,6 +149,11 @@ pub fn render_image( use re_renderer::renderer::{TextureFilterMag, TextureFilterMin}; + let clip_rect = painter.clip_rect().intersect(image_rect_on_screen); + if !clip_rect.is_positive() { + return Ok(()); + } + // Where in "world space" to paint the image. let space_rect = egui::Rect::from_min_size(egui::Pos2::ZERO, image_rect_on_screen.size()); @@ -163,10 +185,10 @@ pub fn render_image( let space_from_pixel = space_from_points * points_from_pixels; let resolution_in_pixel = - crate::gpu_bridge::viewport_resolution_in_pixels(painter.clip_rect(), pixels_from_points); + crate::gpu_bridge::viewport_resolution_in_pixels(clip_rect, pixels_from_points); anyhow::ensure!(resolution_in_pixel[0] > 0 && resolution_in_pixel[1] > 0); - let camera_position_space = space_from_ui.transform_pos(painter.clip_rect().min); + let camera_position_space = space_from_ui.transform_pos(clip_rect.min); let top_left_position = glam::vec2(camera_position_space.x, camera_position_space.y); let target_config = re_renderer::view_builder::TargetConfiguration { @@ -196,7 +218,7 @@ pub fn render_image( render_ctx, command_buffer, view_builder, - painter.clip_rect(), + clip_rect, painter.ctx().pixels_per_point(), )); diff --git a/crates/re_viewer/src/gpu_bridge/tensor_to_gpu.rs b/crates/re_viewer/src/gpu_bridge/tensor_to_gpu.rs index f907b5b62fe9..d7f1a3f391d6 100644 --- a/crates/re_viewer/src/gpu_bridge/tensor_to_gpu.rs +++ b/crates/re_viewer/src/gpu_bridge/tensor_to_gpu.rs @@ -13,9 +13,9 @@ use re_renderer::{ RenderContext, }; -use crate::misc::caches::TensorStats; +use crate::{gpu_bridge::get_or_create_texture, misc::caches::TensorStats}; -use super::get_or_create_texture; +use super::try_get_or_create_texture; // ---------------------------------------------------------------------------- @@ -63,7 +63,7 @@ fn color_tensor_to_gpu( tensor: &Tensor, tensor_stats: &TensorStats, ) -> anyhow::Result { - let texture_handle = get_or_create_texture(render_ctx, hash(tensor.id()), || { + let texture_handle = try_get_or_create_texture(render_ctx, hash(tensor.id()), || { let [height, width, depth] = height_width_depth(tensor)?; let (data, format) = match (depth, &tensor.data) { // Use R8Unorm and R8Snorm to get filtering on the GPU: @@ -161,10 +161,8 @@ fn class_id_tensor_to_gpu( let colormap_width = 256; let colormap_height = (max as usize + colormap_width - 1) / colormap_width; - let colormap_texture_handle = get_or_create_texture( - render_ctx, - hash(annotations.row_id), - || -> anyhow::Result<_> { + let colormap_texture_handle = + get_or_create_texture(render_ctx, hash(annotations.row_id), || { let data: Vec = (0..(colormap_width * colormap_height)) .flat_map(|id| { let color = annotations @@ -175,17 +173,16 @@ fn class_id_tensor_to_gpu( }) .collect(); - Ok(Texture2DCreationDesc { + Texture2DCreationDesc { label: "class_id_colormap".into(), data: data.into(), format: TextureFormat::Rgba8UnormSrgb, width: colormap_width as u32, height: colormap_height as u32, - }) - }, - )?; + } + }); - let main_texture_handle = get_or_create_texture(render_ctx, hash(tensor.id()), || { + let main_texture_handle = try_get_or_create_texture(render_ctx, hash(tensor.id()), || { general_texture_creation_desc_from_tensor(debug_name, tensor) })?; @@ -214,7 +211,7 @@ fn depth_tensor_to_gpu( ); let (min, max) = depth_tensor_range(tensor, tensor_stats)?; - let texture = get_or_create_texture(render_ctx, hash(tensor.id()), || { + let texture = try_get_or_create_texture(render_ctx, hash(tensor.id()), || { general_texture_creation_desc_from_tensor(debug_name, tensor) })?; diff --git a/crates/re_viewer/src/ui/view_tensor/tensor_slice_to_gpu.rs b/crates/re_viewer/src/ui/view_tensor/tensor_slice_to_gpu.rs index 0bb4d9f9d81c..c967806ed51f 100644 --- a/crates/re_viewer/src/ui/view_tensor/tensor_slice_to_gpu.rs +++ b/crates/re_viewer/src/ui/view_tensor/tensor_slice_to_gpu.rs @@ -56,7 +56,7 @@ fn upload_texture_slice_to_gpu( ) -> Result { let id = egui::util::hash((tensor.id(), slice_selection)); - crate::gpu_bridge::get_or_create_texture(render_ctx, id, || { + crate::gpu_bridge::try_get_or_create_texture(render_ctx, id, || { texture_desc_from_tensor(tensor, slice_selection) }) } From 40654d724edb3d5a602d7817c08479f5fa66b99b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 14 Apr 2023 11:49:24 +0200 Subject: [PATCH 2/3] Show colormap previews in UI --- crates/re_viewer/src/ui/view_tensor/ui.rs | 87 +++++++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/crates/re_viewer/src/ui/view_tensor/ui.rs b/crates/re_viewer/src/ui/view_tensor/ui.rs index f9adcaad42c2..f1c9fe118ad4 100644 --- a/crates/re_viewer/src/ui/view_tensor/ui.rs +++ b/crates/re_viewer/src/ui/view_tensor/ui.rs @@ -78,7 +78,7 @@ impl ViewTensorState { Some(ctx.cache.tensor_stats(tensor)), ); self.texture_settings.ui(ctx.re_ui, ui); - self.color_mapping.ui(ctx.re_ui, ui); + self.color_mapping.ui(ctx.render_ctx, ctx.re_ui, ui); }); ui.separator(); @@ -245,7 +245,12 @@ impl Default for ColorMapping { } impl ColorMapping { - fn ui(&mut self, re_ui: &re_ui::ReUi, ui: &mut egui::Ui) { + fn ui( + &mut self, + render_ctx: &mut re_renderer::RenderContext, + re_ui: &re_ui::ReUi, + ui: &mut egui::Ui, + ) { let ColorMapping { map, gamma } = self; re_ui.grid_left_hand_label(ui, "Color map"); @@ -253,9 +258,16 @@ impl ColorMapping { .selected_text(map.to_string()) .show_ui(ui, |ui| { ui.style_mut().wrap = Some(false); - for option in Colormap::ALL { - ui.selectable_value(map, option, option.to_string()); - } + + egui::Grid::new("colormap_selector") + .num_columns(2) + .show(ui, |ui| { + for option in Colormap::ALL { + ui.selectable_value(map, option, option.to_string()); + colormap_preview_ui(render_ctx, ui, option); + ui.end_row(); + } + }); }); ui.end_row(); @@ -267,6 +279,71 @@ impl ColorMapping { } } +/// Show the given colormap as a horizontal bar. +fn colormap_preview_ui( + render_ctx: &mut re_renderer::RenderContext, + ui: &mut egui::Ui, + colormap: Colormap, +) -> egui::Response { + crate::profile_function!(); + + let desired_size = egui::vec2(128.0, 16.0); + let (rect, response) = ui.allocate_exact_size(desired_size, egui::Sense::hover()); + + if ui.is_rect_visible(rect) { + if let Err(err) = paint_colormap_graident(render_ctx, colormap, ui, rect) { + re_log::error_once!("Failed to paint colormap preview: {err}"); + } + } + + response +} + +fn paint_colormap_graident( + render_ctx: &mut re_renderer::RenderContext, + colormap: Colormap, + ui: &mut egui::Ui, + rect: egui::Rect, +) -> anyhow::Result<()> { + let horizontal_gradient_id = egui::util::hash("horizontal_gradient"); + let horizontal_gradient = + crate::gpu_bridge::get_or_create_texture(render_ctx, horizontal_gradient_id, || { + let width = 256; + let height = 1; + let data: Vec = (0..width) + .flat_map(|x| { + let t = x as f32 / (width as f32 - 1.0); + half::f16::from_f32(t).to_le_bytes() + }) + .collect(); + + re_renderer::resource_managers::Texture2DCreationDesc { + label: "horizontal_gradient".into(), + data: data.into(), + format: wgpu::TextureFormat::R16Float, + width, + height, + } + }); + + let colormapped_texture = re_renderer::renderer::ColormappedTexture { + texture: horizontal_gradient, + range: [0.0, 1.0], + gamma: 1.0, + color_mapper: Some(re_renderer::renderer::ColorMapper::Function(colormap)), + }; + + let debug_name = format!("colormap_{colormap}"); + crate::gpu_bridge::render_image( + render_ctx, + ui.painter(), + rect, + colormapped_texture, + egui::TextureOptions::LINEAR, + &debug_name, + ) +} + // ---------------------------------------------------------------------------- /// Should we scale the rendered texture, and if so, how? From 4be56eb04715593b687291b18bc29f5126ca79be Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 14 Apr 2023 11:51:26 +0200 Subject: [PATCH 3/3] Spelling --- crates/re_viewer/src/ui/view_tensor/ui.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/re_viewer/src/ui/view_tensor/ui.rs b/crates/re_viewer/src/ui/view_tensor/ui.rs index f1c9fe118ad4..d32024fd6f01 100644 --- a/crates/re_viewer/src/ui/view_tensor/ui.rs +++ b/crates/re_viewer/src/ui/view_tensor/ui.rs @@ -291,7 +291,7 @@ fn colormap_preview_ui( let (rect, response) = ui.allocate_exact_size(desired_size, egui::Sense::hover()); if ui.is_rect_visible(rect) { - if let Err(err) = paint_colormap_graident(render_ctx, colormap, ui, rect) { + if let Err(err) = paint_colormap_gradient(render_ctx, colormap, ui, rect) { re_log::error_once!("Failed to paint colormap preview: {err}"); } } @@ -299,7 +299,7 @@ fn colormap_preview_ui( response } -fn paint_colormap_graident( +fn paint_colormap_gradient( render_ctx: &mut re_renderer::RenderContext, colormap: Colormap, ui: &mut egui::Ui,