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>
This commit is contained in:
Hao Li 2020-08-20 00:40:07 +00:00 committed by Commit Bot service account
parent 2f6e4ec6c0
commit eff9ef0f22
8 changed files with 183 additions and 3 deletions

View File

@ -499,6 +499,8 @@ source_set("dawn_native_sources") {
"vulkan/NativeSwapChainImplVk.h",
"vulkan/PipelineLayoutVk.cpp",
"vulkan/PipelineLayoutVk.h",
"vulkan/QuerySetVk.cpp",
"vulkan/QuerySetVk.h",
"vulkan/QueueVk.cpp",
"vulkan/QueueVk.h",
"vulkan/RenderPassCache.cpp",

View File

@ -396,6 +396,8 @@ if (DAWN_ENABLE_VULKAN)
"vulkan/NativeSwapChainImplVk.h"
"vulkan/PipelineLayoutVk.cpp"
"vulkan/PipelineLayoutVk.h"
"vulkan/QuerySetVk.cpp"
"vulkan/QuerySetVk.h"
"vulkan/QueueVk.cpp"
"vulkan/QueueVk.h"
"vulkan/RenderPassCache.cpp"

View File

@ -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 @@ namespace dawn_native { namespace vulkan {
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 @@ namespace dawn_native { namespace vulkan {
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) &&

View File

@ -30,6 +30,7 @@ namespace dawn_native { namespace vulkan {
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 @@ namespace dawn_native { namespace vulkan {
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 @@ namespace dawn_native { namespace vulkan {
}
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);
}

View File

@ -36,6 +36,7 @@ namespace dawn_native { namespace vulkan {
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 @@ namespace dawn_native { namespace vulkan {
SerialQueue<VkImageView> mImageViewsToDelete;
SerialQueue<VkPipeline> mPipelinesToDelete;
SerialQueue<VkPipelineLayout> mPipelineLayoutsToDelete;
SerialQueue<VkQueryPool> mQueryPoolsToDelete;
SerialQueue<VkRenderPass> mRenderPassesToDelete;
SerialQueue<VkSampler> mSamplersToDelete;
SerialQueue<VkSemaphore> mSemaphoresToDelete;

View File

@ -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

View File

@ -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_

View File

@ -57,7 +57,7 @@ TEST_P(OcclusionQueryTests, QuerySetDestroy) {
querySet.Destroy();
}
DAWN_INSTANTIATE_TEST(OcclusionQueryTests, D3D12Backend());
DAWN_INSTANTIATE_TEST(OcclusionQueryTests, D3D12Backend(), VulkanBackend());
class PipelineStatisticsQueryTests : public QueryTests {
protected:
@ -91,7 +91,7 @@ TEST_P(PipelineStatisticsQueryTests, QuerySetCreation) {
device.CreateQuerySet(&descriptor);
}
DAWN_INSTANTIATE_TEST(PipelineStatisticsQueryTests, D3D12Backend());
DAWN_INSTANTIATE_TEST(PipelineStatisticsQueryTests, D3D12Backend(), VulkanBackend());
class TimestampExpectation : public detail::Expectation {
public: