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>
This commit is contained in:
Austin Eng 2020-09-02 21:03:29 +00:00 committed by Commit Bot service account
parent ea82272fd6
commit a1758eef07
2 changed files with 64 additions and 95 deletions

View File

@ -893,11 +893,13 @@ namespace dawn_native { namespace vulkan {
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;
@ -928,78 +930,43 @@ namespace dawn_native { namespace vulkan {
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);
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 = {
{fClearColor, fClearColor, fClearColor, fClearColor}};
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);
}
}
}
} 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) {
if (clearValue == TextureBase::ClearValue::Zero &&
IsSubresourceContentInitialized(
SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
// Skip lazy clears if already initialized.
continue;
}
ASSERT(GetFormat().aspects == Aspect::Color);
dawn_native::TextureCopy textureCopy;
textureCopy.texture = this;
textureCopy.origin = {0, 0, layer};
textureCopy.mipLevel = level;
textureCopy.aspect = GetFormat().aspects;
VkBufferImageCopy region =
ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize);
// 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 (clearValue == TextureBase::ClearValue::Zero) {
SetIsSubresourceContentInitialized(true, range);
device->IncrementLazyClearCountForTesting();

View File

@ -143,7 +143,8 @@ TEST_P(NonzeroTextureCreationTests, NonrenderableTextureFormat) {
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 @@ TEST_P(NonzeroTextureCreationTests, NonRenderableTextureClearWithMultiArrayLayer
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 @@ TEST_P(NonzeroTextureCreationTests, NonRenderableAllSubresourcesFilled) {
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;