From d066d17ef6f8030efe9999f67ce60c97fe97aa09 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Mon, 10 May 2021 18:58:51 +0000 Subject: [PATCH] Implement 3D texture copies on Vulkan Bug: dawn:781 Change-Id: I5a1b3cc906b2bcb89c0ba3b202bacd16e012efe8 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/50241 Commit-Queue: Austin Eng Reviewed-by: Corentin Wallez Reviewed-by: Yunchao He --- src/dawn_native/vulkan/CommandBufferVk.cpp | 55 +++++++++++++++------- src/dawn_native/vulkan/DeviceVk.cpp | 2 +- src/dawn_native/vulkan/TextureVk.cpp | 3 -- src/dawn_native/vulkan/UtilsVulkan.cpp | 16 ++++++- src/tests/end2end/CopyTests.cpp | 20 ++++---- 5 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp index 48427ba63a..bbdcf6c3b9 100644 --- a/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/src/dawn_native/vulkan/CommandBufferVk.cpp @@ -69,33 +69,56 @@ namespace dawn_native { namespace vulkan { const Texture* dstTexture = ToBackend(dstCopy.texture.Get()); VkImageCopy region; - - // TODO(jiawei.shao@intel.com): support 1D and 3D textures - ASSERT(srcTexture->GetDimension() == wgpu::TextureDimension::e2D && - dstTexture->GetDimension() == wgpu::TextureDimension::e2D); region.srcSubresource.aspectMask = VulkanAspectMask(aspect); region.srcSubresource.mipLevel = srcCopy.mipLevel; - region.srcSubresource.baseArrayLayer = srcCopy.origin.z; - region.srcSubresource.layerCount = copySize.depthOrArrayLayers; + region.dstSubresource.aspectMask = VulkanAspectMask(aspect); + region.dstSubresource.mipLevel = dstCopy.mipLevel; + + bool has3DTextureInCopy = false; region.srcOffset.x = srcCopy.origin.x; region.srcOffset.y = srcCopy.origin.y; - region.srcOffset.z = 0; - - region.dstSubresource.aspectMask = VulkanAspectMask(aspect); - region.dstSubresource.mipLevel = dstCopy.mipLevel; - region.dstSubresource.baseArrayLayer = dstCopy.origin.z; - region.dstSubresource.layerCount = copySize.depthOrArrayLayers; + switch (srcTexture->GetDimension()) { + case wgpu::TextureDimension::e2D: + region.srcSubresource.baseArrayLayer = srcCopy.origin.z; + region.srcSubresource.layerCount = copySize.depthOrArrayLayers; + region.srcOffset.z = 0; + break; + case wgpu::TextureDimension::e3D: + has3DTextureInCopy = true; + region.srcSubresource.baseArrayLayer = 0; + region.srcSubresource.layerCount = 1; + region.srcOffset.z = srcCopy.origin.z; + break; + case wgpu::TextureDimension::e1D: + // TODO(jiawei.shao@intel.com): support 1D textures + UNREACHABLE(); + } region.dstOffset.x = dstCopy.origin.x; region.dstOffset.y = dstCopy.origin.y; - region.dstOffset.z = 0; + switch (dstTexture->GetDimension()) { + case wgpu::TextureDimension::e2D: + region.dstSubresource.baseArrayLayer = dstCopy.origin.z; + region.dstSubresource.layerCount = copySize.depthOrArrayLayers; + region.dstOffset.z = 0; + break; + case wgpu::TextureDimension::e3D: + has3DTextureInCopy = true; + region.dstSubresource.baseArrayLayer = 0; + region.dstSubresource.layerCount = 1; + region.dstOffset.z = dstCopy.origin.z; + break; + case wgpu::TextureDimension::e1D: + // TODO(jiawei.shao@intel.com): support 1D textures + UNREACHABLE(); + } ASSERT(HasSameTextureCopyExtent(srcCopy, dstCopy, copySize)); Extent3D imageExtent = ComputeTextureCopyExtent(dstCopy, copySize); region.extent.width = imageExtent.width; region.extent.height = imageExtent.height; - region.extent.depth = 1; + region.extent.depth = has3DTextureInCopy ? copySize.depthOrArrayLayers : 1; return region; } @@ -526,7 +549,7 @@ namespace dawn_native { namespace vulkan { ComputeBufferImageCopyRegion(src, dst, copy->copySize); VkImageSubresourceLayers subresource = region.imageSubresource; - ASSERT(dst.texture->GetDimension() == wgpu::TextureDimension::e2D); + ASSERT(dst.texture->GetDimension() != wgpu::TextureDimension::e1D); SubresourceRange range = GetSubresourcesAffectedByCopy(copy->destination, copy->copySize); @@ -564,7 +587,7 @@ namespace dawn_native { namespace vulkan { VkBufferImageCopy region = ComputeBufferImageCopyRegion(dst, src, copy->copySize); - ASSERT(src.texture->GetDimension() == wgpu::TextureDimension::e2D); + ASSERT(src.texture->GetDimension() != wgpu::TextureDimension::e1D); SubresourceRange range = GetSubresourcesAffectedByCopy(copy->source, copy->copySize); diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp index 530b5ca11d..df3324fc62 100644 --- a/src/dawn_native/vulkan/DeviceVk.cpp +++ b/src/dawn_native/vulkan/DeviceVk.cpp @@ -650,7 +650,7 @@ namespace dawn_native { namespace vulkan { VkBufferImageCopy region = ComputeBufferImageCopyRegion(src, *dst, copySizePixels); VkImageSubresourceLayers subresource = region.imageSubresource; - ASSERT(dst->texture->GetDimension() == wgpu::TextureDimension::e2D); + ASSERT(dst->texture->GetDimension() != wgpu::TextureDimension::e1D); SubresourceRange range = GetSubresourcesAffectedByCopy(*dst, copySizePixels); if (IsCompleteSubresourceCopiedTo(dst->texture.Get(), copySizePixels, diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp index 90f85f39f2..c69fe272c3 100644 --- a/src/dawn_native/vulkan/TextureVk.cpp +++ b/src/dawn_native/vulkan/TextureVk.cpp @@ -986,9 +986,6 @@ namespace dawn_native { namespace vulkan { ASSERT(imageBarriers != nullptr); const Format& format = GetFormat(); - // This transitions assume it is a 2D texture - ASSERT(GetDimension() == wgpu::TextureDimension::e2D); - wgpu::TextureUsage allLastUsages = wgpu::TextureUsage::None; mSubresourceLastUsages.Update( range, [&](const SubresourceRange& range, wgpu::TextureUsage* lastUsage) { diff --git a/src/dawn_native/vulkan/UtilsVulkan.cpp b/src/dawn_native/vulkan/UtilsVulkan.cpp index 6167201df0..73753772a0 100644 --- a/src/dawn_native/vulkan/UtilsVulkan.cpp +++ b/src/dawn_native/vulkan/UtilsVulkan.cpp @@ -139,8 +139,22 @@ namespace dawn_native { namespace vulkan { break; } + case wgpu::TextureDimension::e3D: { + region.imageOffset.x = textureCopy.origin.x; + region.imageOffset.y = textureCopy.origin.y; + region.imageOffset.z = textureCopy.origin.z; + + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + + Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize); + region.imageExtent.width = imageExtent.width; + region.imageExtent.height = imageExtent.height; + region.imageExtent.depth = imageExtent.depthOrArrayLayers; + break; + } + case wgpu::TextureDimension::e1D: - case wgpu::TextureDimension::e3D: UNREACHABLE(); } diff --git a/src/tests/end2end/CopyTests.cpp b/src/tests/end2end/CopyTests.cpp index 3426a40e01..951b923086 100644 --- a/src/tests/end2end/CopyTests.cpp +++ b/src/tests/end2end/CopyTests.cpp @@ -968,9 +968,9 @@ TEST_P(CopyTests_T2B, Texture2DArrayRegionWithOffsetEvenRowsPerImage) { // Test that copying whole 3D texture in one texture-to-buffer-copy works. TEST_P(CopyTests_T2B, Texture3DFull) { - // TODO(yunchao.he@intel.com): implement 3D texture copy on Vulkan, Metal, OpenGL and OpenGLES + // TODO(yunchao.he@intel.com): implement 3D texture copy on Metal, OpenGL and OpenGLES // backend. - DAWN_SKIP_TEST_IF(IsVulkan() || IsMetal() || IsOpenGL() || IsOpenGLES()); + DAWN_SKIP_TEST_IF(IsMetal() || IsOpenGL() || IsOpenGLES()); constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; @@ -985,9 +985,9 @@ TEST_P(CopyTests_T2B, Texture3DFull) { // Test that copying a range of texture 3D depths in one texture-to-buffer-copy works. TEST_P(CopyTests_T2B, Texture3DSubRegion) { - // TODO(yunchao.he@intel.com): implement 3D texture copy on Vulkan, Metal, OpenGL and OpenGLES + // TODO(yunchao.he@intel.com): implement 3D texture copy on Metal, OpenGL and OpenGLES // backend. - DAWN_SKIP_TEST_IF(IsVulkan() || IsMetal() || IsOpenGL() || IsOpenGLES()); + DAWN_SKIP_TEST_IF(IsMetal() || IsOpenGL() || IsOpenGLES()); constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; @@ -1445,9 +1445,9 @@ TEST_P(CopyTests_B2T, Texture2DArrayRegionWithOffsetEvenRowsPerImage) { // Test that copying whole texture 3D in one buffer-to-texture-copy works. TEST_P(CopyTests_B2T, Texture3DFull) { - // TODO(yunchao.he@intel.com): implement 3D texture copy on Vulkan, Metal, OpenGL and OpenGLES + // TODO(yunchao.he@intel.com): implement 3D texture copy on Metal, OpenGL and OpenGLES // backend. - DAWN_SKIP_TEST_IF(IsVulkan() || IsMetal() || IsOpenGL() || IsOpenGLES()); + DAWN_SKIP_TEST_IF(IsMetal() || IsOpenGL() || IsOpenGLES()); constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; @@ -1462,9 +1462,9 @@ TEST_P(CopyTests_B2T, Texture3DFull) { // Test that copying a range of texture 3D Depths in one texture-to-buffer-copy works. TEST_P(CopyTests_B2T, Texture3DSubRegion) { - // TODO(yunchao.he@intel.com): implement 3D texture copy on Vulkan, Metal, OpenGL and OpenGLES + // TODO(yunchao.he@intel.com): implement 3D texture copy on Metal, OpenGL and OpenGLES // backend. - DAWN_SKIP_TEST_IF(IsVulkan() || IsMetal() || IsOpenGL() || IsOpenGLES()); + DAWN_SKIP_TEST_IF(IsMetal() || IsOpenGL() || IsOpenGLES()); constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128; @@ -1799,9 +1799,9 @@ TEST_P(CopyTests_T2T, CopyFromNonZeroMipLevelWithTexelBlockSizeLessThan4Bytes) { // Test that copying whole 3D texture in one texture-to-texture-copy works. TEST_P(CopyTests_T2T, Texture3DFull) { - // TODO(yunchao.he@intel.com): implement 3D texture copy on Vulkan, Metal, OpenGL and OpenGLES + // TODO(yunchao.he@intel.com): implement 3D texture copy, Metal, OpenGL and OpenGLES // backend. - DAWN_SKIP_TEST_IF(IsVulkan() || IsMetal() || IsOpenGL() || IsOpenGLES()); + DAWN_SKIP_TEST_IF(IsMetal() || IsOpenGL() || IsOpenGLES()); constexpr uint32_t kWidth = 256; constexpr uint32_t kHeight = 128;