Vulkan: Use dynamic uploader for temp buffer when clearing textures.

Use dynamic uploader so that we don't have to create a new buffer each
time we lazy clear.

Bug: dawn:145
Change-Id: I2d7a769532bd303fdabb7fc70051b70a1114cc07
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10760
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Natasha Lee <natlee@microsoft.com>
This commit is contained in:
Natasha Lee 2019-09-03 18:21:41 +00:00 committed by Commit Bot service account
parent c7910d19fe
commit 086835f3ff
3 changed files with 67 additions and 55 deletions

View File

@ -533,7 +533,11 @@ namespace dawn_native { namespace d3d12 {
uint32_t rowPitch = uint32_t rowPitch =
Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize, Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
kTextureRowPitchAlignment); kTextureRowPitchAlignment);
uint32_t bufferSize = rowPitch * (GetSize().height / GetFormat().blockHeight); uint64_t bufferSize64 = rowPitch * (GetSize().height / GetFormat().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 = nullptr; DynamicUploader* uploader = nullptr;
DAWN_TRY_ASSIGN(uploader, device->GetDynamicUploader()); DAWN_TRY_ASSIGN(uploader, device->GetDynamicUploader());
UploadHandle uploadHandle; UploadHandle uploadHandle;

View File

@ -14,12 +14,17 @@
#include "dawn_native/vulkan/TextureVk.h" #include "dawn_native/vulkan/TextureVk.h"
#include "common/Assert.h"
#include "common/Math.h"
#include "dawn_native/DynamicUploader.h"
#include "dawn_native/Error.h"
#include "dawn_native/VulkanBackend.h" #include "dawn_native/VulkanBackend.h"
#include "dawn_native/vulkan/AdapterVk.h" #include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/BufferVk.h" #include "dawn_native/vulkan/BufferVk.h"
#include "dawn_native/vulkan/CommandRecordingContext.h" #include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/DeviceVk.h" #include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h" #include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/StagingBufferVk.h"
#include "dawn_native/vulkan/UtilsVulkan.h" #include "dawn_native/vulkan/UtilsVulkan.h"
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
@ -442,8 +447,9 @@ namespace dawn_native { namespace vulkan {
ASSERT(false); ASSERT(false);
} }
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) { if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
ClearTexture(ToBackend(GetDevice())->GetPendingRecordingContext(), 0, GetNumMipLevels(), device->ConsumedError(ClearTexture(ToBackend(GetDevice())->GetPendingRecordingContext(),
0, GetArrayLayers(), TextureBase::ClearValue::NonZero); 0, GetNumMipLevels(), 0, GetArrayLayers(),
TextureBase::ClearValue::NonZero));
} }
} }
@ -639,12 +645,13 @@ namespace dawn_native { namespace vulkan {
mLastExternalState = mExternalState; mLastExternalState = mExternalState;
} }
void Texture::ClearTexture(CommandRecordingContext* recordingContext, MaybeError Texture::ClearTexture(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
uint32_t layerCount, uint32_t layerCount,
TextureBase::ClearValue clearValue) { TextureBase::ClearValue clearValue) {
Device* device = ToBackend(GetDevice());
VkImageSubresourceRange range = {}; VkImageSubresourceRange range = {};
range.aspectMask = GetVkAspectMask(); range.aspectMask = GetVkAspectMask();
range.baseMipLevel = baseMipLevel; range.baseMipLevel = baseMipLevel;
@ -654,44 +661,45 @@ namespace dawn_native { namespace vulkan {
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1; uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
TransitionUsageNow(recordingContext, dawn::TextureUsage::CopyDst); TransitionUsageNow(recordingContext, dawn::TextureUsage::CopyDst);
if (GetFormat().isRenderable) {
if (GetFormat().HasDepthOrStencil()) { if (GetFormat().HasDepthOrStencil()) {
VkClearDepthStencilValue clearDepthStencilValue[1]; VkClearDepthStencilValue clearDepthStencilValue[1];
clearDepthStencilValue[0].depth = clearColor; clearDepthStencilValue[0].depth = clearColor;
clearDepthStencilValue[0].stencil = clearColor; clearDepthStencilValue[0].stencil = clearColor;
ToBackend(GetDevice()) device->fn.CmdClearDepthStencilImage(recordingContext->commandBuffer, GetHandle(),
->fn.CmdClearDepthStencilImage(recordingContext->commandBuffer, GetHandle(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
clearDepthStencilValue, 1, &range); clearDepthStencilValue, 1, &range);
} else if (GetFormat().isRenderable) { } else {
VkClearColorValue clearColorValue = {{clearColor, clearColor, clearColor, clearColor}}; VkClearColorValue clearColorValue = {
ToBackend(GetDevice()) {clearColor, clearColor, clearColor, clearColor}};
->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(), device->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColorValue, 1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
&range); &clearColorValue, 1, &range);
}
} else { } else {
// TODO(natlee@microsoft.com): test compressed textures are cleared // TODO(natlee@microsoft.com): test compressed textures are cleared
// create temp buffer with clear color to copy to the texture image // create temp buffer with clear color to copy to the texture image
dawn_native::vulkan::Device* device = uint32_t rowPitch =
reinterpret_cast<dawn_native::vulkan::Device*>(GetDevice()); Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
dawn_native::BufferDescriptor descriptor; kTextureRowPitchAlignment);
descriptor.size = (GetSize().width / GetFormat().blockWidth) * uint64_t bufferSize64 = rowPitch * (GetSize().height / GetFormat().blockHeight);
(GetSize().height / GetFormat().blockHeight) * if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
GetFormat().blockByteSize; return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
descriptor.nextInChain = nullptr; }
descriptor.usage = dawn::BufferUsage::CopySrc | dawn::BufferUsage::MapWrite; uint32_t bufferSize = static_cast<uint32_t>(bufferSize64);
std::unique_ptr<Buffer> srcBuffer = DynamicUploader* uploader = nullptr;
std::make_unique<dawn_native::vulkan::Buffer>(device, &descriptor); DAWN_TRY_ASSIGN(uploader, device->GetDynamicUploader());
uint8_t* clearBuffer = nullptr; UploadHandle uploadHandle;
device->ConsumedError(srcBuffer->MapAtCreation(&clearBuffer)); DAWN_TRY_ASSIGN(uploadHandle, uploader->Allocate(bufferSize));
std::fill(reinterpret_cast<uint32_t*>(clearBuffer), std::fill(reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer),
reinterpret_cast<uint32_t*>(clearBuffer + descriptor.size), clearColor); reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer + bufferSize),
clearColor);
// compute the buffer image copy to set the clear region of entire texture // compute the buffer image copy to set the clear region of entire texture
dawn_native::BufferCopy bufferCopy; dawn_native::BufferCopy bufferCopy;
bufferCopy.buffer = srcBuffer.get();
bufferCopy.imageHeight = 0; bufferCopy.imageHeight = 0;
bufferCopy.offset = 0; bufferCopy.offset = uploadHandle.startOffset;
bufferCopy.rowPitch = 0; bufferCopy.rowPitch = rowPitch;
dawn_native::TextureCopy textureCopy; dawn_native::TextureCopy textureCopy;
textureCopy.texture = this; textureCopy.texture = this;
@ -705,18 +713,17 @@ namespace dawn_native { namespace vulkan {
ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize); ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize);
// copy the clear buffer to the texture image // copy the clear buffer to the texture image
srcBuffer->TransitionUsageNow(recordingContext, dawn::BufferUsage::CopySrc); device->fn.CmdCopyBufferToImage(
ToBackend(GetDevice()) recordingContext->commandBuffer,
->fn.CmdCopyBufferToImage(recordingContext->commandBuffer, srcBuffer->GetHandle(), ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(), GetHandle(),
GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
&region);
} }
if (clearValue == TextureBase::ClearValue::Zero) { if (clearValue == TextureBase::ClearValue::Zero) {
SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
layerCount); layerCount);
GetDevice()->IncrementLazyClearCountForTesting(); device->IncrementLazyClearCountForTesting();
} }
return {};
} }
void Texture::EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext, void Texture::EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
@ -737,8 +744,9 @@ namespace dawn_native { namespace vulkan {
// If subresource has not been initialized, clear it to black as it could contain dirty // If subresource has not been initialized, clear it to black as it could contain dirty
// bits from recycled memory // bits from recycled memory
ClearTexture(recordingContext, baseMipLevel, levelCount, baseArrayLayer, layerCount, GetDevice()->ConsumedError(ClearTexture(recordingContext, baseMipLevel, levelCount,
TextureBase::ClearValue::Zero); baseArrayLayer, layerCount,
TextureBase::ClearValue::Zero));
} }
} }

View File

@ -71,7 +71,7 @@ namespace dawn_native { namespace vulkan {
private: private:
void DestroyImpl() override; void DestroyImpl() override;
void ClearTexture(CommandRecordingContext* recordingContext, MaybeError ClearTexture(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,