Cleanup: always clear Vulkan textures with vkCmdClear*Image

Previously, this code path was gated on whether or not the texture
format is renderable. This should not be the case as this Vulkan
command only requires the texture to have TRANSFER_DST.

Bug: dawn:145
Change-Id: Ifd8f75a70477a8d159c04d1180247cd076c767bc
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/27941
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 83bef81..d234b23 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -893,113 +893,80 @@
                                      TextureBase::ClearValue clearValue) {
         Device* device = ToBackend(GetDevice());
 
-        uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
-        float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f;
+        const bool isZero = clearValue == TextureBase::ClearValue::Zero;
+        uint32_t uClearColor = isZero ? 0 : 1;
+        int32_t sClearColor = isZero ? 0 : 1;
+        float fClearColor = isZero ? 0.f : 1.f;
 
         TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst, range);
-        if (GetFormat().isRenderable) {
-            VkImageSubresourceRange imageRange = {};
-            imageRange.levelCount = 1;
-            imageRange.layerCount = 1;
 
-            for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
-                 ++level) {
-                imageRange.baseMipLevel = level;
-                for (uint32_t layer = range.baseArrayLayer;
-                     layer < range.baseArrayLayer + range.layerCount; ++layer) {
-                    Aspect aspects = Aspect::None;
-                    for (Aspect aspect : IterateEnumMask(range.aspects)) {
-                        if (clearValue == TextureBase::ClearValue::Zero &&
-                            IsSubresourceContentInitialized(
-                                SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
-                            // Skip lazy clears if already initialized.
-                            continue;
-                        }
-                        aspects |= aspect;
-                    }
+        VkImageSubresourceRange imageRange = {};
+        imageRange.levelCount = 1;
+        imageRange.layerCount = 1;
 
-                    if (aspects == Aspect::None) {
-                        continue;
-                    }
-
-                    imageRange.aspectMask = VulkanAspectMask(aspects);
-                    imageRange.baseArrayLayer = layer;
-
-                    if (aspects & (Aspect::Depth | Aspect::Stencil)) {
-                        VkClearDepthStencilValue clearDepthStencilValue[1];
-                        clearDepthStencilValue[0].depth = fClearColor;
-                        clearDepthStencilValue[0].stencil = clearColor;
-                        device->fn.CmdClearDepthStencilImage(
-                            recordingContext->commandBuffer, GetHandle(),
-                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clearDepthStencilValue, 1,
-                            &imageRange);
-                    } else {
-                        ASSERT(aspects == Aspect::Color);
-                        VkClearColorValue clearColorValue = {
-                            {fClearColor, fClearColor, fClearColor, fClearColor}};
-                        device->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(),
-                                                      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                                      &clearColorValue, 1, &imageRange);
-                    }
-                }
-            }
-        } else {
-            // create temp buffer with clear color to copy to the texture image
-            const TexelBlockInfo& blockInfo =
-                GetFormat().GetTexelBlockInfo(wgpu::TextureAspect::All);
-            uint32_t bytesPerRow =
-                Align((GetWidth() / blockInfo.blockWidth) * blockInfo.blockByteSize,
-                      kTextureBytesPerRowAlignment);
-            uint64_t bufferSize64 = bytesPerRow * (GetHeight() / blockInfo.blockHeight);
-            if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
-                return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
-            }
-            uint32_t bufferSize = static_cast<uint32_t>(bufferSize64);
-            DynamicUploader* uploader = device->GetDynamicUploader();
-            UploadHandle uploadHandle;
-            DAWN_TRY_ASSIGN(uploadHandle,
-                            uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
-                                               blockInfo.blockByteSize));
-            memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
-
-            // compute the buffer image copy to set the clear region of entire texture
-            dawn_native::BufferCopy bufferCopy;
-            bufferCopy.rowsPerImage = 0;
-            bufferCopy.offset = uploadHandle.startOffset;
-            bufferCopy.bytesPerRow = bytesPerRow;
-
-            ASSERT(range.aspects == Aspect::Color);
-            for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
-                 ++level) {
-                Extent3D copySize = GetMipLevelVirtualSize(level);
-
-                for (uint32_t layer = range.baseArrayLayer;
-                     layer < range.baseArrayLayer + range.layerCount; ++layer) {
+        for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
+             ++level) {
+            imageRange.baseMipLevel = level;
+            for (uint32_t layer = range.baseArrayLayer;
+                 layer < range.baseArrayLayer + range.layerCount; ++layer) {
+                Aspect aspects = Aspect::None;
+                for (Aspect aspect : IterateEnumMask(range.aspects)) {
                     if (clearValue == TextureBase::ClearValue::Zero &&
                         IsSubresourceContentInitialized(
-                            SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
+                            SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
                         // Skip lazy clears if already initialized.
                         continue;
                     }
+                    aspects |= aspect;
+                }
 
-                    ASSERT(GetFormat().aspects == Aspect::Color);
-                    dawn_native::TextureCopy textureCopy;
-                    textureCopy.texture = this;
-                    textureCopy.origin = {0, 0, layer};
-                    textureCopy.mipLevel = level;
-                    textureCopy.aspect = GetFormat().aspects;
+                if (aspects == Aspect::None) {
+                    continue;
+                }
 
-                    VkBufferImageCopy region =
-                        ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize);
+                imageRange.aspectMask = VulkanAspectMask(aspects);
+                imageRange.baseArrayLayer = layer;
 
-                    // copy the clear buffer to the texture image
-                    device->fn.CmdCopyBufferToImage(
-                        recordingContext->commandBuffer,
-                        ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(), GetHandle(),
-                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+                if (aspects & (Aspect::Depth | Aspect::Stencil)) {
+                    VkClearDepthStencilValue clearDepthStencilValue[1];
+                    clearDepthStencilValue[0].depth = fClearColor;
+                    clearDepthStencilValue[0].stencil = uClearColor;
+                    device->fn.CmdClearDepthStencilImage(recordingContext->commandBuffer,
+                                                         GetHandle(),
+                                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                                         clearDepthStencilValue, 1, &imageRange);
+                } else {
+                    ASSERT(aspects == Aspect::Color);
+                    VkClearColorValue clearColorValue;
+                    switch (GetFormat().type) {
+                        case Format::Type::Float:
+                            clearColorValue.float32[0] = fClearColor;
+                            clearColorValue.float32[1] = fClearColor;
+                            clearColorValue.float32[2] = fClearColor;
+                            clearColorValue.float32[3] = fClearColor;
+                            break;
+                        case Format::Type::Sint:
+                            clearColorValue.int32[0] = sClearColor;
+                            clearColorValue.int32[1] = sClearColor;
+                            clearColorValue.int32[2] = sClearColor;
+                            clearColorValue.int32[3] = sClearColor;
+                            break;
+                        case Format::Type::Uint:
+                            clearColorValue.uint32[0] = uClearColor;
+                            clearColorValue.uint32[1] = uClearColor;
+                            clearColorValue.uint32[2] = uClearColor;
+                            clearColorValue.uint32[3] = uClearColor;
+                            break;
+                        default:
+                            UNREACHABLE();
+                    }
+                    device->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(),
+                                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                                  &clearColorValue, 1, &imageRange);
                 }
             }
         }
+
         if (clearValue == TextureBase::ClearValue::Zero) {
             SetIsSubresourceContentInitialized(true, range);
             device->IncrementLazyClearCountForTesting();
diff --git a/src/tests/end2end/NonzeroTextureCreationTests.cpp b/src/tests/end2end/NonzeroTextureCreationTests.cpp
index c5b62b3..eba13f3 100644
--- a/src/tests/end2end/NonzeroTextureCreationTests.cpp
+++ b/src/tests/end2end/NonzeroTextureCreationTests.cpp
@@ -143,7 +143,8 @@
     wgpu::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
-    std::vector<uint32_t> expected(bufferSize, 0x01010101);
+    uint32_t expectedBytes = IsVulkan() ? 0x7F7F7F7F : 0x01010101;
+    std::vector<uint32_t> expected(bufferSize, expectedBytes);
     EXPECT_BUFFER_U32_RANGE_EQ(expected.data(), bufferDst, 0, 8);
 }
 
@@ -176,7 +177,8 @@
     wgpu::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
-    std::vector<uint32_t> expected(bufferSize, 0x01010101);
+    uint32_t expectedBytes = IsVulkan() ? 0x7F7F7F7F : 0x01010101;
+    std::vector<uint32_t> expected(bufferSize, expectedBytes);
     EXPECT_BUFFER_U32_RANGE_EQ(expected.data(), bufferDst, 0, 8);
 }
 
@@ -244,7 +246,7 @@
     baseDescriptor.mipLevelCount = 1;
     baseDescriptor.usage = wgpu::TextureUsage::CopySrc;
 
-    RGBA8 filled(1, 1, 1, 1);
+    RGBA8 filled = IsVulkan() ? RGBA8(127, 127, 127, 127) : RGBA8(1, 1, 1, 1);
 
     {
         wgpu::TextureDescriptor descriptor = baseDescriptor;