Add reflection APIs for wgpu::QuerySet.

Bug: dawn:1451
Change-Id: I8bce40e4fc0c7caca3c3a4b8c385ba8a393a3f1c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/92662
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2022-06-09 10:12:13 +00:00 committed by Dawn LUCI CQ
parent 5fb759f6e7
commit 45820ae995
13 changed files with 184 additions and 10 deletions

View File

@ -1612,6 +1612,14 @@
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen"}
]
},
{
"name": "get type",
"returns": "query type"
},
{
"name": "get count",
"returns": "uint32_t"
},
{
"name": "destroy"
}

View File

@ -203,6 +203,8 @@
"DeviceSetLoggingCallback",
"InstanceRequestAdapter",
"ShaderModuleGetCompilationInfo",
"QuerySetGetType",
"QuerySetGetCount",
"QueueOnSubmittedWorkDone",
"QueueWriteBuffer",
"QueueWriteTexture",
@ -219,6 +221,7 @@
"BufferDestroy",
"BufferUnmap",
"DeviceCreateErrorBuffer",
"DeviceCreateQuerySet",
"DeviceCreateTexture",
"DeviceGetQueue",
"DeviceInjectError"
@ -228,6 +231,7 @@
"Buffer",
"Device",
"Instance",
"QuerySet",
"Queue",
"ShaderModule",
"Texture"

View File

@ -1126,7 +1126,7 @@ QuerySetBase* DeviceBase::APICreateQuerySet(const QuerySetDescriptor* descriptor
Ref<QuerySetBase> result;
if (ConsumedError(CreateQuerySet(descriptor), &result, "calling %s.CreateQuerySet(%s).", this,
descriptor)) {
return QuerySetBase::MakeError(this);
return QuerySetBase::MakeError(this, descriptor);
}
return result.Detach();
}

View File

