From 7e72f30179744ebb2b62603ee6a016d9bf22f1bc Mon Sep 17 00:00:00 2001 From: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com> Date: Fri, 3 Mar 2023 18:24:17 +0100 Subject: [PATCH] Allow copying of textures with copy-compatible formats (#3528) Co-authored-by: Connor Fitzgerald --- CHANGELOG.md | 1 + wgpu-core/src/command/transfer.rs | 19 ++++++++++--------- wgpu-hal/src/metal/command.rs | 12 ++++++++++-- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6af899b529..d09a341267 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,7 @@ By @teoxoy in [#3534](https://github.com/gfx-rs/wgpu/pull/3534) - Added `TextureFormatFeatureFlags::MULTISAMPLE_X16`. By @Dinnerbone in [#3454](https://github.com/gfx-rs/wgpu/pull/3454) - Support stencil-only views and copying to/from combined depth-stencil textures. By @teoxoy in [#3436](https://github.com/gfx-rs/wgpu/pull/3436) - Added `Features::SHADER_EARLY_DEPTH_TEST`. By @teoxoy in [#3494](https://github.com/gfx-rs/wgpu/pull/3494) +- Allow copying of textures with copy-compatible formats. By @teoxoy in [#3528](https://github.com/gfx-rs/wgpu/pull/3528) - Improve attachment related errors. By @cwfitzgerald in [#3549](https://github.com/gfx-rs/wgpu/pull/3549) - Make error descriptions all upper case. By @cwfitzgerald in [#3549](https://github.com/gfx-rs/wgpu/pull/3549) diff --git a/wgpu-core/src/command/transfer.rs b/wgpu-core/src/command/transfer.rs index 5354485901..dee1ce35f6 100644 --- a/wgpu-core/src/command/transfer.rs +++ b/wgpu-core/src/command/transfer.rs @@ -120,9 +120,9 @@ pub enum TransferError { #[error("The entire texture must be copied when copying from depth texture")] InvalidDepthTextureExtent, #[error( - "Source format ({src_format:?}) and destination format ({dst_format:?}) are not copy-compatible" + "Source format ({src_format:?}) and destination format ({dst_format:?}) are not copy-compatible (they may only differ in srgb-ness)" )] - MismatchedTextureFormats { + TextureFormatsNotCopyCompatible { src_format: wgt::TextureFormat, dst_format: wgt::TextureFormat, }, @@ -1036,13 +1036,14 @@ impl Global { .get(destination.texture) .map_err(|_| TransferError::InvalidTexture(source.texture))?; - // src and dst texture format must be the same. - let src_format = src_texture.desc.format; - let dst_format = dst_texture.desc.format; - if src_format != dst_format { - return Err(TransferError::MismatchedTextureFormats { - src_format, - dst_format, + // src and dst texture format must be copy-compatible + // https://gpuweb.github.io/gpuweb/#copy-compatible + if src_texture.desc.format.remove_srgb_suffix() + != dst_texture.desc.format.remove_srgb_suffix() + { + return Err(TransferError::TextureFormatsNotCopyCompatible { + src_format: src_texture.desc.format, + dst_format: dst_texture.desc.format, } .into()); } diff --git a/wgpu-hal/src/metal/command.rs b/wgpu-hal/src/metal/command.rs index 25e355a32b..1b83f0f112 100644 --- a/wgpu-hal/src/metal/command.rs +++ b/wgpu-hal/src/metal/command.rs @@ -1,5 +1,5 @@ use super::{conv, AsNative}; -use std::{mem, ops::Range}; +use std::{borrow::Cow, mem, ops::Range}; // has to match `Temp::binding_sizes` const WORD_SIZE: usize = 4; @@ -187,6 +187,14 @@ impl crate::CommandEncoder for super::CommandEncoder { ) where T: Iterator, { + let dst_texture = if src.format != dst.format { + let raw_format = self.shared.private_caps.map_format(src.format); + Cow::Owned(objc::rc::autoreleasepool(|| { + dst.raw.new_texture_view(raw_format) + })) + } else { + Cow::Borrowed(&dst.raw) + }; let encoder = self.enter_blit(); for copy in regions { let src_origin = conv::map_origin(©.src_base.origin); @@ -199,7 +207,7 @@ impl crate::CommandEncoder for super::CommandEncoder { copy.src_base.mip_level as u64, src_origin, extent, - &dst.raw, + &dst_texture, copy.dst_base.array_layer as u64, copy.dst_base.mip_level as u64, dst_origin,