Implement buffer lazy initialization before CopyBufferToTexture()
This patch adds the check and implementations of buffer lazy initialization before CopyBufferToTexture(). The support of buffer lazy initialization before CopyTextureToBuffer() is much more complicated than what we do for CopyBufferToTexture(), so we decide to put it in another CL instead of writing them together with CopyBufferToTexture(). BUG=dawn:414 TEST=dawn_end2end_tests Change-Id: I45fdcdde2c9a0dafff23623815fc35c877990ef1 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/25140 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
1233b66c90
commit
d0dd661f18
|
@ -663,6 +663,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
Buffer* buffer = ToBackend(copy->source.buffer.Get());
|
||||
Texture* texture = ToBackend(copy->destination.texture.Get());
|
||||
|
||||
DAWN_TRY(buffer->EnsureDataInitialized(commandContext));
|
||||
|
||||
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||
SubresourceRange subresources = {copy->destination.mipLevel, 1,
|
||||
copy->destination.origin.z,
|
||||
|
|
|
@ -601,6 +601,7 @@ namespace dawn_native { namespace metal {
|
|||
Buffer* buffer = ToBackend(src.buffer.Get());
|
||||
Texture* texture = ToBackend(dst.texture.Get());
|
||||
|
||||
buffer->EnsureDataInitialized(commandContext);
|
||||
EnsureDestinationTextureInitialized(texture, copy->destination, copy->copySize);
|
||||
|
||||
TextureBufferCopySplit splitCopies = ComputeTextureBufferCopySplit(
|
||||
|
|
|
@ -518,6 +518,8 @@ namespace dawn_native { namespace opengl {
|
|||
GLenum target = texture->GetGLTarget();
|
||||
const GLFormat& format = texture->GetGLFormat();
|
||||
|
||||
buffer->EnsureDataInitialized();
|
||||
|
||||
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||
SubresourceRange subresources = {dst.mipLevel, 1, dst.origin.z,
|
||||
copy->copySize.depth};
|
||||
|
|
|
@ -447,6 +447,8 @@ namespace dawn_native { namespace vulkan {
|
|||
auto& src = copy->source;
|
||||
auto& dst = copy->destination;
|
||||
|
||||
ToBackend(src.buffer)->EnsureDataInitialized(recordingContext);
|
||||
|
||||
VkBufferImageCopy region =
|
||||
ComputeBufferImageCopyRegion(src, dst, copy->copySize);
|
||||
VkImageSubresourceLayers subresource = region.imageSubresource;
|
||||
|
|
|
@ -59,6 +59,25 @@ class BufferZeroInitTest : public DawnTest {
|
|||
WaitABit();
|
||||
}
|
||||
}
|
||||
|
||||
wgpu::Texture CreateAndInitialize2DTexture(const wgpu::Extent3D& size,
|
||||
wgpu::TextureFormat format) {
|
||||
wgpu::TextureDescriptor descriptor;
|
||||
descriptor.size = size;
|
||||
descriptor.format = format;
|
||||
descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc |
|
||||
wgpu::TextureUsage::OutputAttachment;
|
||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
utils::ComboRenderPassDescriptor renderPassDescriptor({texture.CreateView()});
|
||||
wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&renderPassDescriptor);
|
||||
renderPass.EndPass();
|
||||
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
||||
queue.Submit(1, &commandBuffer);
|
||||
|
||||
return texture;
|
||||
}
|
||||
};
|
||||
|
||||
// Test that calling writeBuffer to overwrite the entire buffer doesn't need to lazily initialize
|
||||
|
@ -379,6 +398,69 @@ TEST_P(BufferZeroInitTest, MapAtCreation) {
|
|||
kExpectedData.size());
|
||||
}
|
||||
|
||||
// Test that the code path of CopyBufferToTexture clears the source buffer correctly when it is the
|
||||
// first use of the buffer.
|
||||
TEST_P(BufferZeroInitTest, CopyBufferToTexture) {
|
||||
constexpr wgpu::Extent3D kTextureSize = {16u, 16u, 1u};
|
||||
|
||||
constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
|
||||
|
||||
wgpu::Texture texture = CreateAndInitialize2DTexture(kTextureSize, kTextureFormat);
|
||||
const wgpu::TextureCopyView textureCopyView =
|
||||
utils::CreateTextureCopyView(texture, 0, {0, 0, 0});
|
||||
|
||||
const uint32_t requiredBufferSizeForCopy = utils::GetBytesInBufferTextureCopy(
|
||||
kTextureFormat, kTextureSize.width, kTextureBytesPerRowAlignment, kTextureSize.width,
|
||||
kTextureSize.depth);
|
||||
|
||||
constexpr wgpu::BufferUsage kBufferUsage =
|
||||
wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||
|
||||
// bufferOffset == 0
|
||||
{
|
||||
constexpr uint64_t kOffset = 0;
|
||||
const uint32_t totalBufferSize = requiredBufferSizeForCopy + kOffset;
|
||||
wgpu::BufferDescriptor bufferDescriptor;
|
||||
bufferDescriptor.size = totalBufferSize;
|
||||
bufferDescriptor.usage = kBufferUsage;
|
||||
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
|
||||
const wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
||||
buffer, kOffset, kTextureBytesPerRowAlignment, kTextureSize.height);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &kTextureSize);
|
||||
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
||||
EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commandBuffer));
|
||||
|
||||
std::vector<uint32_t> expectedValues(totalBufferSize / sizeof(uint32_t), 0);
|
||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedValues.data(), buffer, 0,
|
||||
totalBufferSize / sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// bufferOffset > 0
|
||||
{
|
||||
constexpr uint64_t kOffset = 8u;
|
||||
const uint32_t totalBufferSize = requiredBufferSizeForCopy + kOffset;
|
||||
wgpu::BufferDescriptor bufferDescriptor;
|
||||
bufferDescriptor.size = totalBufferSize;
|
||||
bufferDescriptor.usage = kBufferUsage;
|
||||
|
||||
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
|
||||
const wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(
|
||||
buffer, kOffset, kTextureBytesPerRowAlignment, kTextureSize.height);
|
||||
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &kTextureSize);
|
||||
wgpu::CommandBuffer commandBuffer = encoder.Finish();
|
||||
EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commandBuffer));
|
||||
|
||||
std::vector<uint32_t> expectedValues(totalBufferSize / sizeof(uint32_t), 0);
|
||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedValues.data(), buffer, 0,
|
||||
totalBufferSize / sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(BufferZeroInitTest,
|
||||
D3D12Backend({"nonzero_clear_resources_on_creation_for_testing",
|
||||
"lazy_clear_buffer_on_first_use"}),
|
||||
|
|
Loading…
Reference in New Issue