@ -27,7 +27,8 @@ namespace {
class ErrorQuerySet final : public QuerySetBase {
public:
explicit ErrorQuerySet(DeviceBase* device) : QuerySetBase(device, ObjectBase::kError) {}
explicit ErrorQuerySet(DeviceBase* device, const QuerySetDescriptor* descriptor)
: QuerySetBase(device, descriptor, ObjectBase::kError) {}
private:
void DestroyImpl() override { UNREACHABLE(); }
@ -113,8 +114,10 @@ QuerySetBase::QuerySetBase(DeviceBase* device) : ApiObjectBase(device, kLabelNot
TrackInDevice();
}
QuerySetBase::QuerySetBase(DeviceBase* device, ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag) {}
QuerySetBase::QuerySetBase(DeviceBase* device,
const QuerySetDescriptor* descriptor,
ObjectBase::ErrorTag tag)
: ApiObjectBase(device, tag), mQueryType(descriptor->type), mQueryCount(descriptor->count) {}
QuerySetBase::~QuerySetBase() {
// Uninitialized or already destroyed
@ -126,8 +129,8 @@ void QuerySetBase::DestroyImpl() {
}
// static
QuerySetBase* QuerySetBase::MakeError(DeviceBase* device) {
return new ErrorQuerySet(device);
QuerySetBase* QuerySetBase::MakeError(DeviceBase* device, const QuerySetDescriptor* descriptor) {
return new ErrorQuerySet(device, descriptor);
}
ObjectType QuerySetBase::GetType() const {
@ -167,6 +170,14 @@ void QuerySetBase::APIDestroy() {
Destroy();
}
wgpu::QueryType QuerySetBase::APIGetType() const {
return mQueryType;
}
uint32_t QuerySetBase::APIGetCount() const {
return mQueryCount;
}
MaybeError QuerySetBase::ValidateDestroy() const {
DAWN_TRY(GetDevice()->ValidateObject(this));
return {};

View File

@ -29,9 +29,7 @@ MaybeError ValidateQuerySetDescriptor(DeviceBase* device, const QuerySetDescript
class QuerySetBase : public ApiObjectBase {
public:
QuerySetBase(DeviceBase* device, const QuerySetDescriptor* descriptor);
static QuerySetBase* MakeError(DeviceBase* device);
static QuerySetBase* MakeError(DeviceBase* device, const QuerySetDescriptor* descriptor);
ObjectType GetType() const override;
@ -45,9 +43,14 @@ class QuerySetBase : public ApiObjectBase {
MaybeError ValidateCanUseInSubmitNow() const;
void APIDestroy();
wgpu::QueryType APIGetType() const;
uint32_t APIGetCount() const;
protected:
QuerySetBase(DeviceBase* device, ObjectBase::ErrorTag tag);
QuerySetBase(DeviceBase* device, const QuerySetDescriptor* descriptor);
QuerySetBase(DeviceBase* device,
const QuerySetDescriptor* descriptor,
ObjectBase::ErrorTag tag);
// Constructor used only for mocking and testing.
explicit QuerySetBase(DeviceBase* device);

View File

@ -78,6 +78,46 @@ TEST_F(QuerySetValidationTest, DestroyDestroyedQuerySet) {
querySet.Destroy();
}
// Test that the query set creation parameters are correctly reflected for successfully created
// query sets.
TEST_F(QuerySetValidationTest, CreationParameterReflectionForValidQuerySet) {
// Test reflection on two succesfully created but different query sets
{
wgpu::QuerySetDescriptor desc;
desc.type = wgpu::QueryType::Occlusion;
desc.count = 18;
wgpu::QuerySet set = device.CreateQuerySet(&desc);
EXPECT_EQ(wgpu::QueryType::Occlusion, set.GetType());
EXPECT_EQ(18u, set.GetCount());
}
{
wgpu::QuerySetDescriptor desc;
// Unfortunately without extensions we can't check a different type.
desc.type = wgpu::QueryType::Occlusion;
desc.count = 1;
wgpu::QuerySet set = device.CreateQuerySet(&desc);
EXPECT_EQ(wgpu::QueryType::Occlusion, set.GetType());
EXPECT_EQ(1u, set.GetCount());
}
}
// Test that the query set creation parameters are correctly reflected for error query sets.
TEST_F(QuerySetValidationTest, CreationParameterReflectionForErrorQuerySet) {
wgpu::QuerySetDescriptor desc;
desc.type = static_cast<wgpu::QueryType>(0xFFFF);
desc.count = 76;
// Error! We have a garbage type.
wgpu::QuerySet set;
ASSERT_DEVICE_ERROR(set = device.CreateQuerySet(&desc));
// Reflection data is still exactly what was in the descriptor.
EXPECT_EQ(desc.type, set.GetType());
EXPECT_EQ(76u, set.GetCount());
}
class OcclusionQueryValidationTest : public QuerySetValidationTest {};
// Test the occlusionQuerySet in RenderPassDescriptor

View File

@ -91,6 +91,8 @@ dawn_component("wire") {
"client/ObjectAllocator.h",
"client/ObjectBase.cpp",
"client/ObjectBase.h",
"client/QuerySet.cpp",
"client/QuerySet.h",
"client/Queue.cpp",
"client/Queue.h",
"client/RequestTracker.h",

View File

@ -64,6 +64,8 @@ target_sources(dawn_wire PRIVATE
"client/ObjectAllocator.h"
"client/ObjectBase.cpp"
"client/ObjectBase.h"
"client/QuerySet.cpp"
"client/QuerySet.h"
"client/Queue.cpp"
"client/Queue.h"
"client/RequestTracker.h"

View File

@ -21,6 +21,7 @@
#include "dawn/wire/client/Buffer.h"
#include "dawn/wire/client/Device.h"
#include "dawn/wire/client/Instance.h"
#include "dawn/wire/client/QuerySet.h"
#include "dawn/wire/client/Queue.h"
#include "dawn/wire/client/ShaderModule.h"
#include "dawn/wire/client/Texture.h"

View File

@ -204,6 +204,10 @@ WGPUBuffer Device::CreateErrorBuffer() {
return Buffer::CreateError(this, &fakeDescriptor);
}
WGPUQuerySet Device::CreateQuerySet(const WGPUQuerySetDescriptor* descriptor) {
return QuerySet::Create(this, descriptor);
}
WGPUTexture Device::CreateTexture(const WGPUTextureDescriptor* descriptor) {
return Texture::Create(this, descriptor);
}

View File

@ -50,6 +50,7 @@ class Device final : public ObjectBase {
void CreateRenderPipelineAsync(WGPURenderPipelineDescriptor const* descriptor,
WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata);
WGPUQuerySet CreateQuerySet(const WGPUQuerySetDescriptor* descriptor);
WGPUTexture CreateTexture(const WGPUTextureDescriptor* descriptor);
void HandleError(WGPUErrorType errorType, const char* message);

View File

@ -0,0 +1,54 @@
// Copyright 2022 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/wire/client/QuerySet.h"
#include "dawn/wire/client/Client.h"
#include "dawn/wire/client/Device.h"
namespace dawn::wire::client {
// static
WGPUQuerySet QuerySet::Create(Device* device, const WGPUQuerySetDescriptor* descriptor) {
Client* wireClient = device->client;
auto* objectAndSerial = wireClient->QuerySetAllocator().New(wireClient);
// Copy over descriptor data for reflection.
QuerySet* querySet = objectAndSerial->object.get();
querySet->mType = descriptor->type;
querySet->mCount = descriptor->count;
// Send the Device::CreateQuerySet command without modifications.
DeviceCreateQuerySetCmd cmd;
cmd.self = ToAPI(device);
cmd.selfId = device->id;
cmd.descriptor = descriptor;
cmd.result = ObjectHandle{querySet->id, objectAndSerial->generation};
wireClient->SerializeCommand(cmd);
return ToAPI(querySet);
}
QuerySet::QuerySet(Client* c, uint32_t r, uint32_t i) : ObjectBase(c, r, i) {}
QuerySet::~QuerySet() = default;
WGPUQueryType QuerySet::GetType() const {
return mType;
}
uint32_t QuerySet::GetCount() const {
return mCount;
}
} // namespace dawn::wire::client

View File

@ -0,0 +1,44 @@
// Copyright 2022 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 SRC_DAWN_WIRE_CLIENT_QUERYSET_H_
#define SRC_DAWN_WIRE_CLIENT_QUERYSET_H_
#include "dawn/webgpu.h"
#include "dawn/wire/client/ObjectBase.h"
namespace dawn::wire::client {
class Device;
class QuerySet final : public ObjectBase {
public:
static WGPUQuerySet Create(Device* device, const WGPUQuerySetDescriptor* descriptor);
QuerySet(Client* client, uint32_t refcount, uint32_t id);
~QuerySet();
// Note that these values can be arbitrary since they aren't validated in the wire client.
WGPUQueryType GetType() const;
uint32_t GetCount() const;
private:
WGPUQueryType mType;
uint32_t mCount;
};
} // namespace dawn::wire::client
#endif // SRC_DAWN_WIRE_CLIENT_QUERYSET_H_