diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 4efb9cfb9a..fb7e08e49b 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -892,6 +892,12 @@ namespace dawn_native { namespace d3d12 { QuerySet* querySet = ToBackend(cmd->querySet.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( querySet->GetQueryHeap(), D3D12QueryType(querySet->GetQueryType()), cmd->firstQuery, cmd->queryCount, destination->GetD3D12Resource(), diff --git a/src/tests/end2end/BufferZeroInitTests.cpp b/src/tests/end2end/BufferZeroInitTests.cpp index 807f4a2dfd..abb181c9e8 100644 --- a/src/tests/end2end/BufferZeroInitTests.cpp +++ b/src/tests/end2end/BufferZeroInitTests.cpp @@ -44,6 +44,15 @@ namespace { } // anonymous namespace class BufferZeroInitTest : public DawnTest { + protected: + std::vector GetRequiredExtensions() override { + std::vector requiredExtensions = {}; + if (SupportsExtensions({"timestamp_query"})) { + requiredExtensions.push_back("timestamp_query"); + } + return requiredExtensions; + } + public: wgpu::Buffer CreateBuffer(uint64_t size, 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, D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"}), MetalBackend({"nonzero_clear_resources_on_creation_for_testing"}), diff --git a/src/tests/end2end/QueryTests.cpp b/src/tests/end2end/QueryTests.cpp index 47ccdd06f5..00522afde2 100644 --- a/src/tests/end2end/QueryTests.cpp +++ b/src/tests/end2end/QueryTests.cpp @@ -28,13 +28,7 @@ class QueryTests : public DawnTest { descriptor.size = size; descriptor.usage = wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; - wgpu::Buffer buffer = device.CreateBuffer(&descriptor); - - // Initialize the buffer values to 0. - std::vector myData = {0, 0}; - device.GetDefaultQueue().WriteBuffer(buffer, 0, myData.data(), size); - - return buffer; + return device.CreateBuffer(&descriptor); } };