From 3b81ae4669e417d203e4649b18b3202c79082849 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 8 Oct 2024 17:54:06 +0200 Subject: [PATCH] cleanup --- .../chroma_subsampling_converter.rs | 12 ++-- .../image_data_to_texture.rs | 70 ++++++------------- .../re_renderer/src/resource_managers/mod.rs | 1 + .../src/gpu_bridge/image_to_gpu.rs | 14 +++- 4 files changed, 39 insertions(+), 58 deletions(-) diff --git a/crates/viewer/re_renderer/src/resource_managers/chroma_subsampling_converter.rs b/crates/viewer/re_renderer/src/resource_managers/chroma_subsampling_converter.rs index 13f9a075226b..0327c3fe65ad 100644 --- a/crates/viewer/re_renderer/src/resource_managers/chroma_subsampling_converter.rs +++ b/crates/viewer/re_renderer/src/resource_managers/chroma_subsampling_converter.rs @@ -15,16 +15,16 @@ use super::ColorPrimaries; /// Supported chroma subsampling input formats. /// -/// This is strongly correlated with the chroma formats in [`super::SourceImageDataFormat`], but has to have -/// stable indices for use in the a uniform buffer. -/// -> Keep in sync with `chroma_subsampling_converter.wgsl` +/// Keep indices in sync with `chroma_subsampling_converter.wgsl` #[allow(non_camel_case_types)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub enum ChromaSubsamplingPixelFormat { /// 4:2:0 subsampling with a separate Y plane, followed by a UV plane. /// /// Expects single channel texture format. - /// Texture layout: + /// + /// First comes entire image in Y in one plane, + /// followed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc. /// /// width /// __________ @@ -40,7 +40,7 @@ pub enum ChromaSubsamplingPixelFormat { /// /// Expects single channel texture format. /// - /// Texture layout: + /// The order of the channels is Y0, U0, Y1, V0, all in the same plane. /// /// width * 2 /// __________________ diff --git a/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs b/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs index 0b0198eba3f0..107691dc8808 100644 --- a/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs +++ b/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs @@ -63,21 +63,13 @@ pub enum SourceImageDataFormat { /// what's appropriate & available for a given device. WgpuCompatible(wgpu::TextureFormat), + /// YUV (== `YCbCr`) formats, typically using chroma downsampling. + Yuv { + format: ChromaSubsamplingPixelFormat, + primaries: ColorPrimaries, + }, + // // TODO(andreas): Add rgb (3 channels!) formats. - - // ----------------------------------------------------------- - // Chroma downsampled formats, using YCbCr format. - // ----------------------------------------------------------- - /// `Y_UV12` (aka `NV12`) is a YUV 4:2:0 chroma downsampled format with 12 bits per pixel and 8 bits per channel. - /// - /// First comes entire image in Y in one plane, - /// followed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc. - Y_UV12(ColorPrimaries), - - /// `YUYV16` (aka `YUYV` or `YUV2`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. - /// - /// The order of the channels is Y0, U0, Y1, V0, all in the same plane. - YUYV16(ColorPrimaries), } impl From for SourceImageDataFormat { @@ -175,11 +167,8 @@ impl<'a> ImageDataDesc<'a> { .ok_or(ImageDataToTextureError::UnsupportedTextureFormat(*format))? as usize } - SourceImageDataFormat::Y_UV12(_) => { - ChromaSubsamplingPixelFormat::Y_UV12.expected_data_buffer_size(*width, *height) - } - SourceImageDataFormat::YUYV16(_) => { - ChromaSubsamplingPixelFormat::YUYV16.expected_data_buffer_size(*width, *height) + SourceImageDataFormat::Yuv { format, .. } => { + format.expected_data_buffer_size(*width, *height) } }; @@ -228,29 +217,19 @@ pub fn transfer_image_data_to_texture( // Reminder: We can't use raw buffers because of WebGL compatibility. let (data_texture_width, data_texture_height) = match source_format { SourceImageDataFormat::WgpuCompatible(_) => (width, height), - SourceImageDataFormat::Y_UV12(_) => { - ChromaSubsamplingPixelFormat::Y_UV12.expected_data_width_height(width, height) - } - SourceImageDataFormat::YUYV16(_) => { - ChromaSubsamplingPixelFormat::YUYV16.expected_data_width_height(width, height) + SourceImageDataFormat::Yuv { format, .. } => { + format.expected_data_width_height(width, height) } }; let data_texture_format = match source_format { SourceImageDataFormat::WgpuCompatible(format) => format, - SourceImageDataFormat::Y_UV12(_) => { - ChromaSubsamplingPixelFormat::Y_UV12.expected_data_texture_format() - } - SourceImageDataFormat::YUYV16(_) => { - ChromaSubsamplingPixelFormat::YUYV16.expected_data_texture_format() - } + SourceImageDataFormat::Yuv { format, .. } => format.expected_data_texture_format(), }; // Allocate gpu belt data and upload it. let data_texture_label = match source_format { SourceImageDataFormat::WgpuCompatible(_) => label.clone(), - SourceImageDataFormat::Y_UV12(_) | SourceImageDataFormat::YUYV16(_) => { - format!("{label}_source_data").into() - } + SourceImageDataFormat::Yuv { .. } => format!("{label}_source_data").into(), }; let data_texture = ctx.gpu_resources.textures.alloc( &ctx.device, @@ -276,22 +255,15 @@ pub fn transfer_image_data_to_texture( // No further conversion needed, we're done here! return Ok(data_texture); } - SourceImageDataFormat::Y_UV12(primaries) | SourceImageDataFormat::YUYV16(primaries) => { - let chroma_format = match source_format { - SourceImageDataFormat::WgpuCompatible(_) => unreachable!(), - SourceImageDataFormat::Y_UV12(_) => ChromaSubsamplingPixelFormat::Y_UV12, - SourceImageDataFormat::YUYV16(_) => ChromaSubsamplingPixelFormat::YUYV16, - }; - ChromaSubsamplingConversionTask::new( - ctx, - chroma_format, - primaries, - &data_texture, - &label, - width, - height, - ) - } + SourceImageDataFormat::Yuv { format, primaries } => ChromaSubsamplingConversionTask::new( + ctx, + format, + primaries, + &data_texture, + &label, + width, + height, + ), }; // Once there's different gpu based conversions, we should probably trait-ify this so we can keep the basic steps. diff --git a/crates/viewer/re_renderer/src/resource_managers/mod.rs b/crates/viewer/re_renderer/src/resource_managers/mod.rs index 0778faca1b9f..91fdefc111a4 100644 --- a/crates/viewer/re_renderer/src/resource_managers/mod.rs +++ b/crates/viewer/re_renderer/src/resource_managers/mod.rs @@ -10,6 +10,7 @@ mod chroma_subsampling_converter; mod image_data_to_texture; mod texture_manager; +pub use chroma_subsampling_converter::ChromaSubsamplingPixelFormat; pub use image_data_to_texture::{ ColorPrimaries, ImageDataDesc, ImageDataToTextureError, SourceImageDataFormat, }; diff --git a/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs b/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs index 7114ef39345e..ad91401d496b 100644 --- a/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs +++ b/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs @@ -10,7 +10,9 @@ use re_renderer::{ config::DeviceCaps, pad_rgb_to_rgba, renderer::{ColorMapper, ColormappedTexture, ShaderDecoding}, - resource_managers::{ColorPrimaries, ImageDataDesc, SourceImageDataFormat}, + resource_managers::{ + ChromaSubsamplingPixelFormat, ColorPrimaries, ImageDataDesc, SourceImageDataFormat, + }, RenderContext, }; use re_types::components::ClassId; @@ -253,11 +255,17 @@ pub fn texture_creation_desc_from_color_image<'a>( // but should confirm & back that up! PixelFormat::NV12 => ( cast_slice_to_cow(image.buffer.as_slice()), - SourceImageDataFormat::Y_UV12(ColorPrimaries::Bt601), + SourceImageDataFormat::Yuv { + format: ChromaSubsamplingPixelFormat::Y_UV12, + primaries: ColorPrimaries::Bt601, + }, ), PixelFormat::YUY2 => ( cast_slice_to_cow(image.buffer.as_slice()), - SourceImageDataFormat::YUYV16(ColorPrimaries::Bt601), + SourceImageDataFormat::Yuv { + format: ChromaSubsamplingPixelFormat::YUYV16, + primaries: ColorPrimaries::Bt601, + }, ), } } else {