Query API: QuerySet

- Add QuerySet w/o backends implementation.
- Add validation tests

Bug: dawn:434
Change-Id: Id9fed4e42fac464b1254cd2e9cf5337a1d803089
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22440
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-06-11 00:34:14 +00:00 committed by Commit Bot service account
parent 70d75c8c00
commit b6eff5acf0
27 changed files with 577 additions and 0 deletions

View File

@ -636,6 +636,13 @@
{"name": "callback", "type": "error callback"},
{"name": "userdata", "type": "void", "annotation": "*"}
]
},
{
"name": "create query set",
"returns": "query set",
"args": [
{"name": "descriptor", "type": "query set descriptor", "annotation": "const*"}
]
}
]
},
@ -854,6 +861,16 @@
{"name": "bind group layouts", "type": "bind group layout", "annotation": "const*", "length": "bind group layout count"}
]
},
"pipeline statistics name": {
"category": "enum",
"values": [
{"value": 0, "name": "vertex shader invocations"},
{"value": 1, "name": "clipper invocations"},
{"value": 2, "name": "clipper primitives out"},
{"value": 3, "name": "fragment shader invocations"},
{"value": 4, "name": "compute shader invocations"}
]
},
"present mode": {
"category": "enum",
"values": [
@ -880,6 +897,33 @@
{"value": 4, "name": "triangle strip"}
]
},
"query set": {
"category": "object",
"methods": [
{
"name": "destroy"
}
]
},
"query set descriptor": {
"category": "structure",
"extensible": true,
"members": [
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen", "optional": true},
{"name": "type", "type": "query type"},
{"name": "count", "type": "uint32_t"},
{"name": "pipeline statistics count", "type": "uint32_t", "default": "0"},
{"name": "pipeline statistics", "type": "pipeline statistics name", "annotation": "const*", "length": "pipeline statistics count"}
]
},
"query type": {
"category": "enum",
"values": [
{"value": 0, "name": "occlusion"},
{"value": 1, "name": "pipeline statistics"},
{"value": 2, "name": "timestamp"}
]
},
"queue": {
"category": "object",
"methods": [

View File

@ -230,6 +230,8 @@ source_set("dawn_native_sources") {
"PipelineLayout.h",
"ProgrammablePassEncoder.cpp",
"ProgrammablePassEncoder.h",
"QuerySet.cpp",
"QuerySet.h",
"Queue.cpp",
"Queue.h",
"RenderBundle.cpp",
@ -442,6 +444,8 @@ source_set("dawn_native_sources") {
"opengl/PipelineGL.h",
"opengl/PipelineLayoutGL.cpp",
"opengl/PipelineLayoutGL.h",
"opengl/QuerySetGL.cpp",
"opengl/QuerySetGL.h",
"opengl/QueueGL.cpp",
"opengl/QueueGL.h",
"opengl/RenderPipelineGL.cpp",

View File

@ -102,6 +102,8 @@ target_sources(dawn_native PRIVATE
"PipelineLayout.h"
"ProgrammablePassEncoder.cpp"
"ProgrammablePassEncoder.h"
"QuerySet.cpp"
"QuerySet.h"
"Queue.cpp"
"Queue.h"
"RenderBundle.cpp"
@ -333,6 +335,8 @@ if (DAWN_ENABLE_OPENGL)
"opengl/PipelineGL.h"
"opengl/PipelineLayoutGL.cpp"
"opengl/PipelineLayoutGL.h"
"opengl/QuerySetGL.cpp"
"opengl/QuerySetGL.h"
"opengl/QueueGL.cpp"
"opengl/QueueGL.h"
"opengl/RenderPipelineGL.cpp"

View File

@ -32,6 +32,7 @@
#include "dawn_native/Instance.h"
#include "dawn_native/MapRequestTracker.h"
#include "dawn_native/PipelineLayout.h"
#include "dawn_native/QuerySet.h"
#include "dawn_native/Queue.h"
#include "dawn_native/RenderBundleEncoder.h"
#include "dawn_native/RenderPipeline.h"
@ -647,6 +648,15 @@ namespace dawn_native {
return result;
}
QuerySetBase* DeviceBase::CreateQuerySet(const QuerySetDescriptor* descriptor) {
QuerySetBase* result = nullptr;
if (ConsumedError(CreateQuerySetInternal(&result, descriptor))) {
return QuerySetBase::MakeError(this);
}
return result;
}
QueueBase* DeviceBase::CreateQueue() {
// TODO(dawn:22): Remove this once users use GetDefaultQueue
EmitDeprecationWarning(
@ -884,6 +894,16 @@ namespace dawn_native {
return {};
}
MaybeError DeviceBase::CreateQuerySetInternal(QuerySetBase** result,
const QuerySetDescriptor* descriptor) {
DAWN_TRY(ValidateIsAlive());
if (IsValidationEnabled()) {
DAWN_TRY(ValidateQuerySetDescriptor(this, descriptor));
}
DAWN_TRY_ASSIGN(*result, CreateQuerySetImpl(descriptor));
return {};
}
MaybeError DeviceBase::CreateRenderBundleEncoderInternal(
RenderBundleEncoder** result,
const RenderBundleEncoderDescriptor* descriptor) {

View File

@ -146,6 +146,7 @@ namespace dawn_native {
CommandEncoder* CreateCommandEncoder(const CommandEncoderDescriptor* descriptor);
ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
QuerySetBase* CreateQuerySet(const QuerySetDescriptor* descriptor);
QueueBase* CreateQueue();
RenderBundleEncoder* CreateRenderBundleEncoder(
const RenderBundleEncoderDescriptor* descriptor);
@ -239,6 +240,8 @@ namespace dawn_native {
const ComputePipelineDescriptor* descriptor) = 0;
virtual ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<QuerySetBase*> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) = 0;
virtual ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) = 0;
virtual ResultOrError<SamplerBase*> CreateSamplerImpl(
@ -267,6 +270,8 @@ namespace dawn_native {
const ComputePipelineDescriptor* descriptor);
MaybeError CreatePipelineLayoutInternal(PipelineLayoutBase** result,
const PipelineLayoutDescriptor* descriptor);
MaybeError CreateQuerySetInternal(QuerySetBase** result,
const QuerySetDescriptor* descriptor);
MaybeError CreateRenderBundleEncoderInternal(
RenderBundleEncoder** result,
const RenderBundleEncoderDescriptor* descriptor);

View File

@ -34,6 +34,7 @@ namespace dawn_native {
class InstanceBase;
class PipelineBase;
class PipelineLayoutBase;
class QuerySetBase;
class QueueBase;
class RenderBundleBase;
class RenderBundleEncoder;

View File

@ -0,0 +1,153 @@
// 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/QuerySet.h"
#include "dawn_native/Device.h"
#include "dawn_native/Extensions.h"
#include "dawn_native/ValidationUtils_autogen.h"
#include <set>
namespace dawn_native {
namespace {
class ErrorQuerySet final : public QuerySetBase {
public:
ErrorQuerySet(DeviceBase* device) : QuerySetBase(device, ObjectBase::kError) {
}
private:
void DestroyImpl() override {
UNREACHABLE();
}
};
} // anonymous namespace
MaybeError ValidateQuerySetDescriptor(DeviceBase* device,
const QuerySetDescriptor* descriptor) {
if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
}
DAWN_TRY(ValidateQueryType(descriptor->type));
switch (descriptor->type) {
case wgpu::QueryType::Occlusion:
if (descriptor->pipelineStatisticsCount != 0) {
return DAWN_VALIDATION_ERROR(
"The pipeline statistics should not be set if query type is Occlusion");
}
break;
case wgpu::QueryType::PipelineStatistics: {
if (!device->IsExtensionEnabled(Extension::PipelineStatisticsQuery)) {
return DAWN_VALIDATION_ERROR(
"The pipeline statistics query feature is not supported");
}
if (descriptor->pipelineStatisticsCount == 0) {
return DAWN_VALIDATION_ERROR(
"At least one pipeline statistics is set if query type is "
"PipelineStatistics");
}
std::set<wgpu::PipelineStatisticsName> pipelineStatisticsSet;
for (uint32_t i = 0; i < descriptor->pipelineStatisticsCount; i++) {
DAWN_TRY(ValidatePipelineStatisticsName(descriptor->pipelineStatistics[i]));
std::pair<std::set<wgpu::PipelineStatisticsName>::iterator, bool> res =
pipelineStatisticsSet.insert((descriptor->pipelineStatistics[i]));
if (!res.second) {
return DAWN_VALIDATION_ERROR("Duplicate pipeline statistics found");
}
}
} break;
case wgpu::QueryType::Timestamp:
if (!device->IsExtensionEnabled(Extension::TimestampQuery)) {
return DAWN_VALIDATION_ERROR("The timestamp query feature is not supported");
}
if (descriptor->pipelineStatisticsCount != 0) {
return DAWN_VALIDATION_ERROR(
"The pipeline statistics should not be set if query type is Timestamp");
}
break;
default:
break;
}
return {};
}
QuerySetBase::QuerySetBase(DeviceBase* device, const QuerySetDescriptor* descriptor)
: ObjectBase(device),
mQueryType(descriptor->type),
mQueryCount(descriptor->count),
mState(QuerySetState::Available) {
for (uint32_t i = 0; i < descriptor->pipelineStatisticsCount; i++) {
mPipelineStatistics.push_back(descriptor->pipelineStatistics[i]);
}
}
QuerySetBase::QuerySetBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ObjectBase(device, tag) {
}
QuerySetBase::~QuerySetBase() {
// Uninitialized or already destroyed
ASSERT(mState == QuerySetState::Unavailable || mState == QuerySetState::Destroyed);
}
// static
QuerySetBase* QuerySetBase::MakeError(DeviceBase* device) {
return new ErrorQuerySet(device);
}
wgpu::QueryType QuerySetBase::GetQueryType() const {
return mQueryType;
}
uint32_t QuerySetBase::GetQueryCount() const {
return mQueryCount;
}
const std::vector<wgpu::PipelineStatisticsName>& QuerySetBase::GetPipelineStatistics() const {
return mPipelineStatistics;
}
void QuerySetBase::Destroy() {
if (GetDevice()->ConsumedError(ValidateDestroy())) {
return;
}
DestroyInternal();
}
MaybeError QuerySetBase::ValidateDestroy() const {
DAWN_TRY(GetDevice()->ValidateObject(this));
return {};
}
void QuerySetBase::DestroyInternal() {
if (mState != QuerySetState::Destroyed) {
DestroyImpl();
}
mState = QuerySetState::Destroyed;
}
} // namespace dawn_native

View File

@ -0,0 +1,61 @@
// 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_QUERYSET_H_
#define DAWNNATIVE_QUERYSET_H_
#include "dawn_native/Error.h"
#include "dawn_native/Forward.h"
#include "dawn_native/ObjectBase.h"
#include "dawn_native/dawn_platform.h"
namespace dawn_native {
MaybeError ValidateQuerySetDescriptor(DeviceBase* device, const QuerySetDescriptor* descriptor);
class QuerySetBase : public ObjectBase {
public:
QuerySetBase(DeviceBase* device, const QuerySetDescriptor* descriptor);
static QuerySetBase* MakeError(DeviceBase* device);
wgpu::QueryType GetQueryType() const;
uint32_t GetQueryCount() const;
const std::vector<wgpu::PipelineStatisticsName>& GetPipelineStatistics() const;
void Destroy();
protected:
QuerySetBase(DeviceBase* device, ObjectBase::ErrorTag tag);
~QuerySetBase() override;
void DestroyInternal();
private:
virtual void DestroyImpl() = 0;
MaybeError ValidateDestroy() const;
wgpu::QueryType mQueryType;
uint32_t mQueryCount;
std::vector<wgpu::PipelineStatisticsName> mPipelineStatistics;
enum class QuerySetState { Unavailable, Available, Destroyed };
QuerySetState mState = QuerySetState::Unavailable;
};
} // namespace dawn_native
#endif // DAWNNATIVE_QUERYSET_H_

View File

@ -63,6 +63,11 @@ namespace dawn_native {
using BackendType = typename BackendTraits::PipelineLayoutType;
};
template <typename BackendTraits>
struct ToBackendTraits<QuerySetBase, BackendTraits> {
using BackendType = typename BackendTraits::QuerySetType;
};
template <typename BackendTraits>
struct ToBackendTraits<QueueBase, BackendTraits> {
using BackendType = typename BackendTraits::QueueType;

View File

@ -285,6 +285,9 @@ namespace dawn_native { namespace d3d12 {
const PipelineLayoutDescriptor* descriptor) {
return PipelineLayout::Create(this, descriptor);
}
ResultOrError<QuerySetBase*> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) {
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation");
}
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return RenderPipeline::Create(this, descriptor);

View File

@ -136,6 +136,8 @@ namespace dawn_native { namespace d3d12 {
const ComputePipelineDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QuerySetBase*> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;

View File

@ -28,6 +28,7 @@ namespace dawn_native { namespace d3d12 {
class Device;
class Heap;
class PipelineLayout;
class QuerySet;
class Queue;
class RenderPipeline;
class Sampler;
@ -46,6 +47,7 @@ namespace dawn_native { namespace d3d12 {
using ComputePipelineType = ComputePipeline;
using DeviceType = Device;
using PipelineLayoutType = PipelineLayout;
using QuerySetType = QuerySet;
using QueueType = Queue;
using RenderPipelineType = RenderPipeline;
using ResourceHeapType = Heap;

View File

@ -76,6 +76,8 @@ namespace dawn_native { namespace metal {
const ComputePipelineDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QuerySetBase*> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;

View File

@ -123,6 +123,9 @@ namespace dawn_native { namespace metal {
const PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
}
ResultOrError<QuerySetBase*> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) {
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation");
}
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return RenderPipeline::Create(this, descriptor);

View File

@ -28,6 +28,7 @@ namespace dawn_native { namespace metal {
class Device;
class Framebuffer;
class PipelineLayout;
class QuerySet;
class Queue;
class RenderPipeline;
class Sampler;
@ -46,6 +47,7 @@ namespace dawn_native { namespace metal {
using ComputePipelineType = ComputePipeline;
using DeviceType = Device;
using PipelineLayoutType = PipelineLayout;
using QuerySetType = QuerySet;
using QueueType = Queue;
using RenderPipelineType = RenderPipeline;
using SamplerType = Sampler;

View File

@ -116,6 +116,9 @@ namespace dawn_native { namespace null {
const PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
}
ResultOrError<QuerySetBase*> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) {
return new QuerySet(this, descriptor);
}
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return new RenderPipeline(this, descriptor);
@ -351,6 +354,19 @@ namespace dawn_native { namespace null {
FreeCommands(&mCommands);
}
// QuerySet
QuerySet::QuerySet(Device* device, const QuerySetDescriptor* descriptor)
: QuerySetBase(device, descriptor) {
}
QuerySet::~QuerySet() {
DestroyInternal();
}
void QuerySet::DestroyImpl() {
}
// Queue
Queue::Queue(Device* device) : QueueBase(device) {

View File

@ -24,6 +24,7 @@
#include "dawn_native/ComputePipeline.h"
#include "dawn_native/Device.h"
#include "dawn_native/PipelineLayout.h"
#include "dawn_native/QuerySet.h"
#include "dawn_native/Queue.h"
#include "dawn_native/RenderPipeline.h"
#include "dawn_native/RingBufferAllocator.h"
@ -45,6 +46,7 @@ namespace dawn_native { namespace null {
using ComputePipeline = ComputePipelineBase;
class Device;
using PipelineLayout = PipelineLayoutBase;
class QuerySet;
class Queue;
using RenderPipeline = RenderPipelineBase;
using Sampler = SamplerBase;
@ -62,6 +64,7 @@ namespace dawn_native { namespace null {
using ComputePipelineType = ComputePipeline;
using DeviceType = Device;
using PipelineLayoutType = PipelineLayout;
using QuerySetType = QuerySet;
using QueueType = Queue;
using RenderPipelineType = RenderPipeline;
using SamplerType = Sampler;
@ -118,6 +121,8 @@ namespace dawn_native { namespace null {
const ComputePipelineDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QuerySetBase*> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
@ -216,6 +221,16 @@ namespace dawn_native { namespace null {
CommandIterator mCommands;
};
class QuerySet final : public QuerySetBase {
public:
QuerySet(Device* device, const QuerySetDescriptor* descriptor);
private:
~QuerySet() override;
void DestroyImpl() override;
};
class Queue final : public QueueBase {
public:
Queue(Device* device);

View File

@ -24,6 +24,7 @@
#include "dawn_native/opengl/CommandBufferGL.h"
#include "dawn_native/opengl/ComputePipelineGL.h"
#include "dawn_native/opengl/PipelineLayoutGL.h"
#include "dawn_native/opengl/QuerySetGL.h"
#include "dawn_native/opengl/QueueGL.h"
#include "dawn_native/opengl/RenderPipelineGL.h"
#include "dawn_native/opengl/SamplerGL.h"
@ -116,6 +117,9 @@ namespace dawn_native { namespace opengl {
const PipelineLayoutDescriptor* descriptor) {
return new PipelineLayout(this, descriptor);
}
ResultOrError<QuerySetBase*> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) {
return new QuerySet(this, descriptor);
}
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return new RenderPipeline(this, descriptor);

View File

@ -19,6 +19,7 @@
#include "common/Platform.h"
#include "dawn_native/Device.h"
#include "dawn_native/QuerySet.h"
#include "dawn_native/opengl/Forward.h"
#include "dawn_native/opengl/GLFormat.h"
#include "dawn_native/opengl/OpenGLFunctions.h"
@ -75,6 +76,8 @@ namespace dawn_native { namespace opengl {
const ComputePipelineDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QuerySetBase*> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;

View File

@ -28,6 +28,7 @@ namespace dawn_native { namespace opengl {
class Device;
class PersistentPipelineState;
class PipelineLayout;
class QuerySet;
class Queue;
class RenderPipeline;
class Sampler;
@ -45,6 +46,7 @@ namespace dawn_native { namespace opengl {
using ComputePipelineType = ComputePipeline;
using DeviceType = Device;
using PipelineLayoutType = PipelineLayout;
using QuerySetType = QuerySet;
using QueueType = Queue;
using RenderPipelineType = RenderPipeline;
using SamplerType = Sampler;

View File

@ -0,0 +1,32 @@
// 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/opengl/QuerySetGL.h"
#include "dawn_native/opengl/DeviceGL.h"
namespace dawn_native { namespace opengl {
QuerySet::QuerySet(Device* device, const QuerySetDescriptor* descriptor)
: QuerySetBase(device, descriptor) {
}
QuerySet::~QuerySet() {
DestroyInternal();
}
void QuerySet::DestroyImpl() {
}
}} // namespace dawn_native::opengl

View File

@ -0,0 +1,36 @@
// 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_OPENGL_QUERYSETGL_H_
#define DAWNNATIVE_OPENGL_QUERYSETGL_H_
#include "dawn_native/QuerySet.h"
namespace dawn_native { namespace opengl {
class Device;
class QuerySet final : public QuerySetBase {
public:
QuerySet(Device* device, const QuerySetDescriptor* descriptor);
private:
~QuerySet() override;
void DestroyImpl() override;
};
}} // namespace dawn_native::opengl
#endif // DAWNNATIVE_OPENGL_QUERYSETGL_H_

View File

@ -124,6 +124,9 @@ namespace dawn_native { namespace vulkan {
const PipelineLayoutDescriptor* descriptor) {
return PipelineLayout::Create(this, descriptor);
}
ResultOrError<QuerySetBase*> Device::CreateQuerySetImpl(const QuerySetDescriptor* descriptor) {
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation");
}
ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) {
return RenderPipeline::Create(this, descriptor);

View File

@ -108,6 +108,8 @@ namespace dawn_native { namespace vulkan {
const ComputePipelineDescriptor* descriptor) override;
ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) override;
ResultOrError<QuerySetBase*> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) override;
ResultOrError<RenderPipelineBase*> CreateRenderPipelineImpl(
const RenderPipelineDescriptor* descriptor) override;
ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;

View File

@ -27,6 +27,7 @@ namespace dawn_native { namespace vulkan {
class ComputePipeline;
class Device;
class PipelineLayout;
class QuerySet;
class Queue;
class RenderPipeline;
class ResourceHeap;
@ -46,6 +47,7 @@ namespace dawn_native { namespace vulkan {
using ComputePipelineType = ComputePipeline;
using DeviceType = Device;
using PipelineLayoutType = PipelineLayout;
using QuerySetType = QuerySet;
using QueueType = Queue;
using RenderPipelineType = RenderPipeline;
using ResourceHeapType = ResourceHeap;

View File

@ -185,6 +185,7 @@ test("dawn_unittests") {
"unittests/validation/FenceValidationTests.cpp",
"unittests/validation/GetBindGroupLayoutValidationTests.cpp",
"unittests/validation/IndexBufferValidationTests.cpp",
"unittests/validation/QuerySetValidationTests.cpp",
"unittests/validation/QueueSubmitValidationTests.cpp",
"unittests/validation/RenderBundleValidationTests.cpp",
"unittests/validation/RenderPassDescriptorValidationTests.cpp",

View File

@ -0,0 +1,150 @@
// 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 "tests/unittests/validation/ValidationTest.h"
#include "utils/WGPUHelpers.h"
class QuerySetValidationTest : public ValidationTest {
protected:
void SetUp() override {
ValidationTest::SetUp();
// Initialize the device with required extensions
deviceWithPipelineStatistics =
CreateDeviceFromAdapter(adapter, {"pipeline_statistics_query"});
deviceWithTimestamp = CreateDeviceFromAdapter(adapter, {"timestamp_query"});
}
void CreateQuerySet(wgpu::Device cDevice,
wgpu::QueryType queryType,
uint32_t queryCount,
std::vector<wgpu::PipelineStatisticsName> pipelineStatistics = {}) {
wgpu::QuerySetDescriptor descriptor;
descriptor.type = queryType;
descriptor.count = queryCount;
if (pipelineStatistics.size() > 0) {
descriptor.pipelineStatistics = pipelineStatistics.data();
descriptor.pipelineStatisticsCount = pipelineStatistics.size();
}
cDevice.CreateQuerySet(&descriptor);
}
wgpu::Device deviceWithPipelineStatistics;
wgpu::Device deviceWithTimestamp;
};
// Test creating query set with/without extensions
TEST_F(QuerySetValidationTest, Creation) {
// Create query set for Occlusion query
{
// Success on default device without any extension enabled
// Occlusion query does not require any extension.
CreateQuerySet(device, wgpu::QueryType::Occlusion, 1);
// Success on the device with extension enabled.
CreateQuerySet(deviceWithPipelineStatistics, wgpu::QueryType::Occlusion, 1);
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Occlusion, 1);
}
// Create query set for PipelineStatistics query
{
// Fail on default device without any extension enabled
ASSERT_DEVICE_ERROR(
CreateQuerySet(device, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticsName::VertexShaderInvocations}));
// Success on the device if the extension is enabled.
CreateQuerySet(deviceWithPipelineStatistics, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticsName::VertexShaderInvocations});
}
// Create query set for Timestamp query
{
// Fail on default device without any extension enabled
ASSERT_DEVICE_ERROR(CreateQuerySet(device, wgpu::QueryType::Timestamp, 1));
// Success on the device if the extension is enabled.
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 1);
}
}
// Test creating query set with invalid type
TEST_F(QuerySetValidationTest, InvalidQueryType) {
ASSERT_DEVICE_ERROR(CreateQuerySet(device, static_cast<wgpu::QueryType>(0xFFFFFFFF), 1));
}
// Test creating query set with unnecessary pipeline statistics
TEST_F(QuerySetValidationTest, UnnecessaryPipelineStatistics) {
// Fail to create with pipeline statistics for Occlusion query
{
ASSERT_DEVICE_ERROR(
CreateQuerySet(device, wgpu::QueryType::Occlusion, 1,
{wgpu::PipelineStatisticsName::VertexShaderInvocations}));
}
// Fail to create with pipeline statistics for Timestamp query
{
ASSERT_DEVICE_ERROR(
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 1,
{wgpu::PipelineStatisticsName::VertexShaderInvocations}));
}
}
// Test creating query set with invalid pipeline statistics
TEST_F(QuerySetValidationTest, InvalidPipelineStatistics) {
// Success to create with all pipeline statistics names which are not in the same order as
// defined in webgpu header file
{
CreateQuerySet(deviceWithPipelineStatistics, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticsName::ClipperInvocations,
wgpu::PipelineStatisticsName::ClipperPrimitivesOut,
wgpu::PipelineStatisticsName::ComputeShaderInvocations,
wgpu::PipelineStatisticsName::FragmentShaderInvocations,
wgpu::PipelineStatisticsName::VertexShaderInvocations});
}
// Fail to create with empty pipeline statistics
{
ASSERT_DEVICE_ERROR(CreateQuerySet(deviceWithPipelineStatistics,
wgpu::QueryType::PipelineStatistics, 1, {}));
}
// Fail to create with invalid pipeline statistics
{
ASSERT_DEVICE_ERROR(
CreateQuerySet(deviceWithPipelineStatistics, wgpu::QueryType::PipelineStatistics, 1,
{static_cast<wgpu::PipelineStatisticsName>(0xFFFFFFFF)}));
}
// Fail to create with duplicate pipeline statistics
{
ASSERT_DEVICE_ERROR(
CreateQuerySet(deviceWithPipelineStatistics, wgpu::QueryType::PipelineStatistics, 1,
{wgpu::PipelineStatisticsName::VertexShaderInvocations,
wgpu::PipelineStatisticsName::VertexShaderInvocations}));
}
}
// Test destroying a destroyed query set
TEST_F(QuerySetValidationTest, DestroyDestroyedQuerySet) {
wgpu::QuerySetDescriptor descriptor;
descriptor.type = wgpu::QueryType::Occlusion;
descriptor.count = 1;
wgpu::QuerySet querySet = device.CreateQuerySet(&descriptor);
querySet.Destroy();
querySet.Destroy();
}