Pass Aspect to TextureBase::GetSize for multiplanar sizes. Bug: dawn:2099 Change-Id: Ie25ee6686f0ccfcfd33116c1d6316d671c91a36c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/154760 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Kokoro: Austin Eng <enga@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
diff --git a/src/dawn/native/CommandBuffer.cpp b/src/dawn/native/CommandBuffer.cpp index 06a12f6..9bfc06d 100644 --- a/src/dawn/native/CommandBuffer.cpp +++ b/src/dawn/native/CommandBuffer.cpp
@@ -91,9 +91,12 @@ } bool IsCompleteSubresourceCopiedTo(const TextureBase* texture, - const Extent3D copySize, - const uint32_t mipLevel) { - Extent3D extent = texture->GetMipLevelSingleSubresourcePhysicalSize(mipLevel); + const Extent3D& copySize, + const uint32_t mipLevel, + Aspect aspect) { + DAWN_ASSERT(HasOneBit(aspect) || aspect == (Aspect::Depth | Aspect::Stencil)); + + Extent3D extent = texture->GetMipLevelSingleSubresourcePhysicalSize(mipLevel, aspect); switch (texture->GetDimension()) { case wgpu::TextureDimension::e1D: @@ -108,6 +111,14 @@ DAWN_UNREACHABLE(); } +bool IsCompleteSubresourceCopiedTo(const TextureBase* texture, + const Extent3D& copySize, + const uint32_t mipLevel, + wgpu::TextureAspect textureAspect) { + auto aspect = SelectFormatAspects(texture->GetFormat(), textureAspect); + return IsCompleteSubresourceCopiedTo(texture, copySize, mipLevel, aspect); +} + SubresourceRange GetSubresourcesAffectedByCopy(const TextureCopy& copy, const Extent3D& copySize) { switch (copy.texture->GetDimension()) { case wgpu::TextureDimension::e1D:
diff --git a/src/dawn/native/CommandBuffer.h b/src/dawn/native/CommandBuffer.h index 12a81b3..a64c6da 100644 --- a/src/dawn/native/CommandBuffer.h +++ b/src/dawn/native/CommandBuffer.h
@@ -64,8 +64,13 @@ }; bool IsCompleteSubresourceCopiedTo(const TextureBase* texture, - const Extent3D copySize, - const uint32_t mipLevel); + const Extent3D& copySize, + const uint32_t mipLevel, + Aspect aspect); +bool IsCompleteSubresourceCopiedTo(const TextureBase* texture, + const Extent3D& copySize, + const uint32_t mipLevel, + wgpu::TextureAspect textureAspect); SubresourceRange GetSubresourcesAffectedByCopy(const TextureCopy& copy, const Extent3D& copySize); void LazyClearRenderPassAttachments(BeginRenderPassCmd* renderPass);
diff --git a/src/dawn/native/CommandEncoder.cpp b/src/dawn/native/CommandEncoder.cpp index 7ce6935..ee88515 100644 --- a/src/dawn/native/CommandEncoder.cpp +++ b/src/dawn/native/CommandEncoder.cpp
@@ -144,14 +144,7 @@ MaybeError ValidateOrSetAttachmentSize(const TextureViewBase* attachment, uint32_t* width, uint32_t* height) { - Extent3D attachmentSize = attachment->GetTexture()->GetMipLevelSingleSubresourceVirtualSize( - attachment->GetBaseMipLevel()); - // TODO(dawn:2099): TextureBase::GetWidth/Height should take an Aspect parameter and perform the - // necessary computation instead. - if (attachment->GetTexture()->GetFormat().IsMultiPlanar()) { - attachmentSize = attachment->GetTexture()->GetFormat().GetAspectSize( - attachment->GetAspects(), attachmentSize); - } + Extent3D attachmentSize = attachment->GetSingleSubresourceVirtualSize(); if (*width == 0) { DAWN_ASSERT(*height == 0); @@ -230,12 +223,8 @@ "The resolve target %s mip level count (%u) is not 1.", resolveTarget, resolveTarget->GetLevelCount()); - const Extent3D& colorTextureSize = - attachment->GetTexture()->GetMipLevelSingleSubresourceVirtualSize( - attachment->GetBaseMipLevel()); - const Extent3D& resolveTextureSize = - resolveTarget->GetTexture()->GetMipLevelSingleSubresourceVirtualSize( - resolveTarget->GetBaseMipLevel()); + const Extent3D& colorTextureSize = attachment->GetSingleSubresourceVirtualSize(); + const Extent3D& resolveTextureSize = resolveTarget->GetSingleSubresourceVirtualSize(); DAWN_INVALID_IF(colorTextureSize.width != resolveTextureSize.width || colorTextureSize.height != resolveTextureSize.height, "The Resolve target %s size (width: %u, height: %u) does not match the color " @@ -260,9 +249,7 @@ MaybeError ValidateColorAttachmentDepthSlice(const TextureViewBase* attachment, uint32_t depthSlice) { if (attachment->GetDimension() == wgpu::TextureViewDimension::e3D) { - const Extent3D& attachmentSize = - attachment->GetTexture()->GetMipLevelSingleSubresourceVirtualSize( - attachment->GetBaseMipLevel()); + const Extent3D& attachmentSize = attachment->GetSingleSubresourceVirtualSize(); DAWN_INVALID_IF(depthSlice >= attachmentSize.depthOrArrayLayers, "The depth slice index (%u) of 3D %s used as attachment is >= the " @@ -1047,7 +1034,7 @@ Ref<TextureViewBase> implicitMSAATargetRef; DAWN_TRY_ASSIGN(implicitMSAATargetRef, device->CreateImplicitMSAARenderTextureViewFor( - resolveTarget->GetTexture(), implicitSampleCount)); + resolveTarget, implicitSampleCount)); colorTarget = implicitMSAATargetRef.Get(); cmd->colorAttachments[index].view = std::move(implicitMSAATargetRef); @@ -1314,9 +1301,7 @@ descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc; descriptor.format = resolveTarget->GetFormat().format; - descriptor.size = - resolveTarget->GetTexture()->GetMipLevelSingleSubresourceVirtualSize( - resolveTarget->GetBaseMipLevel()); + descriptor.size = resolveTarget->GetSingleSubresourceVirtualSize(); descriptor.dimension = wgpu::TextureDimension::e2D; descriptor.mipLevelCount = 1; @@ -1372,7 +1357,7 @@ dstImageCopyTexture.origin = {0, 0, copyTarget.copyDst->GetBaseArrayLayer()}; - Extent3D extent3D = copyTarget.copySrc->GetTexture()->GetSize(); + Extent3D extent3D = copyTarget.copySrc->GetSingleSubresourceVirtualSize(); auto internalUsageScope = MakeInternalUsageScope(); this->APICopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, @@ -1677,6 +1662,10 @@ DAWN_TRY(GetDevice()->ValidateObject(source->texture)); DAWN_TRY(GetDevice()->ValidateObject(destination->texture)); + DAWN_INVALID_IF(source->texture->GetFormat().IsMultiPlanar() || + destination->texture->GetFormat().IsMultiPlanar(), + "Copying between a multiplanar texture and another texture is " + "currently not allowed."); DAWN_TRY_CONTEXT(ValidateImageCopyTexture(GetDevice(), *source, *copySize), "validating source %s.", source->texture); DAWN_TRY_CONTEXT(ValidateImageCopyTexture(GetDevice(), *destination, *copySize),
diff --git a/src/dawn/native/CommandValidation.cpp b/src/dawn/native/CommandValidation.cpp index 609d3c8..d3a92ce 100644 --- a/src/dawn/native/CommandValidation.cpp +++ b/src/dawn/native/CommandValidation.cpp
@@ -337,13 +337,15 @@ textureCopy.mipLevel, texture->GetNumMipLevels(), texture); DAWN_TRY(ValidateTextureAspect(textureCopy.aspect)); - DAWN_INVALID_IF(SelectFormatAspects(texture->GetFormat(), textureCopy.aspect) == Aspect::None, + + const auto aspect = SelectFormatAspects(texture->GetFormat(), textureCopy.aspect); + DAWN_INVALID_IF(aspect == Aspect::None, "%s format (%s) does not have the selected aspect (%s).", texture, texture->GetFormat().format, textureCopy.aspect); if (texture->GetSampleCount() > 1 || texture->GetFormat().HasDepthOrStencil()) { Extent3D subresourceSize = - texture->GetMipLevelSingleSubresourcePhysicalSize(textureCopy.mipLevel); + texture->GetMipLevelSingleSubresourcePhysicalSize(textureCopy.mipLevel, aspect); DAWN_ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D); DAWN_INVALID_IF( textureCopy.origin.x != 0 || textureCopy.origin.y != 0 || @@ -363,9 +365,14 @@ const ImageCopyTexture& textureCopy, const Extent3D& copySize) { const TextureBase* texture = textureCopy.texture; + const Format& format = textureCopy.texture->GetFormat(); + const Aspect aspect = ConvertAspect(format, textureCopy.aspect); + + DAWN_ASSERT(!format.IsMultiPlanar() || HasOneBit(aspect)); // Validation for the copy being in-bounds: - Extent3D mipSize = texture->GetMipLevelSingleSubresourcePhysicalSize(textureCopy.mipLevel); + Extent3D mipSize = + texture->GetMipLevelSingleSubresourcePhysicalSize(textureCopy.mipLevel, aspect); // For 1D/2D textures, include the array layer as depth so it can be checked with other // dimensions. if (texture->GetDimension() != wgpu::TextureDimension::e3D) { @@ -386,7 +393,6 @@ &textureCopy.origin, ©Size, texture, textureCopy.mipLevel, &mipSize); // Validation for the texel block alignments: - const Format& format = textureCopy.texture->GetFormat(); if (format.isCompressed) { const TexelBlockInfo& blockInfo = format.GetAspectInfo(textureCopy.aspect).block; DAWN_INVALID_IF(
diff --git a/src/dawn/native/CopyTextureForBrowserHelper.cpp b/src/dawn/native/CopyTextureForBrowserHelper.cpp index 0ebd828..3c46ff7 100644 --- a/src/dawn/native/CopyTextureForBrowserHelper.cpp +++ b/src/dawn/native/CopyTextureForBrowserHelper.cpp
@@ -747,7 +747,7 @@ const CopyTextureForBrowserOptions* options) { TextureInfo info; info.origin = source->origin; - info.size = source->texture->GetSize(); + info.size = source->texture->GetSize(source->aspect); Ref<TextureViewBase> srcTextureView = nullptr; TextureViewDescriptor srcTextureViewDesc = {};
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp index 7a9bd34c..83cbd18 100644 --- a/src/dawn/native/Device.cpp +++ b/src/dawn/native/Device.cpp
@@ -884,14 +884,15 @@ } ResultOrError<Ref<TextureViewBase>> DeviceBase::CreateImplicitMSAARenderTextureViewFor( - const TextureBase* singleSampledTexture, + const TextureViewBase* singleSampledTextureView, uint32_t sampleCount) { DAWN_ASSERT(IsLockedByCurrentThreadIfNeeded()); TextureDescriptor desc = {}; desc.dimension = wgpu::TextureDimension::e2D; - desc.format = singleSampledTexture->GetFormat().format; - desc.size = {singleSampledTexture->GetWidth(), singleSampledTexture->GetHeight(), 1}; + desc.format = singleSampledTextureView->GetFormat().format; + desc.size = {singleSampledTextureView->GetSingleSubresourceVirtualSize().width, + singleSampledTextureView->GetSingleSubresourceVirtualSize().height, 1}; desc.sampleCount = sampleCount; desc.usage = wgpu::TextureUsage::RenderAttachment; if (HasFeature(Feature::TransientAttachments)) {
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h index a8ea07f..1a4c9dc 100644 --- a/src/dawn/native/Device.h +++ b/src/dawn/native/Device.h
@@ -200,7 +200,7 @@ PipelineLayoutBase* GetEmptyPipelineLayout(); ResultOrError<Ref<TextureViewBase>> CreateImplicitMSAARenderTextureViewFor( - const TextureBase* singleSampledTexture, + const TextureViewBase* singleSampledTexture, uint32_t sampleCount); ResultOrError<Ref<TextureViewBase>> GetOrCreatePlaceholderTextureViewForExternalTexture();
diff --git a/src/dawn/native/ExternalTexture.cpp b/src/dawn/native/ExternalTexture.cpp index be0c85a..1f64fdf 100644 --- a/src/dawn/native/ExternalTexture.cpp +++ b/src/dawn/native/ExternalTexture.cpp
@@ -101,7 +101,7 @@ DAWN_INVALID_IF(descriptor->visibleSize.width == 0 || descriptor->visibleSize.height == 0, "VisibleSize %s have 0 on width or height.", &descriptor->visibleSize); - const Extent3D textureSize = descriptor->plane0->GetTexture()->GetSize(); + const Extent3D textureSize = descriptor->plane0->GetSingleSubresourceVirtualSize(); DAWN_INVALID_IF(descriptor->visibleSize.width > textureSize.width || descriptor->visibleSize.height > textureSize.height, "VisibleSize %s is exceed the texture size, defined by Plane0 size (%u, %u).", @@ -289,8 +289,8 @@ // Calculate scale factors and offsets from the specified visibleSize. DAWN_ASSERT(descriptor->visibleSize.width > 0); DAWN_ASSERT(descriptor->visibleSize.height > 0); - uint32_t frameWidth = descriptor->plane0->GetTexture()->GetWidth(); - uint32_t frameHeight = descriptor->plane0->GetTexture()->GetHeight(); + uint32_t frameWidth = descriptor->plane0->GetSingleSubresourceVirtualSize().width; + uint32_t frameHeight = descriptor->plane0->GetSingleSubresourceVirtualSize().height; float xScale = static_cast<float>(descriptor->visibleSize.width) / static_cast<float>(frameWidth); float yScale =
diff --git a/src/dawn/native/Format.cpp b/src/dawn/native/Format.cpp index 87d081a..715be6f 100644 --- a/src/dawn/native/Format.cpp +++ b/src/dawn/native/Format.cpp
@@ -140,41 +140,6 @@ return aspectInfo[aspectIndex]; } -Extent3D Format::GetAspectSize(Aspect aspect, const Extent3D& textureSize) const { - switch (aspect) { - case Aspect::Color: - case Aspect::Depth: - case Aspect::Stencil: - case Aspect::CombinedDepthStencil: - return textureSize; - case Aspect::Plane0: - DAWN_ASSERT(IsMultiPlanar()); - return textureSize; - case Aspect::Plane1: { - DAWN_ASSERT(IsMultiPlanar()); - auto planeSize = textureSize; - switch (format) { - case wgpu::TextureFormat::R8BG8Biplanar420Unorm: - case wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm: - if (planeSize.width > 1) { - planeSize.width >>= 1; - } - if (planeSize.height > 1) { - planeSize.height >>= 1; - } - break; - default: - DAWN_UNREACHABLE(); - } - return planeSize; - } - case Aspect::None: - break; - } - - DAWN_UNREACHABLE(); -} - FormatIndex Format::GetIndex() const { return ComputeFormatIndex(format); }
diff --git a/src/dawn/native/Format.h b/src/dawn/native/Format.h index 1137ff4..8a84465 100644 --- a/src/dawn/native/Format.h +++ b/src/dawn/native/Format.h
@@ -154,9 +154,6 @@ // Currently means they differ only in sRGB-ness. bool ViewCompatibleWith(const Format& otherFormat) const; - // Returns the aspect's size given the texture's size. - Extent3D GetAspectSize(Aspect aspect, const Extent3D& textureSize) const; - private: // Used to store the aspectInfo for one or more planes. For single plane "color" formats, // only the first aspect info or aspectInfo[0] is valid. For depth-stencil, the first aspect
diff --git a/src/dawn/native/SwapChain.cpp b/src/dawn/native/SwapChain.cpp index 9ef69f5..469b616 100644 --- a/src/dawn/native/SwapChain.cpp +++ b/src/dawn/native/SwapChain.cpp
@@ -200,8 +200,8 @@ DAWN_ASSERT(mCurrentTexture->GetFormat().format == mFormat); DAWN_ASSERT(IsSubset(mUsage, mCurrentTexture->GetUsage())); DAWN_ASSERT(mCurrentTexture->GetDimension() == wgpu::TextureDimension::e2D); - DAWN_ASSERT(mCurrentTexture->GetWidth() == mWidth); - DAWN_ASSERT(mCurrentTexture->GetHeight() == mHeight); + DAWN_ASSERT(mCurrentTexture->GetWidth(Aspect::Color) == mWidth); + DAWN_ASSERT(mCurrentTexture->GetHeight(Aspect::Color) == mHeight); DAWN_ASSERT(mCurrentTexture->GetNumMipLevels() == 1); DAWN_ASSERT(mCurrentTexture->GetArrayLayers() == 1);
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp index 02bbaba..7ec38f4 100644 --- a/src/dawn/native/Texture.cpp +++ b/src/dawn/native/Texture.cpp
@@ -210,11 +210,12 @@ case wgpu::TextureViewDimension::Cube: case wgpu::TextureViewDimension::CubeArray: DAWN_INVALID_IF( - texture->GetSize().width != texture->GetSize().height, + texture->GetSize(descriptor->aspect).width != + texture->GetSize(descriptor->aspect).height, "A %s texture view is not compatible with %s because the texture's width " "(%u) and height (%u) are not equal.", - descriptor->dimension, texture, texture->GetSize().width, - texture->GetSize().height); + descriptor->dimension, texture, texture->GetSize(descriptor->aspect).width, + texture->GetSize(descriptor->aspect).height); DAWN_INVALID_IF(descriptor->dimension == wgpu::TextureViewDimension::CubeArray && device->IsCompatibilityMode(), "A %s texture view for %s is not supported in compatibility mode", @@ -516,7 +517,8 @@ const Format* viewFormat; DAWN_TRY_ASSIGN(viewFormat, device->GetInternalFormat(descriptor->format)); - DAWN_INVALID_IF(SelectFormatAspects(format, descriptor->aspect) == Aspect::None, + const auto aspect = SelectFormatAspects(format, descriptor->aspect); + DAWN_INVALID_IF(aspect == Aspect::None, "Texture format (%s) does not have the texture view's selected aspect (%s).", format.format, descriptor->aspect); @@ -638,7 +640,7 @@ : ApiObjectBase(device, descriptor->label), mDimension(descriptor->dimension), mFormat(device->GetValidInternalFormat(descriptor->format)), - mSize(descriptor->size), + mBaseSize(descriptor->size), mMipLevelCount(descriptor->mipLevelCount), mSampleCount(descriptor->sampleCount), mUsage(descriptor->usage), @@ -699,7 +701,7 @@ : ApiObjectBase(device, tag, descriptor->label), mDimension(descriptor->dimension), mFormat(kUnusedFormat), - mSize(descriptor->size), + mBaseSize(descriptor->size), mMipLevelCount(descriptor->mipLevelCount), mSampleCount(descriptor->sampleCount), mUsage(descriptor->usage), @@ -734,29 +736,74 @@ DAWN_ASSERT(!IsError()); return mViewFormats; } -const Extent3D& TextureBase::GetSize() const { + +const Extent3D& TextureBase::GetBaseSize() const { DAWN_ASSERT(!IsError()); - return mSize; + return mBaseSize; } -uint32_t TextureBase::GetWidth() const { + +Extent3D TextureBase::GetSize(Aspect aspect) const { DAWN_ASSERT(!IsError()); - return mSize.width; + switch (aspect) { + case Aspect::Color: + case Aspect::Depth: + case Aspect::Stencil: + case Aspect::CombinedDepthStencil: + return mBaseSize; + case Aspect::Plane0: + DAWN_ASSERT(GetFormat().IsMultiPlanar()); + return mBaseSize; + case Aspect::Plane1: { + DAWN_ASSERT(GetFormat().IsMultiPlanar()); + auto planeSize = mBaseSize; + switch (GetFormat().format) { + case wgpu::TextureFormat::R8BG8Biplanar420Unorm: + case wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm: + if (planeSize.width > 1) { + planeSize.width >>= 1; + } + if (planeSize.height > 1) { + planeSize.height >>= 1; + } + break; + default: + DAWN_UNREACHABLE(); + } + return planeSize; + } + case Aspect::None: + break; + } + + if (aspect == (Aspect::Depth | Aspect::Stencil)) { + return mBaseSize; + } + + DAWN_UNREACHABLE(); } -uint32_t TextureBase::GetHeight() const { +Extent3D TextureBase::GetSize(wgpu::TextureAspect textureAspect) const { + const auto aspect = SelectFormatAspects(GetFormat(), textureAspect); + return GetSize(aspect); +} +uint32_t TextureBase::GetWidth(Aspect aspect) const { DAWN_ASSERT(!IsError()); - return mSize.height; + return GetSize(aspect).width; } -uint32_t TextureBase::GetDepth() const { +uint32_t TextureBase::GetHeight(Aspect aspect) const { + DAWN_ASSERT(!IsError()); + return GetSize(aspect).height; +} +uint32_t TextureBase::GetDepth(Aspect aspect) const { DAWN_ASSERT(!IsError()); DAWN_ASSERT(mDimension == wgpu::TextureDimension::e3D); - return mSize.depthOrArrayLayers; + return GetSize(aspect).depthOrArrayLayers; } uint32_t TextureBase::GetArrayLayers() const { DAWN_ASSERT(!IsError()); if (mDimension == wgpu::TextureDimension::e3D) { return 1; } - return mSize.depthOrArrayLayers; + return mBaseSize.depthOrArrayLayers; } uint32_t TextureBase::GetNumMipLevels() const { DAWN_ASSERT(!IsError()); @@ -866,8 +913,10 @@ return mSampleCount > 1; } -bool TextureBase::CoverFullSubresource(uint32_t mipLevel, const Extent3D& size) const { - Extent3D levelSize = GetMipLevelSingleSubresourcePhysicalSize(mipLevel); +bool TextureBase::CoversFullSubresource(uint32_t mipLevel, + Aspect aspect, + const Extent3D& size) const { + Extent3D levelSize = GetMipLevelSingleSubresourcePhysicalSize(mipLevel, aspect); switch (GetDimension()) { case wgpu::TextureDimension::e1D: return size.width == levelSize.width; @@ -879,23 +928,25 @@ DAWN_UNREACHABLE(); } -Extent3D TextureBase::GetMipLevelSingleSubresourceVirtualSize(uint32_t level) const { - Extent3D extent = {std::max(mSize.width >> level, 1u), 1u, 1u}; +Extent3D TextureBase::GetMipLevelSingleSubresourceVirtualSize(uint32_t level, Aspect aspect) const { + Extent3D aspectSize = GetSize(aspect); + Extent3D extent = {std::max(aspectSize.width >> level, 1u), 1u, 1u}; if (mDimension == wgpu::TextureDimension::e1D) { return extent; } - extent.height = std::max(mSize.height >> level, 1u); + extent.height = std::max(aspectSize.height >> level, 1u); if (mDimension == wgpu::TextureDimension::e2D) { return extent; } - extent.depthOrArrayLayers = std::max(mSize.depthOrArrayLayers >> level, 1u); + extent.depthOrArrayLayers = std::max(aspectSize.depthOrArrayLayers >> level, 1u); return extent; } -Extent3D TextureBase::GetMipLevelSingleSubresourcePhysicalSize(uint32_t level) const { - Extent3D extent = GetMipLevelSingleSubresourceVirtualSize(level); +Extent3D TextureBase::GetMipLevelSingleSubresourcePhysicalSize(uint32_t level, + Aspect aspect) const { + Extent3D extent = GetMipLevelSingleSubresourceVirtualSize(level, aspect); // Compressed Textures will have paddings if their width or height is not a multiple of // 4 at non-zero mipmap levels. @@ -913,9 +964,10 @@ } Extent3D TextureBase::ClampToMipLevelVirtualSize(uint32_t level, + Aspect aspect, const Origin3D& origin, const Extent3D& extent) const { - const Extent3D virtualSizeAtLevel = GetMipLevelSingleSubresourceVirtualSize(level); + const Extent3D virtualSizeAtLevel = GetMipLevelSingleSubresourceVirtualSize(level, aspect); DAWN_ASSERT(origin.x <= virtualSizeAtLevel.width); DAWN_ASSERT(origin.y <= virtualSizeAtLevel.height); uint32_t clampedCopyExtentWidth = (extent.width > virtualSizeAtLevel.width - origin.x) @@ -927,10 +979,10 @@ return {clampedCopyExtentWidth, clampedCopyExtentHeight, extent.depthOrArrayLayers}; } -Extent3D TextureBase::GetMipLevelSubresourceVirtualSize(uint32_t level) const { - Extent3D extent = GetMipLevelSingleSubresourceVirtualSize(level); +Extent3D TextureBase::GetMipLevelSubresourceVirtualSize(uint32_t level, Aspect aspect) const { + Extent3D extent = GetMipLevelSingleSubresourceVirtualSize(level, aspect); if (mDimension == wgpu::TextureDimension::e2D) { - extent.depthOrArrayLayers = mSize.depthOrArrayLayers; + extent.depthOrArrayLayers = mBaseSize.depthOrArrayLayers; } return extent; } @@ -968,14 +1020,14 @@ } uint32_t TextureBase::APIGetWidth() const { - return mSize.width; + return mBaseSize.width; } uint32_t TextureBase::APIGetHeight() const { - return mSize.height; + return mBaseSize.height; } uint32_t TextureBase::APIGetDepthOrArrayLayers() const { - return mSize.depthOrArrayLayers; + return mBaseSize.depthOrArrayLayers; } uint32_t TextureBase::APIGetMipLevelCount() const { @@ -1095,6 +1147,11 @@ return mRange; } +Extent3D TextureViewBase::GetSingleSubresourceVirtualSize() const { + DAWN_ASSERT(!IsError()); + return GetTexture()->GetMipLevelSingleSubresourceVirtualSize(GetBaseMipLevel(), GetAspects()); +} + ApiObjectList* TextureViewBase::GetObjectTrackingList() { DAWN_ASSERT(!IsError()); return mTexture->GetViewTrackingList();
diff --git a/src/dawn/native/Texture.h b/src/dawn/native/Texture.h index 505895c..bc030bd 100644 --- a/src/dawn/native/Texture.h +++ b/src/dawn/native/Texture.h
@@ -70,10 +70,15 @@ wgpu::TextureDimension GetDimension() const; const Format& GetFormat() const; const FormatSet& GetViewFormats() const; - const Extent3D& GetSize() const; - uint32_t GetWidth() const; - uint32_t GetHeight() const; - uint32_t GetDepth() const; + + // For multiplanar textures, base size is the size of plane 0. For other types of textures, + // base size is the original size passed via TextureDescriptor. + const Extent3D& GetBaseSize() const; + Extent3D GetSize(Aspect aspect) const; + Extent3D GetSize(wgpu::TextureAspect aspect) const; + uint32_t GetWidth(Aspect aspect) const; + uint32_t GetHeight(Aspect aspect) const; + uint32_t GetDepth(Aspect aspect) const; uint32_t GetArrayLayers() const; uint32_t GetNumMipLevels() const; SubresourceRange GetAllSubresources() const; @@ -97,21 +102,22 @@ bool IsMultisampledTexture() const; // Returns true if the size covers the whole subresource. - bool CoverFullSubresource(uint32_t mipLevel, const Extent3D& size) const; + bool CoversFullSubresource(uint32_t mipLevel, Aspect aspect, const Extent3D& size) const; // For a texture with non-block-compressed texture format, its physical size is always equal // to its virtual size. For a texture with block compressed texture format, the physical // size is the one with paddings if necessary, which is always a multiple of the block size // and used in texture copying. The virtual size is the one without paddings, which is not // required to be a multiple of the block size and used in texture sampling. - Extent3D GetMipLevelSingleSubresourcePhysicalSize(uint32_t level) const; - Extent3D GetMipLevelSingleSubresourceVirtualSize(uint32_t level) const; + Extent3D GetMipLevelSingleSubresourcePhysicalSize(uint32_t level, Aspect aspect) const; + Extent3D GetMipLevelSingleSubresourceVirtualSize(uint32_t level, Aspect aspect) const; Extent3D ClampToMipLevelVirtualSize(uint32_t level, + Aspect aspect, const Origin3D& origin, const Extent3D& extent) const; // For 2d-array textures, this keeps the array layers in contrast to // GetMipLevelSingleSubresourceVirtualSize. - Extent3D GetMipLevelSubresourceVirtualSize(uint32_t level) const; + Extent3D GetMipLevelSubresourceVirtualSize(uint32_t level, Aspect aspect) const; ResultOrError<Ref<TextureViewBase>> CreateView( const TextureViewDescriptor* descriptor = nullptr); @@ -158,7 +164,7 @@ wgpu::TextureDimension mDimension; const Format& mFormat; FormatSet mViewFormats; - Extent3D mSize; + Extent3D mBaseSize; uint32_t mMipLevelCount; uint32_t mSampleCount; wgpu::TextureUsage mUsage = wgpu::TextureUsage::None; @@ -196,6 +202,9 @@ uint32_t GetLayerCount() const; const SubresourceRange& GetSubresourceRange() const; + // Returns the size of the texture's subresource at this view's base mip level and aspect. + Extent3D GetSingleSubresourceVirtualSize() const; + protected: void DestroyImpl() override;
diff --git a/src/dawn/native/d3d11/TextureD3D11.cpp b/src/dawn/native/d3d11/TextureD3D11.cpp index b0c5032..b56b0f4 100644 --- a/src/dawn/native/d3d11/TextureD3D11.cpp +++ b/src/dawn/native/d3d11/TextureD3D11.cpp
@@ -241,12 +241,12 @@ T desc; if constexpr (std::is_same<T, D3D11_TEXTURE1D_DESC>::value) { - desc.Width = GetSize().width; + desc.Width = GetBaseSize().width; desc.ArraySize = GetArrayLayers(); desc.MiscFlags = 0; } else if constexpr (std::is_same<T, D3D11_TEXTURE2D_DESC>::value) { - desc.Width = GetSize().width; - desc.Height = GetSize().height; + desc.Width = GetBaseSize().width; + desc.Height = GetBaseSize().height; desc.ArraySize = GetArrayLayers(); desc.SampleDesc.Count = GetSampleCount(); desc.SampleDesc.Quality = 0; @@ -256,9 +256,9 @@ desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; } } else if constexpr (std::is_same<T, D3D11_TEXTURE3D_DESC>::value) { - desc.Width = GetSize().width; - desc.Height = GetSize().height; - desc.Depth = GetSize().depthOrArrayLayers; + desc.Width = GetBaseSize().width; + desc.Height = GetBaseSize().height; + desc.Depth = GetBaseSize().depthOrArrayLayers; desc.MiscFlags = 0; } @@ -537,35 +537,37 @@ const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(range.aspects).block; // TODO(dawn:1705): Use interim texture clear-and-copy as compressed textures do to // avoid CPU-to-GPU write. - Extent3D writeSize = GetMipLevelSubresourceVirtualSize(range.baseMipLevel); - uint32_t bytesPerRow = blockInfo.byteSize * writeSize.width; + for (Aspect aspect : IterateEnumMask(range.aspects)) { + Extent3D writeSize = GetMipLevelSubresourceVirtualSize(range.baseMipLevel, aspect); + uint32_t bytesPerRow = blockInfo.byteSize * writeSize.width; - uint32_t rowsPerImage = writeSize.height; - uint64_t byteLength; - DAWN_TRY_ASSIGN(byteLength, - ComputeRequiredBytesInCopy(blockInfo, writeSize, bytesPerRow, rowsPerImage)); + uint32_t rowsPerImage = writeSize.height; + uint64_t byteLength; + DAWN_TRY_ASSIGN(byteLength, ComputeRequiredBytesInCopy(blockInfo, writeSize, bytesPerRow, + rowsPerImage)); - std::vector<uint8_t> clearData(byteLength, clearValue == ClearValue::Zero ? 0 : 1); - SubresourceRange writeRange = range; - writeRange.layerCount = 1; - writeRange.levelCount = 1; - for (uint32_t layer = range.baseArrayLayer; layer < range.baseArrayLayer + range.layerCount; - ++layer) { - for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount; - ++level) { - if (clearValue == TextureBase::ClearValue::Zero && - IsSubresourceContentInitialized( - SubresourceRange::SingleMipAndLayer(level, layer, range.aspects))) { - // Skip lazy clears if already initialized. - continue; + std::vector<uint8_t> clearData(byteLength, clearValue == ClearValue::Zero ? 0 : 1); + SubresourceRange writeRange = range; + writeRange.layerCount = 1; + writeRange.levelCount = 1; + for (uint32_t layer = range.baseArrayLayer; layer < range.baseArrayLayer + range.layerCount; + ++layer) { + for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount; + ++level) { + if (clearValue == TextureBase::ClearValue::Zero && + IsSubresourceContentInitialized( + SubresourceRange::SingleMipAndLayer(level, layer, aspect))) { + // Skip lazy clears if already initialized. + continue; + } + writeRange.baseArrayLayer = layer; + writeRange.baseMipLevel = level; + writeSize = GetMipLevelSubresourceVirtualSize(level, aspect); + bytesPerRow = blockInfo.byteSize * writeSize.width; + rowsPerImage = writeSize.height; + DAWN_TRY(WriteInternal(commandContext, writeRange, {0, 0, 0}, writeSize, + clearData.data(), bytesPerRow, rowsPerImage)); } - writeRange.baseArrayLayer = layer; - writeRange.baseMipLevel = level; - writeSize = GetMipLevelSubresourceVirtualSize(level); - bytesPerRow = blockInfo.byteSize * writeSize.width; - rowsPerImage = writeSize.height; - DAWN_TRY(WriteInternal(commandContext, writeRange, {0, 0, 0}, writeSize, - clearData.data(), bytesPerRow, rowsPerImage)); } } @@ -575,13 +577,14 @@ MaybeError Texture::ClearCompressed(CommandRecordingContext* commandContext, const SubresourceRange& range, TextureBase::ClearValue clearValue) { + DAWN_ASSERT(range.aspects == Aspect::Color); const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(range.aspects).block; // Create an interim texture of renderable format for reinterpretation conversion. TextureDescriptor desc = {}; desc.label = "CopyUncompressedTextureToCompressedTexureInterim"; desc.dimension = GetDimension(); DAWN_ASSERT(desc.dimension == wgpu::TextureDimension::e2D); - desc.size = {GetSize().width, GetSize().height, 1}; + desc.size = {GetWidth(Aspect::Color), GetHeight(Aspect::Color), 1}; desc.format = UncompressedTextureFormat(GetFormat().format); desc.mipLevelCount = 1; desc.sampleCount = 1; @@ -631,7 +634,7 @@ continue; } uint32_t dstSubresource = GetSubresourceIndex(level, layer, D3D11Aspect(range.aspects)); - auto physicalSize = GetMipLevelSingleSubresourcePhysicalSize(level); + auto physicalSize = GetMipLevelSingleSubresourcePhysicalSize(level, Aspect::Color); // The documentation says D3D11_BOX's coordinates should be in texels for // textures. However the validation layer seemingly assumes them to be in // blocks. Otherwise it would complain like this: @@ -680,7 +683,8 @@ const uint8_t* data, uint32_t bytesPerRow, uint32_t rowsPerImage) { - if (IsCompleteSubresourceCopiedTo(this, size, subresources.baseMipLevel)) { + if (IsCompleteSubresourceCopiedTo(this, size, subresources.baseMipLevel, + subresources.aspects)) { SetIsSubresourceContentInitialized(true, subresources); } else { // Dawn validation should have ensured that full subresources write for depth/stencil @@ -760,7 +764,8 @@ DAWN_TRY_ASSIGN(stagingTexture, CreateInternal(ToBackend(GetDevice()), &desc, Kind::Staging)); // Depth-stencil subresources can only be written to completely and not partially. - DAWN_ASSERT(IsCompleteSubresourceCopiedTo(this, size, subresources.baseMipLevel)); + DAWN_ASSERT( + IsCompleteSubresourceCopiedTo(this, size, subresources.baseMipLevel, subresources.aspects)); SubresourceRange otherRange = subresources; Aspect otherAspects = GetFormat().aspects & ~subresources.aspects; @@ -993,7 +998,8 @@ ->EnsureSubresourceContentInitialized(commandContext, srcSubresources)); SubresourceRange dstSubresources = GetSubresourcesAffectedByCopy(dst, copy->copySize); - if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, dst.mipLevel)) { + if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, dst.mipLevel, + dst.aspect)) { dst.texture->SetIsSubresourceContentInitialized(true, dstSubresources); } else { // Partial update subresource of a depth/stencil texture is not allowed. @@ -1035,8 +1041,9 @@ DAWN_UNREACHABLE(); } - bool isWholeSubresource = src.texture->CoverFullSubresource(src.mipLevel, copy->copySize) && - dst.texture->CoverFullSubresource(dst.mipLevel, copy->copySize); + bool isWholeSubresource = + src.texture->CoversFullSubresource(src.mipLevel, src.aspect, copy->copySize) && + dst.texture->CoversFullSubresource(dst.mipLevel, dst.aspect, copy->copySize); // Partial update subresource of a depth/stencil texture is not allowed. DAWN_ASSERT(isWholeSubresource || !src.texture->GetFormat().HasDepthOrStencil()); @@ -1072,7 +1079,7 @@ TextureDescriptor desc = {}; desc.label = "InterimStencilTexture"; desc.dimension = GetDimension(); - desc.size = GetSize(); + desc.size = GetSize(Aspect::Stencil); desc.format = wgpu::TextureFormat::R8Uint; desc.mipLevelCount = GetNumMipLevels(); desc.sampleCount = GetSampleCount(); @@ -1086,7 +1093,7 @@ // TODO(dawn:1705): Improve to only sync as few as possible. const auto range = view->GetSubresourceRange(); const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(range.aspects).block; - Extent3D size = GetMipLevelSubresourceVirtualSize(range.baseMipLevel); + Extent3D size = GetMipLevelSubresourceVirtualSize(range.baseMipLevel, range.aspects); uint32_t bytesPerRow = blockInfo.byteSize * size.width; uint32_t rowsPerImage = size.height; uint64_t byteLength; @@ -1098,7 +1105,7 @@ ++layer) { for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount; ++level) { - size = GetMipLevelSubresourceVirtualSize(level); + size = GetMipLevelSubresourceVirtualSize(level, range.aspects); bytesPerRow = blockInfo.byteSize * size.width; rowsPerImage = size.height; auto singleRange = SubresourceRange::MakeSingle(range.aspects, layer, level); @@ -1339,7 +1346,8 @@ case wgpu::TextureViewDimension::e3D: uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; uavDesc.Texture3D.FirstWSlice = 0; - uavDesc.Texture3D.WSize = std::max(1u, GetTexture()->GetDepth() >> GetBaseMipLevel()); + uavDesc.Texture3D.WSize = + std::max(1u, GetSingleSubresourceVirtualSize().depthOrArrayLayers); uavDesc.Texture3D.MipSlice = GetBaseMipLevel(); break; // Cube and Cubemap can't be used as storage texture. So there is no need to create UAV
diff --git a/src/dawn/native/d3d12/CommandBufferD3D12.cpp b/src/dawn/native/d3d12/CommandBufferD3D12.cpp index 4c2eb2e..b4c49af 100644 --- a/src/dawn/native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn/native/d3d12/CommandBufferD3D12.cpp
@@ -69,8 +69,8 @@ DAWN_ASSERT(src.texture->GetFormat().CopyCompatibleWith(dst.texture->GetFormat())); DAWN_ASSERT(src.aspect == dst.aspect); - const Extent3D& srcSize = src.texture->GetSize(); - const Extent3D& dstSize = dst.texture->GetSize(); + const Extent3D& srcSize = src.texture->GetSize(src.aspect); + const Extent3D& dstSize = dst.texture->GetSize(dst.aspect); // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-copyresource // In order to use D3D12's copy resource, the textures must be the same dimensions, and @@ -839,7 +839,8 @@ GetSubresourcesAffectedByCopy(copy->destination, copy->copySize); if (IsCompleteSubresourceCopiedTo(texture, copy->copySize, - copy->destination.mipLevel)) { + copy->destination.mipLevel, + copy->destination.aspect)) { texture->SetIsSubresourceContentInitialized(true, subresources); } else { DAWN_TRY( @@ -913,7 +914,8 @@ DAWN_TRY(source->EnsureSubresourceContentInitialized(commandContext, srcRange)); if (IsCompleteSubresourceCopiedTo(destination, copy->copySize, - copy->destination.mipLevel)) { + copy->destination.mipLevel, + copy->destination.aspect)) { destination->SetIsSubresourceContentInitialized(true, dstRange); } else { DAWN_TRY(
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp index a460199..af836c4 100644 --- a/src/dawn/native/d3d12/DeviceD3D12.cpp +++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -550,7 +550,7 @@ SubresourceRange range = GetSubresourcesAffectedByCopy(dst, copySizePixels); - if (IsCompleteSubresourceCopiedTo(texture, copySizePixels, dst.mipLevel)) { + if (IsCompleteSubresourceCopiedTo(texture, copySizePixels, dst.mipLevel, dst.aspect)) { texture->SetIsSubresourceContentInitialized(true, range); } else { DAWN_TRY(texture->EnsureSubresourceContentInitialized(commandContext, range));
diff --git a/src/dawn/native/d3d12/TextureD3D12.cpp b/src/dawn/native/d3d12/TextureD3D12.cpp index 5c19073..9ce8b1f 100644 --- a/src/dawn/native/d3d12/TextureD3D12.cpp +++ b/src/dawn/native/d3d12/TextureD3D12.cpp
@@ -246,7 +246,7 @@ resourceDescriptor.Dimension = D3D12TextureDimension(GetDimension()); resourceDescriptor.Alignment = 0; - const Extent3D& size = GetSize(); + const Extent3D& size = GetBaseSize(); resourceDescriptor.Width = size.width; resourceDescriptor.Height = size.height; resourceDescriptor.DepthOrArraySize = size.depthOrArrayLayers; @@ -812,7 +812,7 @@ uint32_t sliceCount = 1; if (GetDimension() == wgpu::TextureDimension::e3D) { baseSlice = 0; - sliceCount = std::max(GetDepth() >> level, 1u); + sliceCount = std::max(GetDepth(Aspect::Color) >> level, 1u); } D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = GetRTVDescriptor(GetFormat(), level, baseSlice, sliceCount); @@ -830,7 +830,8 @@ for (Aspect aspect : IterateEnumMask(range.aspects)) { const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(aspect).block; - Extent3D largestMipSize = GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel); + Extent3D largestMipSize = + GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel, aspect); uint32_t bytesPerRow = Align((largestMipSize.width / blockInfo.width) * blockInfo.byteSize, @@ -847,7 +848,7 @@ for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount; ++level) { // compute d3d12 texture copy locations for texture and buffer - Extent3D copySize = GetMipLevelSingleSubresourcePhysicalSize(level); + Extent3D copySize = GetMipLevelSingleSubresourcePhysicalSize(level, aspect); for (uint32_t layer = range.baseArrayLayer; layer < range.baseArrayLayer + range.layerCount; ++layer) { @@ -1116,7 +1117,8 @@ case wgpu::TextureViewDimension::e3D: uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D; uavDesc.Texture3D.FirstWSlice = 0; - uavDesc.Texture3D.WSize = std::max(1u, GetTexture()->GetDepth() >> GetBaseMipLevel()); + uavDesc.Texture3D.WSize = + std::max(1u, GetSingleSubresourceVirtualSize().depthOrArrayLayers); uavDesc.Texture3D.MipSlice = GetBaseMipLevel(); break; // Cube and Cubemap can't be used as storage texture. So there is no need to create UAV
diff --git a/src/dawn/native/metal/TextureMTL.mm b/src/dawn/native/metal/TextureMTL.mm index 9180ad8..18be29e 100644 --- a/src/dawn/native/metal/TextureMTL.mm +++ b/src/dawn/native/metal/TextureMTL.mm
@@ -679,7 +679,8 @@ NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]); MTLTextureDescriptor* mtlDesc = mtlDescRef.Get(); - mtlDesc.width = GetWidth(); + DAWN_ASSERT(!GetFormat().IsMultiPlanar()); + mtlDesc.width = GetBaseSize().width; mtlDesc.sampleCount = GetSampleCount(); // Metal only allows format reinterpretation to happen on swizzle pattern or conversion // between linear space and sRGB. For example, creating bgra8Unorm texture view on @@ -715,7 +716,7 @@ break; case wgpu::TextureDimension::e2D: - mtlDesc.height = GetHeight(); + mtlDesc.height = GetBaseSize().height; mtlDesc.arrayLength = GetArrayLayers(); mtlDesc.depth = 1; if (mtlDesc.arrayLength > 1) { @@ -728,8 +729,8 @@ } break; case wgpu::TextureDimension::e3D: - mtlDesc.height = GetHeight(); - mtlDesc.depth = GetDepth(); + mtlDesc.height = GetBaseSize().height; + mtlDesc.depth = GetBaseSize().depthOrArrayLayers; mtlDesc.arrayLength = 1; DAWN_ASSERT(mtlDesc.sampleCount == 1); mtlDesc.textureType = MTLTextureType3D; @@ -993,9 +994,9 @@ } } - DAWN_TRY( - EncodeEmptyMetalRenderPass(device, commandContext, descriptor, - GetMipLevelSingleSubresourceVirtualSize(level))); + DAWN_TRY(EncodeEmptyMetalRenderPass( + device, commandContext, descriptor, + GetMipLevelSingleSubresourceVirtualSize(level, range.aspects))); } } } else { @@ -1008,7 +1009,8 @@ NSRef<MTLRenderPassDescriptor> descriptor; uint32_t attachment = 0; - uint32_t depth = GetMipLevelSingleSubresourceVirtualSize(level).depthOrArrayLayers; + uint32_t depth = GetMipLevelSingleSubresourceVirtualSize(level, Aspect::Color) + .depthOrArrayLayers; for (uint32_t arrayLayer = range.baseArrayLayer; arrayLayer < range.baseArrayLayer + range.layerCount; arrayLayer++) { @@ -1042,16 +1044,16 @@ attachment = 0; DAWN_TRY(EncodeEmptyMetalRenderPass( device, commandContext, descriptor.Get(), - GetMipLevelSingleSubresourceVirtualSize(level))); + GetMipLevelSingleSubresourceVirtualSize(level, Aspect::Color))); descriptor = nullptr; } } } if (descriptor != nullptr) { - DAWN_TRY( - EncodeEmptyMetalRenderPass(device, commandContext, descriptor.Get(), - GetMipLevelSingleSubresourceVirtualSize(level))); + DAWN_TRY(EncodeEmptyMetalRenderPass( + device, commandContext, descriptor.Get(), + GetMipLevelSingleSubresourceVirtualSize(level, Aspect::Color))); } } } @@ -1065,7 +1067,8 @@ // Computations for the bytes per row / image height are done using the physical size // so that enough data is reserved for compressed textures. - Extent3D largestMipSize = GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel); + Extent3D largestMipSize = + GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel, aspect); uint32_t largestMipBytesPerRow = (largestMipSize.width / blockInfo.width) * blockInfo.byteSize; uint64_t largestMipBytesPerImage = static_cast<uint64_t>(largestMipBytesPerRow) * @@ -1087,7 +1090,7 @@ for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount; ++level) { - Extent3D virtualSize = GetMipLevelSingleSubresourceVirtualSize(level); + Extent3D virtualSize = GetMipLevelSingleSubresourceVirtualSize(level, aspect); for (uint32_t arrayLayer = range.baseArrayLayer; arrayLayer < range.baseArrayLayer + range.layerCount; ++arrayLayer) {
diff --git a/src/dawn/native/metal/UtilsMetal.mm b/src/dawn/native/metal/UtilsMetal.mm index 4ec1fa2..b63475c 100644 --- a/src/dawn/native/metal/UtilsMetal.mm +++ b/src/dawn/native/metal/UtilsMetal.mm
@@ -262,7 +262,7 @@ // clamped to the edge of the texture if the block extends outside the bounds of a // texture. const Extent3D clampedCopyExtent = - texture->ClampToMipLevelVirtualSize(mipLevel, origin, copyExtent); + texture->ClampToMipLevelVirtualSize(mipLevel, aspect, origin, copyExtent); // Note: all current GPUs have a 3D texture size limit of 2048 and otherwise 16348 // for non-3D textures except for Apple2 GPUs (iPhone6) which has a non-3D texture @@ -329,7 +329,7 @@ uint32_t copyBlockRowCount = copyExtent.height / blockInfo.height; if (copyBlockRowCount > 1) { DAWN_ASSERT(copyExtent.height - blockInfo.height < - texture->GetMipLevelSingleSubresourceVirtualSize(mipLevel).height); + texture->GetMipLevelSingleSubresourceVirtualSize(mipLevel, aspect).height); const uint32_t localBytesPerImage = 0; // workaround case 3 copy.push_back(TextureBufferCopySplit::CopyInfo( currentOffset, bytesPerRow, localBytesPerImage, @@ -363,7 +363,7 @@ const Extent3D& size) { DAWN_ASSERT(texture == dst.texture.Get()); SubresourceRange range = GetSubresourcesAffectedByCopy(dst, size); - if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), size, dst.mipLevel)) { + if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), size, dst.mipLevel, dst.aspect)) { texture->SetIsSubresourceContentInitialized(true, range); } else { DAWN_TRY(texture->EnsureSubresourceContentInitialized(commandContext, range));
diff --git a/src/dawn/native/opengl/CommandBufferGL.cpp b/src/dawn/native/opengl/CommandBufferGL.cpp index e7bfb43..d410bcd 100644 --- a/src/dawn/native/opengl/CommandBufferGL.cpp +++ b/src/dawn/native/opengl/CommandBufferGL.cpp
@@ -513,7 +513,7 @@ Extent3D validTextureCopyExtent = copySize; const TextureBase* texture = textureCopy.texture.Get(); Extent3D virtualSizeAtLevel = - texture->GetMipLevelSingleSubresourceVirtualSize(textureCopy.mipLevel); + texture->GetMipLevelSingleSubresourceVirtualSize(textureCopy.mipLevel, textureCopy.aspect); DAWN_ASSERT(textureCopy.origin.x <= virtualSizeAtLevel.width); DAWN_ASSERT(textureCopy.origin.y <= virtualSizeAtLevel.height); if (copySize.width > virtualSizeAtLevel.width - textureCopy.origin.x) { @@ -628,8 +628,8 @@ buffer->EnsureDataInitialized(); SubresourceRange range = GetSubresourcesAffectedByCopy(dst, copy->copySize); - if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, - dst.mipLevel)) { + if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, dst.mipLevel, + dst.aspect)) { dst.texture->SetIsSubresourceContentInitialized(true, range); } else { DAWN_TRY(ToBackend(dst.texture)->EnsureSubresourceContentInitialized(range)); @@ -776,7 +776,7 @@ SubresourceRange dstRange = GetSubresourcesAffectedByCopy(dst, copy->copySize); DAWN_TRY(srcTexture->EnsureSubresourceContentInitialized(srcRange)); - if (IsCompleteSubresourceCopiedTo(dstTexture, copySize, dst.mipLevel)) { + if (IsCompleteSubresourceCopiedTo(dstTexture, copySize, dst.mipLevel, dst.aspect)) { dstTexture->SetIsSubresourceContentInitialized(true, dstRange); } else { DAWN_TRY(dstTexture->EnsureSubresourceContentInitialized(dstRange)); @@ -1342,7 +1342,8 @@ uint32_t z = destination.origin.z; if (texture->GetFormat().isCompressed) { size_t rowSize = copySize.width / blockInfo.width * blockInfo.byteSize; - Extent3D virtSize = texture->GetMipLevelSingleSubresourceVirtualSize(destination.mipLevel); + Extent3D virtSize = texture->GetMipLevelSingleSubresourceVirtualSize(destination.mipLevel, + destination.aspect); uint32_t width = std::min(copySize.width, virtSize.width - x); // In GLES glPixelStorei() doesn't affect CompressedTexSubImage*D() and
diff --git a/src/dawn/native/opengl/QueueGL.cpp b/src/dawn/native/opengl/QueueGL.cpp index 3b0f79b..706e17e 100644 --- a/src/dawn/native/opengl/QueueGL.cpp +++ b/src/dawn/native/opengl/QueueGL.cpp
@@ -63,7 +63,8 @@ textureCopy.aspect = SelectFormatAspects(destination.texture->GetFormat(), destination.aspect); SubresourceRange range = GetSubresourcesAffectedByCopy(textureCopy, writeSizePixel); - if (IsCompleteSubresourceCopiedTo(destination.texture, writeSizePixel, destination.mipLevel)) { + if (IsCompleteSubresourceCopiedTo(destination.texture, writeSizePixel, destination.mipLevel, + destination.aspect)) { destination.texture->SetIsSubresourceContentInitialized(true, range); } else { DAWN_TRY(ToBackend(destination.texture)->EnsureSubresourceContentInitialized(range));
diff --git a/src/dawn/native/opengl/TextureGL.cpp b/src/dawn/native/opengl/TextureGL.cpp index 99ac041..b9cbca6 100644 --- a/src/dawn/native/opengl/TextureGL.cpp +++ b/src/dawn/native/opengl/TextureGL.cpp
@@ -193,7 +193,7 @@ gl.BindTexture(mTarget, mHandle); - AllocateTexture(gl, mTarget, GetSampleCount(), levels, glFormat.internalFormat, GetSize()); + AllocateTexture(gl, mTarget, GetSampleCount(), levels, glFormat.internalFormat, GetBaseSize()); // The texture is not complete if it uses mipmapping and not all levels up to // MAX_LEVEL have been defined. @@ -375,7 +375,7 @@ const GLFormat& glFormat = GetGLFormat(); for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount; ++level) { - Extent3D mipSize = GetMipLevelSingleSubresourcePhysicalSize(level); + Extent3D mipSize = GetMipLevelSingleSubresourcePhysicalSize(level, Aspect::Color); for (uint32_t layer = range.baseArrayLayer; layer < range.baseArrayLayer + range.layerCount; ++layer) { if (clearValue == TextureBase::ClearValue::Zero && @@ -441,8 +441,9 @@ DoClear(); break; case wgpu::TextureDimension::e3D: - uint32_t depth = GetMipLevelSingleSubresourceVirtualSize(level) - .depthOrArrayLayers; + uint32_t depth = + GetMipLevelSingleSubresourceVirtualSize(level, Aspect::Color) + .depthOrArrayLayers; for (GLint z = 0; z < static_cast<GLint>(depth); ++z) { gl.FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, GetHandle(), level, z); @@ -471,7 +472,8 @@ const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(Aspect::Color).block; DAWN_ASSERT(kTextureBytesPerRowAlignment % blockInfo.byteSize == 0); - Extent3D largestMipSize = GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel); + Extent3D largestMipSize = + GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel, Aspect::Color); uint32_t bytesPerRow = Align((largestMipSize.width / blockInfo.width) * blockInfo.byteSize, 4); @@ -515,7 +517,7 @@ dataLayout.bytesPerRow = bytesPerRow; dataLayout.rowsPerImage = largestMipSize.height; - Extent3D mipSize = GetMipLevelSingleSubresourcePhysicalSize(level); + Extent3D mipSize = GetMipLevelSingleSubresourcePhysicalSize(level, Aspect::Color); for (uint32_t layer = range.baseArrayLayer; layer < range.baseArrayLayer + range.layerCount; ++layer) { @@ -647,8 +649,8 @@ uint32_t srcLevel = GetBaseMipLevel(); uint32_t numLevels = GetLevelCount(); - uint32_t width = texture->GetWidth() >> srcLevel; - uint32_t height = texture->GetHeight() >> srcLevel; + uint32_t width = GetSingleSubresourceVirtualSize().width; + uint32_t height = GetSingleSubresourceVirtualSize().height; Extent3D size{width, height, GetLayerCount()}; if (mHandle == 0) {
diff --git a/src/dawn/native/vulkan/CommandBufferVk.cpp b/src/dawn/native/vulkan/CommandBufferVk.cpp index 78d3dd8..2faf05e 100644 --- a/src/dawn/native/vulkan/CommandBufferVk.cpp +++ b/src/dawn/native/vulkan/CommandBufferVk.cpp
@@ -579,7 +579,7 @@ GetSubresourcesAffectedByCopy(copy->destination, copy->copySize); if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, - subresource.mipLevel)) { + subresource.mipLevel, dst.aspect)) { // Since texture has been overwritten, it has been "initialized" dst.texture->SetIsSubresourceContentInitialized(true, range); } else { @@ -647,8 +647,8 @@ DAWN_TRY(ToBackend(src.texture) ->EnsureSubresourceContentInitialized(recordingContext, srcRange)); - if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, - dst.mipLevel)) { + if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, dst.mipLevel, + dst.aspect)) { // Since destination texture has been overwritten, it has been "initialized" dst.texture->SetIsSubresourceContentInitialized(true, dstRange); } else {
diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp index 63ac944..455add0 100644 --- a/src/dawn/native/vulkan/DeviceVk.cpp +++ b/src/dawn/native/vulkan/DeviceVk.cpp
@@ -801,7 +801,8 @@ SubresourceRange range = GetSubresourcesAffectedByCopy(dst, copySizePixels); - if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copySizePixels, subresource.mipLevel)) { + if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copySizePixels, subresource.mipLevel, + dst.aspect)) { // Since texture has been overwritten, it has been "initialized" dst.texture->SetIsSubresourceContentInitialized(true, range); } else {
diff --git a/src/dawn/native/vulkan/SwapChainVk.cpp b/src/dawn/native/vulkan/SwapChainVk.cpp index 0fe1bd2..d7ca5c0 100644 --- a/src/dawn/native/vulkan/SwapChainVk.cpp +++ b/src/dawn/native/vulkan/SwapChainVk.cpp
@@ -551,13 +551,13 @@ region.srcSubresource.baseArrayLayer = 0; region.srcSubresource.layerCount = 1; region.srcOffsets[0] = {0, 0, 0}; - region.srcOffsets[1] = {static_cast<int32_t>(mBlitTexture->GetWidth()), - static_cast<int32_t>(mBlitTexture->GetHeight()), 1}; + region.srcOffsets[1] = {static_cast<int32_t>(mBlitTexture->GetWidth(Aspect::Color)), + static_cast<int32_t>(mBlitTexture->GetHeight(Aspect::Color)), 1}; region.dstSubresource = region.srcSubresource; region.dstOffsets[0] = {0, 0, 0}; - region.dstOffsets[1] = {static_cast<int32_t>(mTexture->GetWidth()), - static_cast<int32_t>(mTexture->GetHeight()), 1}; + region.dstOffsets[1] = {static_cast<int32_t>(mTexture->GetWidth(Aspect::Color)), + static_cast<int32_t>(mTexture->GetHeight(Aspect::Color)), 1}; device->fn.CmdBlitImage(recordingContext->commandBuffer, mBlitTexture->GetHandle(), mBlitTexture->GetCurrentLayoutForSwapChain(), mTexture->GetHandle(),
diff --git a/src/dawn/native/vulkan/TextureVk.cpp b/src/dawn/native/vulkan/TextureVk.cpp index ac52da5..d71df30 100644 --- a/src/dawn/native/vulkan/TextureVk.cpp +++ b/src/dawn/native/vulkan/TextureVk.cpp
@@ -190,7 +190,7 @@ } void FillVulkanCreateInfoSizesAndType(const Texture& texture, VkImageCreateInfo* info) { - const Extent3D& size = texture.GetSize(); + const Extent3D& size = texture.GetBaseSize(); info->mipLevels = texture.GetNumMipLevels(); info->samples = VulkanSampleCount(texture.GetSampleCount()); @@ -746,7 +746,7 @@ DAWN_ASSERT(IsSampleCountSupported(device, createInfo)); - if (GetArrayLayers() >= 6 && GetWidth() == GetHeight()) { + if (GetArrayLayers() >= 6 && GetBaseSize().width == GetBaseSize().height) { createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; } @@ -794,7 +794,7 @@ format == wgpu::TextureFormat::RGBA32Float; textureIsBuggy &= GetNumMipLevels() > 1; textureIsBuggy &= GetDimension() == wgpu::TextureDimension::e2D; - textureIsBuggy &= IsPowerOfTwo(GetWidth()) && IsPowerOfTwo(GetHeight()); + textureIsBuggy &= IsPowerOfTwo(GetBaseSize().width) && IsPowerOfTwo(GetBaseSize().height); if (textureIsBuggy) { DAWN_TRY(ClearTexture(ToBackend(GetDevice())->GetPendingRecordingContext(), GetAllSubresources(), TextureBase::ClearValue::Zero)); @@ -1290,8 +1290,8 @@ range.aspects == Aspect::Plane1); const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(range.aspects).block; - Extent3D largestMipSize = GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel); - largestMipSize = GetFormat().GetAspectSize(range.aspects, largestMipSize); + Extent3D largestMipSize = + GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel, range.aspects); uint32_t bytesPerRow = Align((largestMipSize.width / blockInfo.width) * blockInfo.byteSize, device->GetOptimalBytesPerRowAlignment()); @@ -1307,8 +1307,7 @@ std::vector<VkBufferImageCopy> regions; for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount; ++level) { - Extent3D copySize = GetMipLevelSingleSubresourcePhysicalSize(level); - copySize = GetFormat().GetAspectSize(range.aspects, copySize); + Extent3D copySize = GetMipLevelSingleSubresourcePhysicalSize(level, range.aspects); imageRange.baseMipLevel = level; for (uint32_t layer = range.baseArrayLayer; layer < range.baseArrayLayer + range.layerCount; ++layer) {
diff --git a/src/dawn/native/vulkan/UtilsVulkan.cpp b/src/dawn/native/vulkan/UtilsVulkan.cpp index 7080e11..0d651ef 100644 --- a/src/dawn/native/vulkan/UtilsVulkan.cpp +++ b/src/dawn/native/vulkan/UtilsVulkan.cpp
@@ -115,7 +115,7 @@ Extent3D validTextureCopyExtent = copySize; const TextureBase* texture = textureCopy.texture.Get(); Extent3D virtualSizeAtLevel = - texture->GetMipLevelSingleSubresourceVirtualSize(textureCopy.mipLevel); + texture->GetMipLevelSingleSubresourceVirtualSize(textureCopy.mipLevel, textureCopy.aspect); DAWN_ASSERT(textureCopy.origin.x <= virtualSizeAtLevel.width); DAWN_ASSERT(textureCopy.origin.y <= virtualSizeAtLevel.height); if (copySize.width > virtualSizeAtLevel.width - textureCopy.origin.x) {
diff --git a/src/dawn/tests/end2end/VideoViewsTests.cpp b/src/dawn/tests/end2end/VideoViewsTests.cpp index 77c36e5..161214f 100644 --- a/src/dawn/tests/end2end/VideoViewsTests.cpp +++ b/src/dawn/tests/end2end/VideoViewsTests.cpp
@@ -773,13 +773,13 @@ wgpu::Texture srcTexture = platformTexture->wgpuTexture; wgpu::BufferDescriptor bufferDescriptor; - bufferDescriptor.size = 1; + bufferDescriptor.size = 256; bufferDescriptor.usage = wgpu::BufferUsage::CopyDst; wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor); wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}); - wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 4); + wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 256); wgpu::Extent3D copySize = {1, 1, 1}; @@ -799,14 +799,14 @@ wgpu::Texture srcTexture = platformTexture->wgpuTexture; wgpu::BufferDescriptor bufferDescriptor; - bufferDescriptor.size = 1; + bufferDescriptor.size = 256; bufferDescriptor.usage = wgpu::BufferUsage::CopyDst; wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor); wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); - wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 4); + wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 256); wgpu::Extent3D copySize = {1, 1, 1}; @@ -1433,6 +1433,62 @@ } } +// Test copying from a multi-planar format to a buffer fails if texture aspect is not single plane. +TEST_P(VideoViewsExtendedUsagesTests, T2BCopyAllAspectsFails) { + DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation")); + + auto srcTexture = + CreateMultiPlanarTexture(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc, + /*isCheckerboard*/ false, + /*initialized*/ true); + + wgpu::BufferDescriptor bufferDescriptor; + bufferDescriptor.size = 256; + bufferDescriptor.usage = wgpu::BufferUsage::CopyDst; + wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor); + + wgpu::ImageCopyTexture copySrc = + utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::All); + + wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 256); + + wgpu::Extent3D copySize = {1, 1, 1}; + + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToBuffer(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR_MSG(encoder.Finish(), testing::HasSubstr("More than a single aspect")); +} + +// Test copying from one multi-planar formatted texture into another fails even if +// MultiPlanarFormatExtendedUsages is enabled. +TEST_P(VideoViewsExtendedUsagesTests, T2TCopyPlaneAspectFails) { + DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation")); + + auto srcTexture = + CreateMultiPlanarTexture(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc, + /*isCheckerboard*/ false, + /*initialized*/ true); + auto dstTexture = + CreateMultiPlanarTexture(wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst, + /*isCheckerboard*/ false, + /*initialized*/ true); + + wgpu::ImageCopyTexture copySrc = + utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); + + wgpu::ImageCopyTexture copyDst = + utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only); + + wgpu::Extent3D copySize = {1, 1, 1}; + + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyTextureToTexture(©Src, ©Dst, ©Size); + ASSERT_DEVICE_ERROR_MSG(encoder.Finish(), testing::HasSubstr("not allowed")); +} + DAWN_INSTANTIATE_TEST_B(VideoViewsTests, VideoViewsTestBackend::Backends(), VideoViewsTestBackend::Formats());