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:
parent
c7910d19fe
commit
086835f3ff
|
@ -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;
|
||||||
|
|
|
@ -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, ®ion);
|
||||||
®ion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue