diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp index 6f2fc9e94e..90fae81909 100644 --- a/src/dawn_native/vulkan/TextureVk.cpp +++ b/src/dawn_native/vulkan/TextureVk.cpp @@ -677,30 +677,45 @@ namespace dawn_native { namespace vulkan { uint32_t layerCount, TextureBase::ClearValue clearValue) { Device* device = ToBackend(GetDevice()); - VkImageSubresourceRange range = {}; - range.aspectMask = GetVkAspectMask(); - range.baseMipLevel = baseMipLevel; - range.levelCount = levelCount; - range.baseArrayLayer = baseArrayLayer; - range.layerCount = layerCount; + uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1; float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f; TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst); if (GetFormat().isRenderable) { - if (GetFormat().HasDepthOrStencil()) { - 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, &range); - } else { - VkClearColorValue clearColorValue = { - {fClearColor, fClearColor, fClearColor, fClearColor}}; - device->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - &clearColorValue, 1, &range); + VkImageSubresourceRange range = {}; + range.aspectMask = GetVkAspectMask(); + range.levelCount = 1; + range.layerCount = 1; + + for (uint32_t level = baseMipLevel; level < baseMipLevel + levelCount; ++level) { + range.baseMipLevel = level; + for (uint32_t layer = baseArrayLayer; layer < baseArrayLayer + layerCount; + ++layer) { + if (clearValue == TextureBase::ClearValue::Zero && + IsSubresourceContentInitialized(level, 1, layer, 1)) { + // Skip lazy clears if already initialized. + continue; + } + + range.baseArrayLayer = layer; + + if (GetFormat().HasDepthOrStencil()) { + 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, &range); + } else { + VkClearColorValue clearColorValue = { + {fClearColor, fClearColor, fClearColor, fClearColor}}; + device->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &clearColorValue, 1, &range); + } + } } } else { // TODO(natlee@microsoft.com): test compressed textures are cleared @@ -725,11 +740,17 @@ namespace dawn_native { namespace vulkan { bufferCopy.offset = uploadHandle.startOffset; bufferCopy.rowPitch = rowPitch; - Extent3D copySize = {GetSize().width, GetSize().height, 1}; - for (uint32_t level = baseMipLevel; level < baseMipLevel + levelCount; ++level) { + Extent3D copySize = GetMipLevelVirtualSize(level); + for (uint32_t layer = baseArrayLayer; layer < baseArrayLayer + layerCount; ++layer) { + if (clearValue == TextureBase::ClearValue::Zero && + IsSubresourceContentInitialized(level, 1, layer, 1)) { + // Skip lazy clears if already initialized. + continue; + } + dawn_native::TextureCopy textureCopy; textureCopy.texture = this; textureCopy.origin = {0, 0, 0}; diff --git a/src/tests/end2end/NonzeroTextureCreationTests.cpp b/src/tests/end2end/NonzeroTextureCreationTests.cpp index 7f384cc121..605b150d63 100644 --- a/src/tests/end2end/NonzeroTextureCreationTests.cpp +++ b/src/tests/end2end/NonzeroTextureCreationTests.cpp @@ -195,7 +195,7 @@ TEST_P(NonzeroTextureCreationTests, NonRenderableTextureClearWithMultiArrayLayer // Test that all subresources of a renderable texture are filled because the toggle is enabled. TEST_P(NonzeroTextureCreationTests, AllSubresourcesFilled) { // TODO(crbug.com/dawn/145): Implement on other platforms. - DAWN_SKIP_TEST_IF(!IsMetal() && !IsD3D12()); + DAWN_SKIP_TEST_IF(!IsMetal() && !IsD3D12() && !IsVulkan()); wgpu::TextureDescriptor baseDescriptor; baseDescriptor.dimension = wgpu::TextureDimension::e2D; @@ -251,7 +251,7 @@ TEST_P(NonzeroTextureCreationTests, AllSubresourcesFilled) { // Test that all subresources of a nonrenderable texture are filled because the toggle is enabled. TEST_P(NonzeroTextureCreationTests, NonRenderableAllSubresourcesFilled) { // TODO(crbug.com/dawn/145): Implement on other platforms. - DAWN_SKIP_TEST_IF(!IsMetal() && !IsD3D12()); + DAWN_SKIP_TEST_IF(!IsMetal() && !IsD3D12() && !IsVulkan()); wgpu::TextureDescriptor baseDescriptor; baseDescriptor.dimension = wgpu::TextureDimension::e2D; diff --git a/src/tests/end2end/TextureZeroInitTests.cpp b/src/tests/end2end/TextureZeroInitTests.cpp index 0ceaed5195..a7d0664fb7 100644 --- a/src/tests/end2end/TextureZeroInitTests.cpp +++ b/src/tests/end2end/TextureZeroInitTests.cpp @@ -872,7 +872,7 @@ TEST_P(TextureZeroInitTest, RenderingLoadingDepthStencilStoreOpClear) { // uninitialized mip does not clear the initialized mip. TEST_P(TextureZeroInitTest, PreservesInitializedMip) { // TODO(crbug.com/dawn/145): Fix this on other backends - DAWN_SKIP_TEST_IF(!IsMetal() && !IsD3D12()); + DAWN_SKIP_TEST_IF(!IsMetal() && !IsD3D12() && !IsVulkan()); wgpu::TextureDescriptor sampleTextureDescriptor = CreateTextureDescriptor( 2, 1, @@ -953,7 +953,7 @@ TEST_P(TextureZeroInitTest, PreservesInitializedMip) { // the uninitialized layer does not clear the initialized layer. TEST_P(TextureZeroInitTest, PreservesInitializedArrayLayer) { // TODO(crbug.com/dawn/145): Fix this on other backends - DAWN_SKIP_TEST_IF(!IsMetal() && !IsD3D12()); + DAWN_SKIP_TEST_IF(!IsMetal() && !IsD3D12() && !IsVulkan()); wgpu::TextureDescriptor sampleTextureDescriptor = CreateTextureDescriptor( 1, 2,