From 9cfada3f22ad99ff378b8128553ee347864ca038 Mon Sep 17 00:00:00 2001 From: Kanabenki Date: Sat, 21 Oct 2023 21:10:37 +0200 Subject: [PATCH] Detect cubemap for dds textures (#10222) # Objective - Closes #10049. - Detect DDS texture containing a cubemap or a cubemap array. ## Solution - When loading a dds texture, the header capabilities are checked for the cubemap flag. An error is returned if not all faces are provided. --- ## Changelog ### Added - Added a new texture error `TextureError::IncompleteCubemap`, used for dds cubemap textures containing less than 6 faces, as that is not supported on modern graphics APIs. ### Fixed - DDS cubemaps are now loaded as cubemaps instead of 2D textures. ## Migration Guide If you are matching on a `TextureError`, you will need to add a new branch to handle `TextureError::IncompleteCubemap`. --- crates/bevy_render/src/texture/dds.rs | 42 ++++++++++++++++++++----- crates/bevy_render/src/texture/image.rs | 3 ++ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/crates/bevy_render/src/texture/dds.rs b/crates/bevy_render/src/texture/dds.rs index 6f773193ab9a0..16f1aa7240f97 100644 --- a/crates/bevy_render/src/texture/dds.rs +++ b/crates/bevy_render/src/texture/dds.rs @@ -1,6 +1,8 @@ -use ddsfile::{D3DFormat, Dds, DxgiFormat}; +use ddsfile::{Caps2, D3DFormat, Dds, DxgiFormat}; use std::io::Cursor; -use wgpu::{Extent3d, TextureDimension, TextureFormat}; +use wgpu::{ + Extent3d, TextureDimension, TextureFormat, TextureViewDescriptor, TextureViewDimension, +}; use super::{CompressedImageFormats, Image, TextureError}; @@ -18,14 +20,29 @@ pub fn dds_buffer_to_image( ))); } let mut image = Image::default(); + let is_cubemap = dds.header.caps2.contains(Caps2::CUBEMAP); + let mut depth_or_array_layers = if dds.get_num_array_layers() > 1 { + dds.get_num_array_layers() + } else { + dds.get_depth() + }; + if is_cubemap { + if !dds.header.caps2.contains( + Caps2::CUBEMAP_NEGATIVEX + | Caps2::CUBEMAP_NEGATIVEY + | Caps2::CUBEMAP_NEGATIVEZ + | Caps2::CUBEMAP_POSITIVEX + | Caps2::CUBEMAP_POSITIVEY + | Caps2::CUBEMAP_POSITIVEZ, + ) { + return Err(TextureError::IncompleteCubemap); + } + depth_or_array_layers *= 6; + } image.texture_descriptor.size = Extent3d { width: dds.get_width(), height: dds.get_height(), - depth_or_array_layers: if dds.get_num_array_layers() > 1 { - dds.get_num_array_layers() - } else { - dds.get_depth() - }, + depth_or_array_layers, } .physical_size(texture_format); image.texture_descriptor.mip_level_count = dds.get_num_mipmap_levels(); @@ -37,6 +54,17 @@ pub fn dds_buffer_to_image( } else { TextureDimension::D1 }; + if is_cubemap { + let dimension = if image.texture_descriptor.size.depth_or_array_layers > 6 { + TextureViewDimension::CubeArray + } else { + TextureViewDimension::Cube + }; + image.texture_view_descriptor = Some(TextureViewDescriptor { + dimension: Some(dimension), + ..Default::default() + }); + } image.data = dds.data; Ok(image) } diff --git a/crates/bevy_render/src/texture/image.rs b/crates/bevy_render/src/texture/image.rs index d14388d87504c..8adf57267a2fe 100644 --- a/crates/bevy_render/src/texture/image.rs +++ b/crates/bevy_render/src/texture/image.rs @@ -438,6 +438,9 @@ pub enum TextureError { TranscodeError(String), #[error("format requires transcoding: {0:?}")] FormatRequiresTranscodingError(TranscodeFormat), + /// Only cubemaps with six faces are supported. + #[error("only cubemaps with six faces are supported")] + IncompleteCubemap, } /// The type of a raw image buffer.