Skip to content

Commit

Permalink
Optimize GLTF/GLB texture loading in debug builds
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed May 9, 2023
1 parent 47c8d3e commit 62fe8d5
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 32 deletions.
13 changes: 11 additions & 2 deletions crates/re_renderer/src/importer/gltf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,17 @@ pub fn load_gltf_from_buffer(
lifetime: ResourceLifeTime,
ctx: &mut RenderContext,
) -> anyhow::Result<Vec<MeshInstance>> {
let (doc, buffers, images) = gltf::import_slice(buffer)?;
crate::profile_function!();

let (doc, buffers, images) = {
crate::profile_scope!("gltf::import_slice");
gltf::import_slice(buffer)?
};

let mut images_as_textures = Vec::with_capacity(images.len());
for (_index, image) in images.into_iter().enumerate() {
crate::profile_scope!("image");

let (format, data) = if let Some(format) = map_format(image.format) {
(format, image.pixels)
} else {
Expand All @@ -33,7 +40,7 @@ pub fn load_gltf_from_buffer(
re_log::debug!("Converting Rgb8 to Rgba8");
(
wgpu::TextureFormat::Rgba8UnormSrgb,
Texture2DCreationDesc::convert_rgb8_to_rgba8(&image.pixels),
crate::pad_rgb_to_rgba(&image.pixels, 255),
)
} else {
anyhow::bail!("Unsupported texture format {:?}", image.format);
Expand Down Expand Up @@ -83,6 +90,8 @@ pub fn load_gltf_from_buffer(

let mut meshes = HashMap::with_capacity(doc.meshes().len());
for ref mesh in doc.meshes() {
crate::profile_scope!("mesh");

let re_mesh = import_mesh(
mesh,
&buffers,
Expand Down
23 changes: 23 additions & 0 deletions crates/re_renderer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,26 @@ macro_rules! profile_scope {
puffin::profile_scope!($($arg)*);
};
}

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

/// Pad `RGB` to `RGBA` with the given alpha.
pub fn pad_rgb_to_rgba<T: Copy>(rgb: &[T], alpha: T) -> Vec<T> {
crate::profile_function!();
if cfg!(debug_assertions) {
// fastest version in debug builds.
// 5x faster in debug builds, but 2x slower in release
let mut rgba = vec![alpha; rgb.len() / 3 * 4];
for i in 0..(rgb.len() / 3) {
rgba[4 * i] = rgb[3 * i];
rgba[4 * i + 1] = rgb[3 * i + 1];
rgba[4 * i + 2] = rgb[3 * i + 2];
}
rgba
} else {
// fastest version in optimized builds
rgb.chunks_exact(3)
.flat_map(|chunk| [chunk[0], chunk[1], chunk[2], alpha])
.collect()
}
}
9 changes: 0 additions & 9 deletions crates/re_renderer/src/resource_managers/texture_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,6 @@ pub struct Texture2DCreationDesc<'a> {
//generate_mip_maps: bool, // TODO(andreas): generate mipmaps!
}

impl<'a> Texture2DCreationDesc<'a> {
pub fn convert_rgb8_to_rgba8(rgb_pixels: &[u8]) -> Vec<u8> {
rgb_pixels
.chunks_exact(3)
.flat_map(|color| [color[0], color[1], color[2], 255])
.collect()
}
}

// TODO(andreas): Move this to texture pool.
#[derive(thiserror::Error, Debug)]
pub enum TextureCreationError {
Expand Down
23 changes: 2 additions & 21 deletions crates/re_viewer_context/src/gpu_bridge/tensor_to_gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use wgpu::TextureFormat;

use re_log_types::component_types::{DecodedTensor, Tensor, TensorData};
use re_renderer::{
pad_rgb_to_rgba,
renderer::{ColorMapper, ColormappedTexture},
resource_managers::Texture2DCreationDesc,
RenderContext,
Expand Down Expand Up @@ -419,29 +420,9 @@ fn narrow_f64_to_f32s(slice: &[f64]) -> Cow<'static, [u8]> {
bytes.into()
}

fn pad_to_four_elements<T: Copy>(data: &[T], pad: T) -> Vec<T> {
crate::profile_function!();
if cfg!(debug_assertions) {
// fastest version in debug builds.
// 5x faster in debug builds, but 2x slower in release
let mut padded = vec![pad; data.len() / 3 * 4];
for i in 0..(data.len() / 3) {
padded[4 * i] = data[3 * i];
padded[4 * i + 1] = data[3 * i + 1];
padded[4 * i + 2] = data[3 * i + 2];
}
padded
} else {
// fastest version in optimized builds
data.chunks_exact(3)
.flat_map(|chunk| [chunk[0], chunk[1], chunk[2], pad])
.collect()
}
}

fn pad_and_cast<T: Copy + Pod>(data: &[T], pad: T) -> Cow<'static, [u8]> {
crate::profile_function!();
let padded: Vec<T> = pad_to_four_elements(data, pad);
let padded: Vec<T> = pad_rgb_to_rgba(data, pad);
let bytes: Vec<u8> = pod_collect_to_vec(&padded);
bytes.into()
}
Expand Down

0 comments on commit 62fe8d5

Please sign in to comment.