Implement depth-only/stencil-only copies on Vulkan and Metal
Bug: dawn:439
Change-Id: I07ab014f4f13b73c09b2eecc48cd38b06d88166a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24684
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp
index 8315b1b..3b7d016 100644
--- a/src/dawn_native/vulkan/CommandBufferVk.cpp
+++ b/src/dawn_native/vulkan/CommandBufferVk.cpp
@@ -68,7 +68,7 @@
// TODO(jiawei.shao@intel.com): support 1D and 3D textures
ASSERT(srcTexture->GetDimension() == wgpu::TextureDimension::e2D &&
dstTexture->GetDimension() == wgpu::TextureDimension::e2D);
- region.srcSubresource.aspectMask = srcTexture->GetVkAspectMask();
+ region.srcSubresource.aspectMask = srcTexture->GetVkAspectMask(srcCopy.aspect);
region.srcSubresource.mipLevel = srcCopy.mipLevel;
region.srcSubresource.baseArrayLayer = srcCopy.origin.z;
region.srcSubresource.layerCount = copySize.depth;
@@ -77,7 +77,7 @@
region.srcOffset.y = srcCopy.origin.y;
region.srcOffset.z = 0;
- region.dstSubresource.aspectMask = dstTexture->GetVkAspectMask();
+ region.dstSubresource.aspectMask = dstTexture->GetVkAspectMask(dstCopy.aspect);
region.dstSubresource.mipLevel = dstCopy.mipLevel;
region.dstSubresource.baseArrayLayer = dstCopy.origin.z;
region.dstSubresource.layerCount = copySize.depth;
diff --git a/src/dawn_native/vulkan/QueueVk.cpp b/src/dawn_native/vulkan/QueueVk.cpp
index b19b236..c7c4ad7 100644
--- a/src/dawn_native/vulkan/QueueVk.cpp
+++ b/src/dawn_native/vulkan/QueueVk.cpp
@@ -36,10 +36,10 @@
uint32_t optimallyAlignedBytesPerRow,
uint32_t alignedRowsPerImage,
const TextureDataLayout* dataLayout,
- const Format& textureFormat,
+ const TexelBlockInfo& blockInfo,
const Extent3D* writeSize) {
uint32_t newDataSize = ComputeRequiredBytesInCopy(
- textureFormat, *writeSize, optimallyAlignedBytesPerRow, alignedRowsPerImage);
+ blockInfo, *writeSize, optimallyAlignedBytesPerRow, alignedRowsPerImage);
uint64_t optimalOffsetAlignment =
ToBackend(device)
@@ -56,10 +56,10 @@
const uint8_t* srcPointer = static_cast<const uint8_t*>(data);
srcPointer += dataLayout->offset;
- uint32_t alignedRowsPerImageInBlock = alignedRowsPerImage / textureFormat.blockHeight;
- uint32_t dataRowsPerImageInBlock = dataLayout->rowsPerImage / textureFormat.blockHeight;
+ uint32_t alignedRowsPerImageInBlock = alignedRowsPerImage / blockInfo.blockHeight;
+ uint32_t dataRowsPerImageInBlock = dataLayout->rowsPerImage / blockInfo.blockHeight;
if (dataRowsPerImageInBlock == 0) {
- dataRowsPerImageInBlock = writeSize->height / textureFormat.blockHeight;
+ dataRowsPerImageInBlock = writeSize->height / blockInfo.blockHeight;
}
uint64_t additionalOffset =
@@ -110,12 +110,14 @@
size_t dataSize,
const TextureDataLayout* dataLayout,
const Extent3D* writeSize) {
- uint32_t blockSize = destination->texture->GetFormat().blockByteSize;
- uint32_t blockWidth = destination->texture->GetFormat().blockWidth;
+ const TexelBlockInfo& blockInfo =
+ destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect);
+
// We are only copying the part of the data that will appear in the texture.
// Note that validating texture copy range ensures that writeSize->width and
// writeSize->height are multiples of blockWidth and blockHeight respectively.
- uint32_t alignedBytesPerRow = (writeSize->width) / blockWidth * blockSize;
+ uint32_t alignedBytesPerRow =
+ (writeSize->width) / blockInfo.blockWidth * blockInfo.blockByteSize;
uint32_t alignedRowsPerImage = writeSize->height;
uint32_t optimalBytesPerRowAlignment =
@@ -126,11 +128,10 @@
Align(alignedBytesPerRow, optimalBytesPerRowAlignment);
UploadHandle uploadHandle;
- DAWN_TRY_ASSIGN(
- uploadHandle,
- UploadTextureDataAligningBytesPerRow(
- GetDevice(), data, dataSize, alignedBytesPerRow, optimallyAlignedBytesPerRow,
- alignedRowsPerImage, dataLayout, destination->texture->GetFormat(), writeSize));
+ DAWN_TRY_ASSIGN(uploadHandle, UploadTextureDataAligningBytesPerRow(
+ GetDevice(), data, dataSize, alignedBytesPerRow,
+ optimallyAlignedBytesPerRow, alignedRowsPerImage,
+ dataLayout, blockInfo, writeSize));
TextureDataLayout passDataLayout = *dataLayout;
passDataLayout.offset = uploadHandle.startOffset;
@@ -141,9 +142,10 @@
textureCopy.texture = destination->texture;
textureCopy.mipLevel = destination->mipLevel;
textureCopy.origin = destination->origin;
+ textureCopy.aspect = destination->aspect;
return ToBackend(GetDevice())
->CopyFromStagingToTexture(uploadHandle.stagingBuffer, passDataLayout, &textureCopy,
*writeSize);
}
-}} // namespace dawn_native::vulkan
\ No newline at end of file
+}} // namespace dawn_native::vulkan
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 3c7ffe8..6d1291bf 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -669,8 +669,21 @@
return mHandle;
}
- VkImageAspectFlags Texture::GetVkAspectMask() const {
- return VulkanAspectMask(GetFormat().aspects);
+ VkImageAspectFlags Texture::GetVkAspectMask(wgpu::TextureAspect aspect) const {
+ // TODO(enga): These masks could be precomputed.
+ switch (aspect) {
+ case wgpu::TextureAspect::All:
+ return VulkanAspectMask(GetFormat().aspects);
+ case wgpu::TextureAspect::DepthOnly:
+ ASSERT(GetFormat().aspects & Aspect::Depth);
+ return VulkanAspectMask(Aspect::Depth);
+ case wgpu::TextureAspect::StencilOnly:
+ ASSERT(GetFormat().aspects & Aspect::Stencil);
+ return VulkanAspectMask(Aspect::Stencil);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
}
void Texture::TweakTransitionForExternalUsage(CommandRecordingContext* recordingContext,
@@ -872,7 +885,7 @@
TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst, range);
if (GetFormat().isRenderable) {
VkImageSubresourceRange imageRange = {};
- imageRange.aspectMask = GetVkAspectMask();
+ imageRange.aspectMask = GetVkAspectMask(wgpu::TextureAspect::All);
imageRange.levelCount = 1;
imageRange.layerCount = 1;
@@ -943,10 +956,12 @@
continue;
}
+ ASSERT(GetFormat().aspects == Aspect::Color);
dawn_native::TextureCopy textureCopy;
textureCopy.texture = this;
textureCopy.origin = {0, 0, layer};
textureCopy.mipLevel = level;
+ textureCopy.aspect = wgpu::TextureAspect::All;
VkBufferImageCopy region =
ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize);
diff --git a/src/dawn_native/vulkan/TextureVk.h b/src/dawn_native/vulkan/TextureVk.h
index 8a1564a..6748ebd 100644
--- a/src/dawn_native/vulkan/TextureVk.h
+++ b/src/dawn_native/vulkan/TextureVk.h
@@ -59,7 +59,7 @@
VkImage nativeImage);
VkImage GetHandle() const;
- VkImageAspectFlags GetVkAspectMask() const;
+ VkImageAspectFlags GetVkAspectMask(wgpu::TextureAspect aspect) const;
// Transitions the texture to be used as `usage`, recording any necessary barrier in
// `commands`.
diff --git a/src/dawn_native/vulkan/UtilsVulkan.cpp b/src/dawn_native/vulkan/UtilsVulkan.cpp
index 15011ce..b7116da 100644
--- a/src/dawn_native/vulkan/UtilsVulkan.cpp
+++ b/src/dawn_native/vulkan/UtilsVulkan.cpp
@@ -84,12 +84,14 @@
region.bufferOffset = dataLayout.offset;
// In Vulkan the row length is in texels while it is in bytes for Dawn
- const Format& format = texture->GetFormat();
- ASSERT(dataLayout.bytesPerRow % format.blockByteSize == 0);
- region.bufferRowLength = dataLayout.bytesPerRow / format.blockByteSize * format.blockWidth;
+ const TexelBlockInfo& blockInfo =
+ texture->GetFormat().GetTexelBlockInfo(textureCopy.aspect);
+ ASSERT(dataLayout.bytesPerRow % blockInfo.blockByteSize == 0);
+ region.bufferRowLength =
+ dataLayout.bytesPerRow / blockInfo.blockByteSize * blockInfo.blockWidth;
region.bufferImageHeight = dataLayout.rowsPerImage;
- region.imageSubresource.aspectMask = texture->GetVkAspectMask();
+ region.imageSubresource.aspectMask = texture->GetVkAspectMask(textureCopy.aspect);
region.imageSubresource.mipLevel = textureCopy.mipLevel;
switch (textureCopy.texture->GetDimension()) {
@@ -115,4 +117,4 @@
return region;
}
-}} // namespace dawn_native::vulkan
\ No newline at end of file
+}} // namespace dawn_native::vulkan