Add buffer lazy initialization before resolve queries on D3D12

- Reomve buffer initialization at buffer creation in end2end tests,
and implement lazy initialization when resolving queries to buffer
on D3D12 backend.
- Add buffer lazy zero init tests for resolveQuerySet on D3D12.
- For other backends, buffer lazy initialization will be added when
its resolve method is implemented.

Bug: dawn:434
Change-Id: Ib91c004b37ca912135a1c2fbb53bbd16e2d4eac6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/28461
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Hao Li <hao.x.li@intel.com>
This commit is contained in:
Hao Li 2020-09-17 01:59:29 +00:00 committed by Commit Bot service account
parent 19b910d796
commit 6419bddd9b
3 changed files with 82 additions and 7 deletions

View File

@ -892,6 +892,12 @@ namespace dawn_native { namespace d3d12 {
QuerySet* querySet = ToBackend(cmd->querySet.Get()); QuerySet* querySet = ToBackend(cmd->querySet.Get());
Buffer* destination = ToBackend(cmd->destination.Get()); Buffer* destination = ToBackend(cmd->destination.Get());
DAWN_TRY(destination->EnsureDataInitializedAsDestination(
commandContext, cmd->destinationOffset,
cmd->queryCount * sizeof(uint64_t)));
destination->TrackUsageAndTransitionNow(commandContext,
wgpu::BufferUsage::CopyDst);
commandList->ResolveQueryData( commandList->ResolveQueryData(
querySet->GetQueryHeap(), D3D12QueryType(querySet->GetQueryType()), querySet->GetQueryHeap(), D3D12QueryType(querySet->GetQueryType()),
cmd->firstQuery, cmd->queryCount, destination->GetD3D12Resource(), cmd->firstQuery, cmd->queryCount, destination->GetD3D12Resource(),

View File

@ -44,6 +44,15 @@ namespace {
} // anonymous namespace } // anonymous namespace
class BufferZeroInitTest : public DawnTest { class BufferZeroInitTest : public DawnTest {
protected:
std::vector<const char*> GetRequiredExtensions() override {
std::vector<const char*> requiredExtensions = {};
if (SupportsExtensions({"timestamp_query"})) {
requiredExtensions.push_back("timestamp_query");
}
return requiredExtensions;
}
public: public:
wgpu::Buffer CreateBuffer(uint64_t size, wgpu::Buffer CreateBuffer(uint64_t size,
wgpu::BufferUsage usage, wgpu::BufferUsage usage,
@ -1160,6 +1169,72 @@ TEST_P(BufferZeroInitTest, IndirectBufferForDispatchIndirect) {
} }
} }
// Test the buffer will be lazily intialized correctly when its first use is in resolveQuerySet
TEST_P(BufferZeroInitTest, ResolveQuerySet) {
// Timestamp query is not supported on OpenGL
DAWN_SKIP_TEST_IF(IsOpenGL());
// TODO(hao.x.li@intel.com): Remove it after timestamp query is implementated on Vulkan and
// Metal
DAWN_SKIP_TEST_IF(IsVulkan() || IsMetal());
// Skip if timestamp extension is not supported on device
DAWN_SKIP_TEST_IF(!SupportsExtensions({"timestamp_query"}));
constexpr uint64_t kBufferSize = 16u;
constexpr wgpu::BufferUsage kBufferUsage =
wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::CopyDst;
wgpu::QuerySetDescriptor descriptor;
descriptor.count = 2u;
descriptor.type = wgpu::QueryType::Timestamp;
wgpu::QuerySet querySet = device.CreateQuerySet(&descriptor);
// Resolve data to the whole buffer doesn't need lazy initialization.
{
constexpr uint32_t kQueryCount = 2u;
constexpr uint64_t kDestinationOffset = 0u;
wgpu::Buffer destination = CreateBuffer(kBufferSize, kBufferUsage);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(querySet, 0);
encoder.WriteTimestamp(querySet, 1);
encoder.ResolveQuerySet(querySet, 0, kQueryCount, destination, kDestinationOffset);
wgpu::CommandBuffer commands = encoder.Finish();
EXPECT_LAZY_CLEAR(0u, queue.Submit(1, &commands));
}
// Resolve data to partial of the buffer needs lazy initialization.
// destinationOffset == 0 and destinationOffset + 8 * queryCount < kBufferSize
{
constexpr uint32_t kQueryCount = 1u;
constexpr uint64_t kDestinationOffset = 0u;
wgpu::Buffer destination = CreateBuffer(kBufferSize, kBufferUsage);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(querySet, 0);
encoder.ResolveQuerySet(querySet, 0, kQueryCount, destination, kDestinationOffset);
wgpu::CommandBuffer commands = encoder.Finish();
EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commands));
}
// destinationOffset > 0 and destinationOffset + 8 * queryCount <= kBufferSize
{
constexpr uint32_t kQueryCount = 1;
constexpr uint64_t kDestinationOffset = 8u;
wgpu::Buffer destination = CreateBuffer(kBufferSize, kBufferUsage);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.WriteTimestamp(querySet, 0);
encoder.ResolveQuerySet(querySet, 0, kQueryCount, destination, kDestinationOffset);
wgpu::CommandBuffer commands = encoder.Finish();
EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commands));
}
}
DAWN_INSTANTIATE_TEST(BufferZeroInitTest, DAWN_INSTANTIATE_TEST(BufferZeroInitTest,
D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"}), D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"}),
MetalBackend({"nonzero_clear_resources_on_creation_for_testing"}), MetalBackend({"nonzero_clear_resources_on_creation_for_testing"}),

View File

@ -28,13 +28,7 @@ class QueryTests : public DawnTest {
descriptor.size = size; descriptor.size = size;
descriptor.usage = wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::CopySrc | descriptor.usage = wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::CopySrc |
wgpu::BufferUsage::CopyDst; wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&descriptor); return device.CreateBuffer(&descriptor);
// Initialize the buffer values to 0.
std::vector<uint64_t> myData = {0, 0};
device.GetDefaultQueue().WriteBuffer(buffer, 0, myData.data(), size);
return buffer;
} }
}; };