Query API: QuerySet on Vulkan
- Implement QuerySet on Vulkan backend.
- Enable end2end tests on Vulkan. The timestamp tests will be enabled
in following CL which implement timestamp query.
Bug: dawn:434
Change-Id: I7ee04380c5f6b5af561cc23e28637dcae70bc7b9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/26360
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Hao Li <hao.x.li@intel.com>
diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn
index 0633915..cecfc1e 100644
--- a/src/dawn_native/BUILD.gn
+++ b/src/dawn_native/BUILD.gn
@@ -499,6 +499,8 @@
"vulkan/NativeSwapChainImplVk.h",
"vulkan/PipelineLayoutVk.cpp",
"vulkan/PipelineLayoutVk.h",
+ "vulkan/QuerySetVk.cpp",
+ "vulkan/QuerySetVk.h",
"vulkan/QueueVk.cpp",
"vulkan/QueueVk.h",
"vulkan/RenderPassCache.cpp",
diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt
index c7f0808..afac9c5 100644
--- a/src/dawn_native/CMakeLists.txt
+++ b/src/dawn_native/CMakeLists.txt
@@ -396,6 +396,8 @@
"vulkan/NativeSwapChainImplVk.h"
"vulkan/PipelineLayoutVk.cpp"
"vulkan/PipelineLayoutVk.h"
+ "vulkan/QuerySetVk.cpp"
+ "vulkan/QuerySetVk.h"
"vulkan/QueueVk.cpp"
"vulkan/QueueVk.h"
"vulkan/RenderPassCache.cpp"
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 818af70..01ba55c 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -28,6 +28,7 @@
#include "dawn_native/vulkan/ComputePipelineVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/PipelineLayoutVk.h"
+#include "dawn_native/vulkan/QuerySetVk.h"
#include "dawn_native/vulkan/QueueVk.h"
#include "dawn_native/vulkan/RenderPassCache.h"
#include "dawn_native/vulkan/RenderPipelineVk.h"
@@ -125,7 +126,7 @@
return PipelineLayout::Create(this, descriptor);
}
ResultOrError<QuerySetBase*> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) {
- return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation");
+ return QuerySet::Create(this, descriptor);
}
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
@@ -318,6 +319,12 @@
usedKnobs.features.textureCompressionBC = VK_TRUE;
}
+ if (IsExtensionEnabled(Extension::PipelineStatisticsQuery)) {
+ ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.pipelineStatisticsQuery ==
+ VK_TRUE);
+ usedKnobs.features.pipelineStatisticsQuery = VK_TRUE;
+ }
+
if (IsExtensionEnabled(Extension::ShaderFloat16)) {
const VulkanDeviceInfo& deviceInfo = ToBackend(GetAdapter())->GetDeviceInfo();
ASSERT(deviceInfo.HasExt(DeviceExt::ShaderFloat16Int8) &&
diff --git a/src/dawn_native/vulkan/FencedDeleter.cpp b/src/dawn_native/vulkan/FencedDeleter.cpp
index 388eb93..42a4237 100644
--- a/src/dawn_native/vulkan/FencedDeleter.cpp
+++ b/src/dawn_native/vulkan/FencedDeleter.cpp
@@ -30,6 +30,7 @@
ASSERT(mMemoriesToDelete.Empty());
ASSERT(mPipelinesToDelete.Empty());
ASSERT(mPipelineLayoutsToDelete.Empty());
+ ASSERT(mQueryPoolsToDelete.Empty());
ASSERT(mRenderPassesToDelete.Empty());
ASSERT(mSamplersToDelete.Empty());
ASSERT(mSemaphoresToDelete.Empty());
@@ -70,6 +71,10 @@
mPipelineLayoutsToDelete.Enqueue(layout, mDevice->GetPendingCommandSerial());
}
+ void FencedDeleter::DeleteWhenUnused(VkQueryPool querypool) {
+ mQueryPoolsToDelete.Enqueue(querypool, mDevice->GetPendingCommandSerial());
+ }
+
void FencedDeleter::DeleteWhenUnused(VkRenderPass renderPass) {
mRenderPassesToDelete.Enqueue(renderPass, mDevice->GetPendingCommandSerial());
}
@@ -164,6 +169,11 @@
}
mDescriptorPoolsToDelete.ClearUpTo(completedSerial);
+ for (VkQueryPool pool : mQueryPoolsToDelete.IterateUpTo(completedSerial)) {
+ mDevice->fn.DestroyQueryPool(vkDevice, pool, nullptr);
+ }
+ mQueryPoolsToDelete.ClearUpTo(completedSerial);
+
for (VkSampler sampler : mSamplersToDelete.IterateUpTo(completedSerial)) {
mDevice->fn.DestroySampler(vkDevice, sampler, nullptr);
}
diff --git a/src/dawn_native/vulkan/FencedDeleter.h b/src/dawn_native/vulkan/FencedDeleter.h
index 7200eda..9e516b1 100644
--- a/src/dawn_native/vulkan/FencedDeleter.h
+++ b/src/dawn_native/vulkan/FencedDeleter.h
@@ -36,6 +36,7 @@
void DeleteWhenUnused(VkPipelineLayout layout);
void DeleteWhenUnused(VkRenderPass renderPass);
void DeleteWhenUnused(VkPipeline pipeline);
+ void DeleteWhenUnused(VkQueryPool querypool);
void DeleteWhenUnused(VkSampler sampler);
void DeleteWhenUnused(VkSemaphore semaphore);
void DeleteWhenUnused(VkShaderModule module);
@@ -54,6 +55,7 @@
SerialQueue<VkImageView> mImageViewsToDelete;
SerialQueue<VkPipeline> mPipelinesToDelete;
SerialQueue<VkPipelineLayout> mPipelineLayoutsToDelete;
+ SerialQueue<VkQueryPool> mQueryPoolsToDelete;
SerialQueue<VkRenderPass> mRenderPassesToDelete;
SerialQueue<VkSampler> mSamplersToDelete;
SerialQueue<VkSemaphore> mSemaphoresToDelete;
diff --git a/src/dawn_native/vulkan/QuerySetVk.cpp b/src/dawn_native/vulkan/QuerySetVk.cpp
new file mode 100644
index 0000000..0d740a6
--- /dev/null
+++ b/src/dawn_native/vulkan/QuerySetVk.cpp
@@ -0,0 +1,112 @@
+// Copyright 2020 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/vulkan/QuerySetVk.h"
+
+#include "dawn_native/vulkan/DeviceVk.h"
+#include "dawn_native/vulkan/FencedDeleter.h"
+#include "dawn_native/vulkan/VulkanError.h"
+#include "dawn_platform/DawnPlatform.h"
+
+namespace dawn_native { namespace vulkan {
+
+ namespace {
+ VkQueryType VulkanQueryType(wgpu::QueryType type) {
+ switch (type) {
+ case wgpu::QueryType::Occlusion:
+ return VK_QUERY_TYPE_OCCLUSION;
+ case wgpu::QueryType::PipelineStatistics:
+ return VK_QUERY_TYPE_PIPELINE_STATISTICS;
+ case wgpu::QueryType::Timestamp:
+ return VK_QUERY_TYPE_TIMESTAMP;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ VkQueryPipelineStatisticFlags VulkanQueryPipelineStatisticFlags(
+ std::vector<wgpu::PipelineStatisticName> pipelineStatisticsSet) {
+ VkQueryPipelineStatisticFlags pipelineStatistics = 0;
+ for (size_t i = 0; i < pipelineStatisticsSet.size(); ++i) {
+ switch (pipelineStatisticsSet[i]) {
+ case wgpu::PipelineStatisticName::ClipperInvocations:
+ pipelineStatistics |= VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT;
+ break;
+ case wgpu::PipelineStatisticName::ClipperPrimitivesOut:
+ pipelineStatistics |= VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT;
+ break;
+ case wgpu::PipelineStatisticName::ComputeShaderInvocations:
+ pipelineStatistics |=
+ VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
+ break;
+ case wgpu::PipelineStatisticName::FragmentShaderInvocations:
+ pipelineStatistics |=
+ VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT;
+ break;
+ case wgpu::PipelineStatisticName::VertexShaderInvocations:
+ pipelineStatistics |=
+ VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ return pipelineStatistics;
+ }
+ } // anonymous namespace
+
+ // static
+ ResultOrError<QuerySet*> QuerySet::Create(Device* device,
+ const QuerySetDescriptor* descriptor) {
+ Ref<QuerySet> queryset = AcquireRef(new QuerySet(device, descriptor));
+ DAWN_TRY(queryset->Initialize());
+ return queryset.Detach();
+ }
+
+ MaybeError QuerySet::Initialize() {
+ VkQueryPoolCreateInfo createInfo;
+ createInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
+ createInfo.pNext = NULL;
+ createInfo.flags = 0;
+ createInfo.queryType = VulkanQueryType(GetQueryType());
+ createInfo.queryCount = GetQueryCount();
+ if (GetQueryType() == wgpu::QueryType::PipelineStatistics) {
+ createInfo.pipelineStatistics =
+ VulkanQueryPipelineStatisticFlags(GetPipelineStatistics());
+ }
+
+ Device* device = ToBackend(GetDevice());
+ return CheckVkOOMThenSuccess(
+ device->fn.CreateQueryPool(device->GetVkDevice(), &createInfo, nullptr, &*mHandle),
+ "vkCreateQueryPool");
+ }
+
+ VkQueryPool QuerySet::GetHandle() const {
+ return mHandle;
+ }
+
+ QuerySet::~QuerySet() {
+ DestroyInternal();
+ }
+
+ void QuerySet::DestroyImpl() {
+ if (mHandle != VK_NULL_HANDLE) {
+ ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
+ mHandle = VK_NULL_HANDLE;
+ }
+ }
+
+}} // namespace dawn_native::vulkan
diff --git a/src/dawn_native/vulkan/QuerySetVk.h b/src/dawn_native/vulkan/QuerySetVk.h
new file mode 100644
index 0000000..18cd001
--- /dev/null
+++ b/src/dawn_native/vulkan/QuerySetVk.h
@@ -0,0 +1,45 @@
+// Copyright 2020 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DAWNNATIVE_VULKAN_QUERYSETVK_H_
+#define DAWNNATIVE_VULKAN_QUERYSETVK_H_
+
+#include "dawn_native/QuerySet.h"
+
+#include "common/vulkan_platform.h"
+
+namespace dawn_native { namespace vulkan {
+
+ class Device;
+
+ class QuerySet final : public QuerySetBase {
+ public:
+ static ResultOrError<QuerySet*> Create(Device* device,
+ const QuerySetDescriptor* descriptor);
+
+ VkQueryPool GetHandle() const;
+
+ private:
+ ~QuerySet() override;
+ using QuerySetBase::QuerySetBase;
+ MaybeError Initialize();
+
+ void DestroyImpl() override;
+
+ VkQueryPool mHandle = VK_NULL_HANDLE;
+ };
+
+}} // namespace dawn_native::vulkan
+
+#endif // DAWNNATIVE_VULKAN_QUERYSETVK_H_
diff --git a/src/tests/end2end/QueryTests.cpp b/src/tests/end2end/QueryTests.cpp
index 5436021..47ccdd0 100644
--- a/src/tests/end2end/QueryTests.cpp
+++ b/src/tests/end2end/QueryTests.cpp
@@ -57,7 +57,7 @@
querySet.Destroy();
}
-DAWN_INSTANTIATE_TEST(OcclusionQueryTests, D3D12Backend());
+DAWN_INSTANTIATE_TEST(OcclusionQueryTests, D3D12Backend(), VulkanBackend());
class PipelineStatisticsQueryTests : public QueryTests {
protected:
@@ -91,7 +91,7 @@
device.CreateQuerySet(&descriptor);
}
-DAWN_INSTANTIATE_TEST(PipelineStatisticsQueryTests, D3D12Backend());
+DAWN_INSTANTIATE_TEST(PipelineStatisticsQueryTests, D3D12Backend(), VulkanBackend());
class TimestampExpectation : public detail::Expectation {
public: