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:
parent
ea82272fd6
commit
a1758eef07
|
@ -893,113 +893,80 @@ namespace dawn_native { namespace vulkan {
|
||||||
TextureBase::ClearValue clearValue) {
|
TextureBase::ClearValue clearValue) {
|
||||||
Device* device = ToBackend(GetDevice());
|
Device* device = ToBackend(GetDevice());
|
||||||
|
|
||||||
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
|
const bool isZero = clearValue == TextureBase::ClearValue::Zero;
|
||||||
float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f;
|
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);
|
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;
|
VkImageSubresourceRange imageRange = {};
|
||||||
++level) {
|
imageRange.levelCount = 1;
|
||||||
imageRange.baseMipLevel = level;
|
imageRange.layerCount = 1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aspects == Aspect::None) {
|
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
|
||||||
continue;
|
++level) {
|
||||||
}
|
imageRange.baseMipLevel = level;
|
||||||
|
for (uint32_t layer = range.baseArrayLayer;
|
||||||
imageRange.aspectMask = VulkanAspectMask(aspects);
|
layer < range.baseArrayLayer + range.layerCount; ++layer) {
|
||||||
imageRange.baseArrayLayer = layer;
|
Aspect aspects = Aspect::None;
|
||||||
|
for (Aspect aspect : IterateEnumMask(range.aspects)) {
|
||||||
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) {
|
|
||||||
if (clearValue == TextureBase::ClearValue::Zero &&
|
if (clearValue == TextureBase::ClearValue::Zero &&
|
||||||
IsSubresourceContentInitialized(
|
IsSubresourceContentInitialized(
|
||||||
SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
|
SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
|
||||||
// Skip lazy clears if already initialized.
|
// Skip lazy clears if already initialized.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
aspects |= aspect;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(GetFormat().aspects == Aspect::Color);
|
if (aspects == Aspect::None) {
|
||||||
dawn_native::TextureCopy textureCopy;
|
continue;
|
||||||
textureCopy.texture = this;
|
}
|
||||||
textureCopy.origin = {0, 0, layer};
|
|
||||||
textureCopy.mipLevel = level;
|
|
||||||
textureCopy.aspect = GetFormat().aspects;
|
|
||||||
|
|
||||||
VkBufferImageCopy region =
|
imageRange.aspectMask = VulkanAspectMask(aspects);
|
||||||
ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize);
|
imageRange.baseArrayLayer = layer;
|
||||||
|
|
||||||
// copy the clear buffer to the texture image
|
if (aspects & (Aspect::Depth | Aspect::Stencil)) {
|
||||||
device->fn.CmdCopyBufferToImage(
|
VkClearDepthStencilValue clearDepthStencilValue[1];
|
||||||
recordingContext->commandBuffer,
|
clearDepthStencilValue[0].depth = fClearColor;
|
||||||
ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(), GetHandle(),
|
clearDepthStencilValue[0].stencil = uClearColor;
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
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) {
|
if (clearValue == TextureBase::ClearValue::Zero) {
|
||||||
SetIsSubresourceContentInitialized(true, range);
|
SetIsSubresourceContentInitialized(true, range);
|
||||||
device->IncrementLazyClearCountForTesting();
|
device->IncrementLazyClearCountForTesting();
|
||||||
|
|
|
@ -143,7 +143,8 @@ TEST_P(NonzeroTextureCreationTests, NonrenderableTextureFormat) {
|
||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
queue.Submit(1, &commands);
|
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);
|
EXPECT_BUFFER_U32_RANGE_EQ(expected.data(), bufferDst, 0, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +177,8 @@ TEST_P(NonzeroTextureCreationTests, NonRenderableTextureClearWithMultiArrayLayer
|
||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
queue.Submit(1, &commands);
|
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);
|
EXPECT_BUFFER_U32_RANGE_EQ(expected.data(), bufferDst, 0, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +246,7 @@ TEST_P(NonzeroTextureCreationTests, NonRenderableAllSubresourcesFilled) {
|
||||||
baseDescriptor.mipLevelCount = 1;
|
baseDescriptor.mipLevelCount = 1;
|
||||||
baseDescriptor.usage = wgpu::TextureUsage::CopySrc;
|
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;
|
wgpu::TextureDescriptor descriptor = baseDescriptor;
|
||||||
|
|
Loading…
Reference in New Issue