Remove Fences
Fences are no longer part of the WebGPU spec, and have been removed from Blink. Bug: dawn:22 Change-Id: I240c4c4107acfaf9facec88a43a38b5ff327c7a6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/50702 Commit-Queue: Brandon Jones <bajones@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
36cb5a86de
commit
a548578f67
55
dawn.json
55
dawn.json
|
@ -951,47 +951,6 @@
|
|||
{"name": "format", "type": "texture format"}
|
||||
]
|
||||
},
|
||||
"fence": {
|
||||
"category": "object",
|
||||
"methods": [
|
||||
{
|
||||
"name": "get completed value",
|
||||
"returns": "uint64_t"
|
||||
},
|
||||
{
|
||||
"name": "on completion",
|
||||
"args": [
|
||||
{"name": "value", "type": "uint64_t"},
|
||||
{"name": "callback", "type": "fence on completion callback"},
|
||||
{"name": "userdata", "type": "void", "annotation": "*"}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"fence on completion callback": {
|
||||
"category": "callback",
|
||||
"args": [
|
||||
{"name": "status", "type": "fence completion status"},
|
||||
{"name": "userdata", "type": "void", "annotation": "*"}
|
||||
]
|
||||
},
|
||||
"fence completion status": {
|
||||
"category": "enum",
|
||||
"values": [
|
||||
{"value": 0, "name": "success"},
|
||||
{"value": 1, "name": "error"},
|
||||
{"value": 2, "name": "unknown"},
|
||||
{"value": 3, "name": "device lost"}
|
||||
]
|
||||
},
|
||||
"fence descriptor": {
|
||||
"category": "structure",
|
||||
"extensible": true,
|
||||
"members": [
|
||||
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen", "optional": true},
|
||||
{"name": "initial value", "type": "uint64_t", "default": "0"}
|
||||
]
|
||||
},
|
||||
"filter mode": {
|
||||
"category": "enum",
|
||||
"values": [
|
||||
|
@ -1210,20 +1169,6 @@
|
|||
{"name": "commands", "type": "command buffer", "annotation": "const*", "length": "command count"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "signal",
|
||||
"args": [
|
||||
{"name": "fence", "type": "fence"},
|
||||
{"name": "signal value", "type": "uint64_t"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "create fence",
|
||||
"returns": "fence",
|
||||
"args": [
|
||||
{"name": "descriptor", "type": "fence descriptor", "annotation": "const*", "optional": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "on submitted work done",
|
||||
"args": [
|
||||
|
|
|
@ -59,11 +59,6 @@
|
|||
{ "name": "object type", "type": "ObjectType" },
|
||||
{ "name": "object id", "type": "ObjectId" }
|
||||
],
|
||||
"fence on completion": [
|
||||
{ "name": "fence id", "type": "ObjectId" },
|
||||
{ "name": "value", "type": "uint64_t" },
|
||||
{ "name": "request serial", "type": "uint64_t" }
|
||||
],
|
||||
"queue on submitted work done": [
|
||||
{ "name": "queue id", "type": "ObjectId" },
|
||||
{ "name": "signal value", "type": "uint64_t" },
|
||||
|
@ -124,15 +119,6 @@
|
|||
{ "name": "type", "type": "error type" },
|
||||
{ "name": "message", "type": "char", "annotation": "const*", "length": "strlen" }
|
||||
],
|
||||
"fence on completion callback": [
|
||||
{ "name": "fence", "type": "ObjectHandle", "handle_type": "fence" },
|
||||
{ "name": "request serial", "type": "uint64_t" },
|
||||
{ "name": "status", "type": "fence completion status" }
|
||||
],
|
||||
"fence update completed value": [
|
||||
{ "name": "fence", "type": "ObjectHandle", "handle_type": "fence" },
|
||||
{ "name": "value", "type": "uint64_t" }
|
||||
],
|
||||
"queue work done callback": [
|
||||
{ "name": "queue", "type": "ObjectHandle", "handle_type": "queue" },
|
||||
{ "name": "request serial", "type": "uint64_t" },
|
||||
|
@ -162,8 +148,6 @@
|
|||
"DevicePopErrorScope",
|
||||
"DeviceSetDeviceLostCallback",
|
||||
"DeviceSetUncapturedErrorCallback",
|
||||
"FenceGetCompletedValue",
|
||||
"FenceOnCompletion",
|
||||
"ShaderModuleGetCompilationInfo",
|
||||
"QueueOnSubmittedWorkDone",
|
||||
"QueueWriteBuffer",
|
||||
|
@ -176,13 +160,11 @@
|
|||
"DeviceGetDefaultQueue",
|
||||
"DeviceGetQueue",
|
||||
"DeviceInjectError",
|
||||
"DevicePushErrorScope",
|
||||
"QueueCreateFence"
|
||||
"DevicePushErrorScope"
|
||||
],
|
||||
"client_special_objects": [
|
||||
"Buffer",
|
||||
"Device",
|
||||
"Fence",
|
||||
"Queue",
|
||||
"ShaderModule"
|
||||
],
|
||||
|
@ -194,7 +176,6 @@
|
|||
"QueueSignal"
|
||||
],
|
||||
"server_reverse_lookup_objects": [
|
||||
"Fence"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -228,8 +228,6 @@ source_set("dawn_native_sources") {
|
|||
"Extensions.h",
|
||||
"ExternalTexture.cpp",
|
||||
"ExternalTexture.h",
|
||||
"Fence.cpp",
|
||||
"Fence.h",
|
||||
"Format.cpp",
|
||||
"Format.h",
|
||||
"Forward.h",
|
||||
|
|
|
@ -96,8 +96,6 @@ target_sources(dawn_native PRIVATE
|
|||
"ExternalTexture.h"
|
||||
"ObjectContentHasher.cpp"
|
||||
"ObjectContentHasher.h"
|
||||
"Fence.cpp"
|
||||
"Fence.h"
|
||||
"Format.cpp"
|
||||
"Format.h"
|
||||
"Forward.h"
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "dawn_native/ErrorData.h"
|
||||
#include "dawn_native/ErrorScope.h"
|
||||
#include "dawn_native/ExternalTexture.h"
|
||||
#include "dawn_native/Fence.h"
|
||||
#include "dawn_native/Instance.h"
|
||||
#include "dawn_native/InternalPipelineStore.h"
|
||||
#include "dawn_native/PersistentCache.h"
|
||||
|
|
|
@ -1,159 +0,0 @@
|
|||
// Copyright 2018 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/Fence.h"
|
||||
|
||||
#include "common/Assert.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/Queue.h"
|
||||
#include "dawn_native/ValidationUtils_autogen.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
struct FenceInFlight : QueueBase::TaskInFlight {
|
||||
FenceInFlight(Ref<Fence> fence, FenceAPISerial value)
|
||||
: fence(std::move(fence)), value(value) {
|
||||
}
|
||||
void Finish() override {
|
||||
fence->SetCompletedValue(value, WGPUFenceCompletionStatus_Success);
|
||||
}
|
||||
void HandleDeviceLoss() override {
|
||||
fence->SetCompletedValue(value, WGPUFenceCompletionStatus_DeviceLost);
|
||||
}
|
||||
~FenceInFlight() override = default;
|
||||
|
||||
private:
|
||||
Ref<Fence> fence;
|
||||
FenceAPISerial value;
|
||||
};
|
||||
|
||||
MaybeError ValidateFenceDescriptor(const FenceDescriptor* descriptor) {
|
||||
if (descriptor->nextInChain != nullptr) {
|
||||
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// Fence
|
||||
|
||||
Fence::Fence(QueueBase* queue, const FenceDescriptor* descriptor)
|
||||
: ObjectBase(queue->GetDevice()),
|
||||
mSignalValue(descriptor->initialValue),
|
||||
mCompletedValue(descriptor->initialValue),
|
||||
mQueue(queue) {
|
||||
}
|
||||
|
||||
Fence::Fence(DeviceBase* device, ObjectBase::ErrorTag tag) : ObjectBase(device, tag) {
|
||||
}
|
||||
|
||||
Fence::~Fence() {
|
||||
for (auto& request : mRequests.IterateAll()) {
|
||||
ASSERT(!IsError());
|
||||
request.completionCallback(WGPUFenceCompletionStatus_Unknown, request.userdata);
|
||||
}
|
||||
mRequests.Clear();
|
||||
}
|
||||
|
||||
// static
|
||||
Fence* Fence::MakeError(DeviceBase* device) {
|
||||
return new Fence(device, ObjectBase::kError);
|
||||
}
|
||||
|
||||
uint64_t Fence::APIGetCompletedValue() const {
|
||||
if (IsError()) {
|
||||
return 0;
|
||||
}
|
||||
return uint64_t(mCompletedValue);
|
||||
}
|
||||
|
||||
void Fence::APIOnCompletion(uint64_t apiValue,
|
||||
wgpu::FenceOnCompletionCallback callback,
|
||||
void* userdata) {
|
||||
FenceAPISerial value(apiValue);
|
||||
|
||||
WGPUFenceCompletionStatus status;
|
||||
if (GetDevice()->ConsumedError(ValidateOnCompletion(value, &status))) {
|
||||
callback(status, userdata);
|
||||
return;
|
||||
}
|
||||
ASSERT(!IsError());
|
||||
|
||||
if (value <= mCompletedValue) {
|
||||
callback(WGPUFenceCompletionStatus_Success, userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
OnCompletionData request;
|
||||
request.completionCallback = callback;
|
||||
request.userdata = userdata;
|
||||
mRequests.Enqueue(std::move(request), value);
|
||||
}
|
||||
|
||||
FenceAPISerial Fence::GetSignaledValue() const {
|
||||
ASSERT(!IsError());
|
||||
return mSignalValue;
|
||||
}
|
||||
|
||||
const QueueBase* Fence::GetQueue() const {
|
||||
ASSERT(!IsError());
|
||||
return mQueue.Get();
|
||||
}
|
||||
|
||||
void Fence::SetSignaledValue(FenceAPISerial signalValue) {
|
||||
ASSERT(!IsError());
|
||||
ASSERT(signalValue > mSignalValue);
|
||||
mSignalValue = signalValue;
|
||||
}
|
||||
|
||||
void Fence::SetCompletedValue(FenceAPISerial completedValue, WGPUFenceCompletionStatus status) {
|
||||
ASSERT(!IsError());
|
||||
ASSERT(completedValue <= mSignalValue);
|
||||
ASSERT(completedValue > mCompletedValue);
|
||||
mCompletedValue = completedValue;
|
||||
|
||||
for (auto& request : mRequests.IterateUpTo(mCompletedValue)) {
|
||||
request.completionCallback(status, request.userdata);
|
||||
}
|
||||
mRequests.ClearUpTo(mCompletedValue);
|
||||
}
|
||||
|
||||
void Fence::UpdateFenceOnComplete(Fence* fence, FenceAPISerial value) {
|
||||
std::unique_ptr<FenceInFlight> fenceInFlight =
|
||||
std::make_unique<FenceInFlight>(fence, value);
|
||||
|
||||
// TODO: use GetLastSubmittedCommandSerial in the future for perforamnce
|
||||
GetDevice()->GetQueue()->TrackTask(std::move(fenceInFlight),
|
||||
GetDevice()->GetPendingCommandSerial());
|
||||
}
|
||||
|
||||
MaybeError Fence::ValidateOnCompletion(FenceAPISerial value,
|
||||
WGPUFenceCompletionStatus* status) const {
|
||||
*status = WGPUFenceCompletionStatus_DeviceLost;
|
||||
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||
|
||||
*status = WGPUFenceCompletionStatus_Error;
|
||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||
|
||||
if (value > mSignalValue) {
|
||||
return DAWN_VALIDATION_ERROR("Value greater than fence signaled value");
|
||||
}
|
||||
|
||||
*status = WGPUFenceCompletionStatus_Success;
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace dawn_native
|
|
@ -1,74 +0,0 @@
|
|||
// Copyright 2018 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_FENCE_H_
|
||||
#define DAWNNATIVE_FENCE_H_
|
||||
|
||||
#include "common/SerialMap.h"
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/Forward.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/ObjectBase.h"
|
||||
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
MaybeError ValidateFenceDescriptor(const FenceDescriptor* descriptor);
|
||||
|
||||
class Fence final : public ObjectBase {
|
||||
public:
|
||||
Fence(QueueBase* queue, const FenceDescriptor* descriptor);
|
||||
|
||||
static Fence* MakeError(DeviceBase* device);
|
||||
|
||||
FenceAPISerial GetSignaledValue() const;
|
||||
const QueueBase* GetQueue() const;
|
||||
|
||||
// Dawn API
|
||||
uint64_t APIGetCompletedValue() const;
|
||||
void APIOnCompletion(uint64_t value,
|
||||
wgpu::FenceOnCompletionCallback callback,
|
||||
void* userdata);
|
||||
|
||||
protected:
|
||||
friend class QueueBase;
|
||||
friend struct FenceInFlight;
|
||||
void SetSignaledValue(FenceAPISerial signalValue);
|
||||
void SetCompletedValue(FenceAPISerial completedValue, WGPUFenceCompletionStatus status);
|
||||
void UpdateFenceOnComplete(Fence* fence, FenceAPISerial value);
|
||||
|
||||
private:
|
||||
Fence(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||
~Fence() override;
|
||||
|
||||
MaybeError ValidateOnCompletion(FenceAPISerial value,
|
||||
WGPUFenceCompletionStatus* status) const;
|
||||
|
||||
struct OnCompletionData {
|
||||
wgpu::FenceOnCompletionCallback completionCallback = nullptr;
|
||||
void* userdata = nullptr;
|
||||
};
|
||||
|
||||
FenceAPISerial mSignalValue;
|
||||
FenceAPISerial mCompletedValue;
|
||||
Ref<QueueBase> mQueue;
|
||||
SerialMap<FenceAPISerial, OnCompletionData> mRequests;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
||||
#endif // DAWNNATIVE_FENCE_H_
|
|
@ -23,7 +23,6 @@
|
|||
#include "dawn_native/CopyTextureForBrowserHelper.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/DynamicUploader.h"
|
||||
#include "dawn_native/Fence.h"
|
||||
#include "dawn_native/QuerySet.h"
|
||||
#include "dawn_native/RenderPassEncoder.h"
|
||||
#include "dawn_native/RenderPipeline.h"
|
||||
|
@ -184,19 +183,6 @@ namespace dawn_native {
|
|||
}
|
||||
}
|
||||
|
||||
void QueueBase::APISignal(Fence* fence, uint64_t apiSignalValue) {
|
||||
FenceAPISerial signalValue(apiSignalValue);
|
||||
|
||||
DeviceBase* device = GetDevice();
|
||||
if (device->ConsumedError(ValidateSignal(fence, signalValue))) {
|
||||
return;
|
||||
}
|
||||
ASSERT(!IsError());
|
||||
|
||||
fence->SetSignaledValue(signalValue);
|
||||
fence->UpdateFenceOnComplete(fence, signalValue);
|
||||
}
|
||||
|
||||
void QueueBase::APIOnSubmittedWorkDone(uint64_t signalValue,
|
||||
WGPUQueueWorkDoneCallback callback,
|
||||
void* userdata) {
|
||||
|
@ -246,22 +232,6 @@ namespace dawn_native {
|
|||
mTasksInFlight.Clear();
|
||||
}
|
||||
|
||||
Fence* QueueBase::APICreateFence(const FenceDescriptor* descriptor) {
|
||||
// TODO(chromium:1177476): Remove once the deprecation period is finished.
|
||||
GetDevice()->EmitDeprecationWarning(
|
||||
"Fences are deprecated, use Queue::OnSubmittedWorkDone instead.");
|
||||
|
||||
if (GetDevice()->ConsumedError(ValidateCreateFence(descriptor))) {
|
||||
return Fence::MakeError(GetDevice());
|
||||
}
|
||||
|
||||
if (descriptor == nullptr) {
|
||||
FenceDescriptor defaultDescriptor = {};
|
||||
return new Fence(this, &defaultDescriptor);
|
||||
}
|
||||
return new Fence(this, descriptor);
|
||||
}
|
||||
|
||||
void QueueBase::APIWriteBuffer(BufferBase* buffer,
|
||||
uint64_t bufferOffset,
|
||||
const void* data,
|
||||
|
@ -437,21 +407,6 @@ namespace dawn_native {
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError QueueBase::ValidateSignal(const Fence* fence, FenceAPISerial signalValue) const {
|
||||
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||
DAWN_TRY(GetDevice()->ValidateObject(fence));
|
||||
|
||||
if (fence->GetQueue() != this) {
|
||||
return DAWN_VALIDATION_ERROR(
|
||||
"Fence must be signaled on the queue on which it was created.");
|
||||
}
|
||||
if (signalValue <= fence->GetSignaledValue()) {
|
||||
return DAWN_VALIDATION_ERROR("Signal value less than or equal to fence signaled value");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
MaybeError QueueBase::ValidateOnSubmittedWorkDone(uint64_t signalValue,
|
||||
WGPUQueueWorkDoneStatus* status) const {
|
||||
*status = WGPUQueueWorkDoneStatus_DeviceLost;
|
||||
|
@ -467,16 +422,6 @@ namespace dawn_native {
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError QueueBase::ValidateCreateFence(const FenceDescriptor* descriptor) const {
|
||||
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||
if (descriptor != nullptr) {
|
||||
DAWN_TRY(ValidateFenceDescriptor(descriptor));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
MaybeError QueueBase::ValidateWriteBuffer(const BufferBase* buffer,
|
||||
uint64_t bufferOffset,
|
||||
size_t size) const {
|
||||
|
|
|
@ -38,8 +38,6 @@ namespace dawn_native {
|
|||
|
||||
// Dawn API
|
||||
void APISubmit(uint32_t commandCount, CommandBufferBase* const* commands);
|
||||
void APISignal(Fence* fence, uint64_t signalValue);
|
||||
Fence* APICreateFence(const FenceDescriptor* descriptor);
|
||||
void APIOnSubmittedWorkDone(uint64_t signalValue,
|
||||
WGPUQueueWorkDoneCallback callback,
|
||||
void* userdata);
|
||||
|
@ -92,10 +90,8 @@ namespace dawn_native {
|
|||
const Extent3D& writeSize);
|
||||
|
||||
MaybeError ValidateSubmit(uint32_t commandCount, CommandBufferBase* const* commands) const;
|
||||
MaybeError ValidateSignal(const Fence* fence, FenceAPISerial signalValue) const;
|
||||
MaybeError ValidateOnSubmittedWorkDone(uint64_t signalValue,
|
||||
WGPUQueueWorkDoneStatus* status) const;
|
||||
MaybeError ValidateCreateFence(const FenceDescriptor* descriptor) const;
|
||||
MaybeError ValidateWriteBuffer(const BufferBase* buffer,
|
||||
uint64_t bufferOffset,
|
||||
size_t size) const;
|
||||
|
|
|
@ -80,8 +80,6 @@ dawn_component("dawn_wire") {
|
|||
"client/ClientInlineMemoryTransferService.cpp",
|
||||
"client/Device.cpp",
|
||||
"client/Device.h",
|
||||
"client/Fence.cpp",
|
||||
"client/Fence.h",
|
||||
"client/ObjectAllocator.h",
|
||||
"client/Queue.cpp",
|
||||
"client/Queue.h",
|
||||
|
@ -92,7 +90,6 @@ dawn_component("dawn_wire") {
|
|||
"server/Server.h",
|
||||
"server/ServerBuffer.cpp",
|
||||
"server/ServerDevice.cpp",
|
||||
"server/ServerFence.cpp",
|
||||
"server/ServerInlineMemoryTransferService.cpp",
|
||||
"server/ServerQueue.cpp",
|
||||
"server/ServerShaderModule.cpp",
|
||||
|
|
|
@ -52,8 +52,6 @@ target_sources(dawn_wire PRIVATE
|
|||
"client/ClientInlineMemoryTransferService.cpp"
|
||||
"client/Device.cpp"
|
||||
"client/Device.h"
|
||||
"client/Fence.cpp"
|
||||
"client/Fence.h"
|
||||
"client/ObjectAllocator.h"
|
||||
"client/Queue.cpp"
|
||||
"client/Queue.h"
|
||||
|
@ -64,7 +62,6 @@ target_sources(dawn_wire PRIVATE
|
|||
"server/Server.h"
|
||||
"server/ServerBuffer.cpp"
|
||||
"server/ServerDevice.cpp"
|
||||
"server/ServerFence.cpp"
|
||||
"server/ServerInlineMemoryTransferService.cpp"
|
||||
"server/ServerQueue.cpp"
|
||||
"server/ServerShaderModule.cpp"
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include "dawn_wire/client/Buffer.h"
|
||||
#include "dawn_wire/client/Device.h"
|
||||
#include "dawn_wire/client/Fence.h"
|
||||
#include "dawn_wire/client/Queue.h"
|
||||
#include "dawn_wire/client/ShaderModule.h"
|
||||
|
||||
|
|
|
@ -70,26 +70,6 @@ namespace dawn_wire { namespace client {
|
|||
readInitialDataInfo);
|
||||
}
|
||||
|
||||
bool Client::DoFenceUpdateCompletedValue(Fence* fence, uint64_t value) {
|
||||
// The fence might have been deleted or recreated so this isn't an error.
|
||||
if (fence == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
fence->OnUpdateCompletedValueCallback(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Client::DoFenceOnCompletionCallback(Fence* fence,
|
||||
uint64_t requestSerial,
|
||||
WGPUFenceCompletionStatus status) {
|
||||
// The fence might have been deleted or recreated so this isn't an error.
|
||||
if (fence == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return fence->OnCompletionCallback(requestSerial, status);
|
||||
}
|
||||
|
||||
bool Client::DoQueueWorkDoneCallback(Queue* queue,
|
||||
uint64_t requestSerial,
|
||||
WGPUQueueWorkDoneStatus status) {
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright 2019 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/Fence.h"
|
||||
|
||||
#include "dawn_wire/client/Client.h"
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
Fence::~Fence() {
|
||||
// Callbacks need to be fired in all cases, as they can handle freeing resources
|
||||
// so we call them with "Unknown" status.
|
||||
for (auto& it : mOnCompletionRequests) {
|
||||
if (it.second.callback) {
|
||||
it.second.callback(WGPUFenceCompletionStatus_Unknown, it.second.userdata);
|
||||
}
|
||||
}
|
||||
mOnCompletionRequests.clear();
|
||||
}
|
||||
|
||||
void Fence::CancelCallbacksForDisconnect() {
|
||||
for (auto& it : mOnCompletionRequests) {
|
||||
if (it.second.callback) {
|
||||
it.second.callback(WGPUFenceCompletionStatus_DeviceLost, it.second.userdata);
|
||||
}
|
||||
}
|
||||
mOnCompletionRequests.clear();
|
||||
}
|
||||
|
||||
void Fence::Initialize(const WGPUFenceDescriptor* descriptor) {
|
||||
mCompletedValue = descriptor != nullptr ? descriptor->initialValue : 0u;
|
||||
}
|
||||
|
||||
void Fence::OnCompletion(uint64_t value,
|
||||
WGPUFenceOnCompletionCallback callback,
|
||||
void* userdata) {
|
||||
if (client->IsDisconnected()) {
|
||||
callback(WGPUFenceCompletionStatus_DeviceLost, userdata);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t serial = mOnCompletionRequestSerial++;
|
||||
ASSERT(mOnCompletionRequests.find(serial) == mOnCompletionRequests.end());
|
||||
|
||||
FenceOnCompletionCmd cmd;
|
||||
cmd.fenceId = this->id;
|
||||
cmd.value = value;
|
||||
cmd.requestSerial = serial;
|
||||
|
||||
mOnCompletionRequests[serial] = {callback, userdata};
|
||||
|
||||
client->SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
void Fence::OnUpdateCompletedValueCallback(uint64_t value) {
|
||||
mCompletedValue = value;
|
||||
}
|
||||
|
||||
bool Fence::OnCompletionCallback(uint64_t requestSerial, WGPUFenceCompletionStatus status) {
|
||||
auto requestIt = mOnCompletionRequests.find(requestSerial);
|
||||
if (requestIt == mOnCompletionRequests.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the request data so that the callback cannot be called again.
|
||||
// ex.) inside the callback: if the fence is deleted, all callbacks reject.
|
||||
OnCompletionData request = std::move(requestIt->second);
|
||||
mOnCompletionRequests.erase(requestIt);
|
||||
|
||||
request.callback(status, request.userdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t Fence::GetCompletedValue() const {
|
||||
return mCompletedValue;
|
||||
}
|
||||
|
||||
}} // namespace dawn_wire::client
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2019 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 DAWNWIRE_CLIENT_FENCE_H_
|
||||
#define DAWNWIRE_CLIENT_FENCE_H_
|
||||
|
||||
#include <dawn/webgpu.h>
|
||||
|
||||
#include "common/SerialMap.h"
|
||||
#include "dawn_wire/client/ObjectBase.h"
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
class Queue;
|
||||
class Fence final : public ObjectBase {
|
||||
public:
|
||||
using ObjectBase::ObjectBase;
|
||||
~Fence();
|
||||
void Initialize(const WGPUFenceDescriptor* descriptor);
|
||||
|
||||
void CheckPassedFences();
|
||||
void OnCompletion(uint64_t value, WGPUFenceOnCompletionCallback callback, void* userdata);
|
||||
void OnUpdateCompletedValueCallback(uint64_t value);
|
||||
bool OnCompletionCallback(uint64_t requestSerial, WGPUFenceCompletionStatus status);
|
||||
|
||||
uint64_t GetCompletedValue() const;
|
||||
|
||||
private:
|
||||
void CancelCallbacksForDisconnect() override;
|
||||
|
||||
struct OnCompletionData {
|
||||
WGPUFenceOnCompletionCallback callback = nullptr;
|
||||
void* userdata = nullptr;
|
||||
};
|
||||
uint64_t mCompletedValue = 0;
|
||||
uint64_t mOnCompletionRequestSerial = 0;
|
||||
std::map<uint64_t, OnCompletionData> mOnCompletionRequests;
|
||||
};
|
||||
|
||||
}} // namespace dawn_wire::client
|
||||
|
||||
#endif // DAWNWIRE_CLIENT_FENCE_H_
|
|
@ -60,20 +60,6 @@ namespace dawn_wire { namespace client {
|
|||
client->SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
WGPUFence Queue::CreateFence(WGPUFenceDescriptor const* descriptor) {
|
||||
auto* allocation = client->FenceAllocator().New(client);
|
||||
|
||||
QueueCreateFenceCmd cmd;
|
||||
cmd.self = ToAPI(this);
|
||||
cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
|
||||
cmd.descriptor = descriptor;
|
||||
client->SerializeCommand(cmd);
|
||||
|
||||
Fence* fence = allocation->object.get();
|
||||
fence->Initialize(descriptor);
|
||||
return ToAPI(fence);
|
||||
}
|
||||
|
||||
void Queue::WriteBuffer(WGPUBuffer cBuffer,
|
||||
uint64_t bufferOffset,
|
||||
const void* data,
|
||||
|
|
|
@ -35,7 +35,6 @@ namespace dawn_wire { namespace client {
|
|||
void OnSubmittedWorkDone(uint64_t signalValue,
|
||||
WGPUQueueWorkDoneCallback callback,
|
||||
void* userdata);
|
||||
WGPUFence CreateFence(const WGPUFenceDescriptor* descriptor);
|
||||
void WriteBuffer(WGPUBuffer cBuffer, uint64_t bufferOffset, const void* data, size_t size);
|
||||
void WriteTexture(const WGPUImageCopyTexture* destination,
|
||||
const void* data,
|
||||
|
|
|
@ -127,20 +127,6 @@ namespace dawn_wire { namespace server {
|
|||
uint64_t requestSerial;
|
||||
};
|
||||
|
||||
struct FenceCompletionUserdata : CallbackUserdata {
|
||||
using CallbackUserdata::CallbackUserdata;
|
||||
|
||||
ObjectHandle fence;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
struct FenceOnCompletionUserdata : CallbackUserdata {
|
||||
using CallbackUserdata::CallbackUserdata;
|
||||
|
||||
ObjectHandle fence;
|
||||
uint64_t requestSerial;
|
||||
};
|
||||
|
||||
struct ShaderModuleGetCompilationInfoUserdata : CallbackUserdata {
|
||||
using CallbackUserdata::CallbackUserdata;
|
||||
|
||||
|
@ -218,10 +204,6 @@ namespace dawn_wire { namespace server {
|
|||
const char* message,
|
||||
ErrorScopeUserdata* userdata);
|
||||
void OnBufferMapAsyncCallback(WGPUBufferMapAsyncStatus status, MapUserdata* userdata);
|
||||
void OnFenceCompletedValueUpdated(WGPUFenceCompletionStatus status,
|
||||
FenceCompletionUserdata* userdata);
|
||||
void OnFenceOnCompletion(WGPUFenceCompletionStatus status,
|
||||
FenceOnCompletionUserdata* userdata);
|
||||
void OnQueueWorkDone(WGPUQueueWorkDoneStatus status, QueueWorkDoneUserdata* userdata);
|
||||
void OnCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus status,
|
||||
WGPUComputePipeline pipeline,
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
// Copyright 2019 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/server/Server.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace dawn_wire { namespace server {
|
||||
|
||||
void Server::OnFenceCompletedValueUpdated(WGPUFenceCompletionStatus status,
|
||||
FenceCompletionUserdata* data) {
|
||||
if (status != WGPUFenceCompletionStatus_Success) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnFenceUpdateCompletedValueCmd cmd;
|
||||
cmd.fence = data->fence;
|
||||
cmd.value = data->value;
|
||||
|
||||
SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
bool Server::DoFenceOnCompletion(ObjectId fenceId, uint64_t value, uint64_t requestSerial) {
|
||||
// The null object isn't valid as `self`
|
||||
if (fenceId == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* fence = FenceObjects().Get(fenceId);
|
||||
if (fence == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto userdata = MakeUserdata<FenceOnCompletionUserdata>();
|
||||
userdata->fence = ObjectHandle{fenceId, fence->generation};
|
||||
userdata->requestSerial = requestSerial;
|
||||
|
||||
mProcs.fenceOnCompletion(
|
||||
fence->handle, value,
|
||||
ForwardToServer<decltype(
|
||||
&Server::OnFenceOnCompletion)>::Func<&Server::OnFenceOnCompletion>(),
|
||||
userdata.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::OnFenceOnCompletion(WGPUFenceCompletionStatus status,
|
||||
FenceOnCompletionUserdata* data) {
|
||||
ReturnFenceOnCompletionCallbackCmd cmd;
|
||||
cmd.fence = data->fence;
|
||||
cmd.requestSerial = data->requestSerial;
|
||||
cmd.status = status;
|
||||
|
||||
SerializeCommand(cmd);
|
||||
}
|
||||
|
||||
}} // namespace dawn_wire::server
|
|
@ -17,29 +17,6 @@
|
|||
|
||||
namespace dawn_wire { namespace server {
|
||||
|
||||
bool Server::DoQueueSignal(WGPUQueue cSelf, WGPUFence cFence, uint64_t signalValue) {
|
||||
if (cFence == nullptr) {
|
||||
return false;
|
||||
}
|
||||
mProcs.queueSignal(cSelf, cFence, signalValue);
|
||||
|
||||
ObjectId fenceId = FenceObjectIdTable().Get(cFence);
|
||||
ASSERT(fenceId != 0);
|
||||
auto* fence = FenceObjects().Get(fenceId);
|
||||
ASSERT(fence != nullptr);
|
||||
|
||||
auto userdata = MakeUserdata<FenceCompletionUserdata>();
|
||||
userdata->fence = ObjectHandle{fenceId, fence->generation};
|
||||
userdata->value = signalValue;
|
||||
|
||||
mProcs.fenceOnCompletion(
|
||||
cFence, signalValue,
|
||||
ForwardToServer<decltype(&Server::OnFenceCompletedValueUpdated)>::Func<
|
||||
&Server::OnFenceCompletedValueUpdated>(),
|
||||
userdata.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::OnQueueWorkDone(WGPUQueueWorkDoneStatus status, QueueWorkDoneUserdata* data) {
|
||||
ReturnQueueWorkDoneCallbackCmd cmd;
|
||||
cmd.queue = data->queue;
|
||||
|
|
|
@ -197,7 +197,6 @@ test("dawn_unittests") {
|
|||
"unittests/validation/DynamicStateCommandValidationTests.cpp",
|
||||
"unittests/validation/ErrorScopeValidationTests.cpp",
|
||||
"unittests/validation/ExternalTextureTests.cpp",
|
||||
"unittests/validation/FenceValidationTests.cpp",
|
||||
"unittests/validation/GetBindGroupLayoutValidationTests.cpp",
|
||||
"unittests/validation/IndexBufferValidationTests.cpp",
|
||||
"unittests/validation/MinimumBufferSizeValidationTests.cpp",
|
||||
|
@ -232,7 +231,6 @@ test("dawn_unittests") {
|
|||
"unittests/wire/WireDisconnectTests.cpp",
|
||||
"unittests/wire/WireErrorCallbackTests.cpp",
|
||||
"unittests/wire/WireExtensionTests.cpp",
|
||||
"unittests/wire/WireFenceTests.cpp",
|
||||
"unittests/wire/WireInjectDeviceTests.cpp",
|
||||
"unittests/wire/WireInjectSwapChainTests.cpp",
|
||||
"unittests/wire/WireInjectTextureTests.cpp",
|
||||
|
@ -318,7 +316,6 @@ source_set("dawn_end2end_tests_sources") {
|
|||
"end2end/DynamicBufferOffsetTests.cpp",
|
||||
"end2end/EntryPointTests.cpp",
|
||||
"end2end/ExternalTextureTests.cpp",
|
||||
"end2end/FenceTests.cpp",
|
||||
"end2end/FirstIndexOffsetTests.cpp",
|
||||
"end2end/GpuMemorySynchronizationTests.cpp",
|
||||
"end2end/IndexFormatTests.cpp",
|
||||
|
|
|
@ -188,11 +188,6 @@ TEST_P(DeprecationTests, BindGroupLayoutEntryViewDimensionDefaulting) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test that fences are deprecated.
|
||||
TEST_P(DeprecationTests, CreateFence) {
|
||||
EXPECT_DEPRECATION_WARNING(queue.CreateFence());
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(DeprecationTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
|
|
|
@ -35,23 +35,6 @@ static void ToMockDeviceLostCallback(const char* message, void* userdata) {
|
|||
self->StartExpectDeviceError();
|
||||
}
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
|
||||
static void ToMockFenceOnCompletionFails(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
EXPECT_EQ(WGPUFenceCompletionStatus_DeviceLost, status);
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
}
|
||||
static void ToMockFenceOnCompletionSucceeds(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
EXPECT_EQ(WGPUFenceCompletionStatus_Success, status);
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
}
|
||||
|
||||
class MockQueueWorkDoneCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||
|
@ -70,13 +53,11 @@ class DeviceLostTest : public DawnTest {
|
|||
DawnTest::SetUp();
|
||||
DAWN_SKIP_TEST_IF(UsesWire());
|
||||
mockDeviceLostCallback = std::make_unique<MockDeviceLostCallback>();
|
||||
mockFenceOnCompletionCallback = std::make_unique<MockFenceOnCompletionCallback>();
|
||||
mockQueueWorkDoneCallback = std::make_unique<MockQueueWorkDoneCallback>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
mockDeviceLostCallback = nullptr;
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
mockQueueWorkDoneCallback = nullptr;
|
||||
DawnTest::TearDown();
|
||||
}
|
||||
|
@ -416,67 +397,6 @@ TEST_P(DeviceLostTest, CommandEncoderFinishFails) {
|
|||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Test that CreateFenceFails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateFenceFails) {
|
||||
SetCallbackAndLoseForTesting();
|
||||
|
||||
EXPECT_DEPRECATION_WARNING(ASSERT_DEVICE_ERROR(queue.CreateFence()));
|
||||
}
|
||||
|
||||
// Test that queue signal fails when device is lost
|
||||
TEST_P(DeviceLostTest, QueueSignalFenceFails) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
SetCallbackAndLoseForTesting();
|
||||
|
||||
ASSERT_DEVICE_ERROR(queue.Signal(fence, 3));
|
||||
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, nullptr))
|
||||
.Times(1);
|
||||
ASSERT_DEVICE_ERROR(fence.OnCompletion(2u, ToMockFenceOnCompletionFails, nullptr));
|
||||
|
||||
// completed value should not have changed from initial value
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 0u);
|
||||
}
|
||||
|
||||
// Test that Fence On Completion fails after device is lost
|
||||
TEST_P(DeviceLostTest, FenceOnCompletionFails) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
SetCallbackAndLoseForTesting();
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, nullptr))
|
||||
.Times(1);
|
||||
ASSERT_DEVICE_ERROR(fence.OnCompletion(2u, ToMockFenceOnCompletionFails, nullptr));
|
||||
ASSERT_DEVICE_ERROR(device.Tick());
|
||||
|
||||
// completed value is the last value signaled (all previous GPU operations are as if completed)
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
// Test that Fence::OnCompletion callbacks with device lost status when device is lost after calling
|
||||
// OnCompletion
|
||||
TEST_P(DeviceLostTest, FenceOnCompletionBeforeLossFails) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, nullptr))
|
||||
.Times(1);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletionFails, nullptr);
|
||||
SetCallbackAndLoseForTesting();
|
||||
ASSERT_DEVICE_ERROR(device.Tick());
|
||||
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
// Test that QueueOnSubmittedWorkDone fails after device is lost.
|
||||
TEST_P(DeviceLostTest, QueueOnSubmittedWorkDoneFails) {
|
||||
SetCallbackAndLoseForTesting();
|
||||
|
@ -499,36 +419,6 @@ TEST_P(DeviceLostTest, QueueOnSubmittedWorkDoneBeforeLossFails) {
|
|||
ASSERT_DEVICE_ERROR(device.Tick());
|
||||
}
|
||||
|
||||
// Regression test for the Null backend not properly setting the completedSerial when
|
||||
// WaitForIdleForDestruction is called, causing the fence signaling to not be retired and an
|
||||
// ASSERT to fire.
|
||||
TEST_P(DeviceLostTest, AfterSubmitAndSerial) {
|
||||
queue.Submit(0, nullptr);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 1);
|
||||
SetCallbackAndLoseForTesting();
|
||||
}
|
||||
|
||||
// Test that when you Signal, then Tick, then device lost, the fence completed value would be 2
|
||||
TEST_P(DeviceLostTest, FenceSignalTickOnCompletion) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
WaitForAllOperations();
|
||||
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.Times(1);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletionSucceeds, nullptr);
|
||||
SetCallbackAndLoseForTesting();
|
||||
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
// Test that LostForTesting can only be called on one time
|
||||
TEST_P(DeviceLostTest, LoseForTestingOnce) {
|
||||
// First LoseForTesting call should occur normally
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
// Copyright 2018 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 <gmock/gmock.h>
|
||||
#include "tests/DawnTest.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
using namespace testing;
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
|
||||
static void ToMockFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class MockPopErrorScopeCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUErrorType type, const char* message, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockPopErrorScopeCallback> mockPopErrorScopeCallback;
|
||||
static void ToMockPopErrorScopeCallback(WGPUErrorType type, const char* message, void* userdata) {
|
||||
mockPopErrorScopeCallback->Call(type, message, userdata);
|
||||
}
|
||||
|
||||
class FenceTests : public DawnTest {
|
||||
private:
|
||||
struct CallbackInfo {
|
||||
FenceTests* test;
|
||||
uint64_t value;
|
||||
WGPUFenceCompletionStatus status;
|
||||
int32_t callIndex = -1; // If this is -1, the callback was not called
|
||||
|
||||
void Update(WGPUFenceCompletionStatus status) {
|
||||
this->callIndex = test->mCallIndex++;
|
||||
this->status = status;
|
||||
}
|
||||
};
|
||||
|
||||
int32_t mCallIndex;
|
||||
|
||||
protected:
|
||||
FenceTests() : mCallIndex(0) {
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
DawnTest::SetUp();
|
||||
mockFenceOnCompletionCallback = std::make_unique<MockFenceOnCompletionCallback>();
|
||||
mockPopErrorScopeCallback = std::make_unique<MockPopErrorScopeCallback>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
mockPopErrorScopeCallback = nullptr;
|
||||
DawnTest::TearDown();
|
||||
}
|
||||
|
||||
void WaitForCompletedValue(wgpu::Fence fence, uint64_t completedValue) {
|
||||
while (fence.GetCompletedValue() < completedValue) {
|
||||
WaitABit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Test that signaling a fence updates the completed value
|
||||
TEST_P(FenceTests, SimpleSignal) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1u;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
// Completed value starts at initial value
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 1u);
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
WaitForCompletedValue(fence, 2);
|
||||
|
||||
// Completed value updates to signaled value
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
// Test callbacks are called in increasing order of fence completion value
|
||||
TEST_P(FenceTests, OnCompletionOrdering) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
{
|
||||
testing::InSequence s;
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Success, this + 0))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Success, this + 1))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Success, this + 3))
|
||||
.Times(1);
|
||||
}
|
||||
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, this + 2);
|
||||
fence.OnCompletion(0u, ToMockFenceOnCompletion, this + 0);
|
||||
fence.OnCompletion(3u, ToMockFenceOnCompletion, this + 3);
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 1);
|
||||
|
||||
WaitForCompletedValue(fence, 4);
|
||||
}
|
||||
|
||||
// Test callbacks still occur if Queue::Signal happens multiple times
|
||||
TEST_P(FenceTests, MultipleSignalOnCompletion) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.Times(1);
|
||||
fence.OnCompletion(3u, ToMockFenceOnCompletion, nullptr);
|
||||
|
||||
WaitForCompletedValue(fence, 4);
|
||||
}
|
||||
|
||||
// Test callbacks still occur if Queue::Signal and fence::OnCompletion happens multiple times
|
||||
TEST_P(FenceTests, SignalOnCompletionWait) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
queue.Signal(fence, 6);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 6))
|
||||
.Times(1);
|
||||
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 2);
|
||||
fence.OnCompletion(5u, ToMockFenceOnCompletion, this + 6);
|
||||
|
||||
WaitForCompletedValue(fence, 6);
|
||||
}
|
||||
|
||||
// Test callbacks still occur if Queue::Signal and fence::OnCompletion happens multiple times
|
||||
TEST_P(FenceTests, SignalOnCompletionWaitStaggered) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 2);
|
||||
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 4))
|
||||
.Times(1);
|
||||
fence.OnCompletion(3u, ToMockFenceOnCompletion, this + 4);
|
||||
|
||||
WaitForCompletedValue(fence, 4);
|
||||
}
|
||||
|
||||
// Test all callbacks are called if they are added for the same fence value
|
||||
TEST_P(FenceTests, OnCompletionMultipleCallbacks) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 0))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 1))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 3))
|
||||
.Times(1);
|
||||
|
||||
fence.OnCompletion(4u, ToMockFenceOnCompletion, this + 0);
|
||||
fence.OnCompletion(4u, ToMockFenceOnCompletion, this + 1);
|
||||
fence.OnCompletion(4u, ToMockFenceOnCompletion, this + 2);
|
||||
fence.OnCompletion(4u, ToMockFenceOnCompletion, this + 3);
|
||||
|
||||
WaitForCompletedValue(fence, 4u);
|
||||
}
|
||||
|
||||
// TODO(enga): Enable when fence is removed from fence signal tracker
|
||||
// Currently it holds a reference and is not destructed
|
||||
TEST_P(FenceTests, DISABLED_DestroyBeforeOnCompletionEnd) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
// The fence in this block will be deleted when it goes out of scope
|
||||
{
|
||||
wgpu::Fence testFence;
|
||||
EXPECT_DEPRECATION_WARNING(testFence = queue.CreateFence());
|
||||
|
||||
queue.Signal(testFence, 4);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Unknown, this + 0))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Unknown, this + 1))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Unknown, this + 2))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Unknown, this + 3))
|
||||
.Times(1);
|
||||
|
||||
testFence.OnCompletion(1u, ToMockFenceOnCompletion, this + 0);
|
||||
testFence.OnCompletion(2u, ToMockFenceOnCompletion, this + 1);
|
||||
testFence.OnCompletion(2u, ToMockFenceOnCompletion, this + 2);
|
||||
testFence.OnCompletion(3u, ToMockFenceOnCompletion, this + 3);
|
||||
}
|
||||
|
||||
// Wait for another fence to be sure all callbacks have cleared
|
||||
queue.Signal(fence, 1);
|
||||
WaitForCompletedValue(fence, 1);
|
||||
}
|
||||
|
||||
// Regression test that validation errors that are tracked client-side are captured
|
||||
// in error scopes.
|
||||
TEST_P(FenceTests, ClientValidationErrorInErrorScope) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
device.PushErrorScope(wgpu::ErrorFilter::Validation);
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
EXPECT_CALL(*mockPopErrorScopeCallback, Call(WGPUErrorType_Validation, _, this)).Times(1);
|
||||
device.PopErrorScope(ToMockPopErrorScopeCallback, this);
|
||||
|
||||
WaitForCompletedValue(fence, 4);
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(FenceTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
OpenGLBackend(),
|
||||
OpenGLESBackend(),
|
||||
VulkanBackend());
|
|
@ -28,17 +28,6 @@ static void ToMockMapCallback(WGPUBufferMapAsyncStatus status, void* userdata) {
|
|||
mockMapCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
|
||||
static void ToMockFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
EXPECT_EQ(status, WGPUFenceCompletionStatus_Success);
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class MockQueueWorkDoneCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||
|
@ -55,7 +44,6 @@ class QueueTimelineTests : public DawnTest {
|
|||
DawnTest::SetUp();
|
||||
|
||||
mockMapCallback = std::make_unique<MockMapCallback>();
|
||||
mockFenceOnCompletionCallback = std::make_unique<MockFenceOnCompletionCallback>();
|
||||
mockQueueWorkDoneCallback = std::make_unique<MockQueueWorkDoneCallback>();
|
||||
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
|
@ -66,7 +54,6 @@ class QueueTimelineTests : public DawnTest {
|
|||
|
||||
void TearDown() override {
|
||||
mockMapCallback = nullptr;
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
mockQueueWorkDoneCallback = nullptr;
|
||||
DawnTest::TearDown();
|
||||
}
|
||||
|
@ -74,27 +61,6 @@ class QueueTimelineTests : public DawnTest {
|
|||
wgpu::Buffer mMapReadBuffer;
|
||||
};
|
||||
|
||||
// Test that mMapReadBuffer.MapAsync callback happens before fence.OnCompletion callback
|
||||
// when queue.Signal is called after mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called.
|
||||
TEST_P(QueueTimelineTests, MapReadSignalOnComplete) {
|
||||
testing::InSequence sequence;
|
||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this))
|
||||
.Times(1);
|
||||
|
||||
mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, 0, ToMockMapCallback, this);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 1);
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this);
|
||||
|
||||
WaitForAllOperations();
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test that mMapReadBuffer.MapAsync callback happens before queue.OnWorkDone callback
|
||||
// when queue.OnSubmittedWorkDone is called after mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called.
|
||||
|
@ -111,26 +77,6 @@ TEST_P(QueueTimelineTests, MapRead_OnWorkDone) {
|
|||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test that fence.OnCompletion callback happens before mMapReadBuffer.MapAsync callback when
|
||||
// queue.OnSubmittedWorkDone is called before mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called.
|
||||
TEST_P(QueueTimelineTests, SignalMapReadOnComplete) {
|
||||
testing::InSequence sequence;
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, 0, ToMockMapCallback, this);
|
||||
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, this);
|
||||
WaitForAllOperations();
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test that queue.OnWorkDone callback happens before mMapReadBuffer.MapAsync callback when
|
||||
// queue.Signal is called before mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called.
|
||||
|
@ -147,65 +93,6 @@ TEST_P(QueueTimelineTests, OnWorkDone_MapRead) {
|
|||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test that fence.OnCompletion callback happens before mMapReadBuffer.MapAsync callback when
|
||||
// queue.Signal is called before mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called
|
||||
TEST_P(QueueTimelineTests, SignalOnCompleteMapRead) {
|
||||
testing::InSequence sequence;
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, this);
|
||||
|
||||
mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, 0, ToMockMapCallback, this);
|
||||
|
||||
WaitForAllOperations();
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test a complicated case with many signals surrounding a buffer mapping.
|
||||
TEST_P(QueueTimelineTests, SurroundWithFenceSignals) {
|
||||
testing::InSequence sequence;
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 0))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 3))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 5))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 6))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 8))
|
||||
.Times(1);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 2);
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 0);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, this + 2);
|
||||
|
||||
mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, 0, ToMockMapCallback, this);
|
||||
queue.Signal(fence, 6);
|
||||
fence.OnCompletion(3u, ToMockFenceOnCompletion, this + 3);
|
||||
fence.OnCompletion(5u, ToMockFenceOnCompletion, this + 5);
|
||||
fence.OnCompletion(6u, ToMockFenceOnCompletion, this + 6);
|
||||
|
||||
queue.Signal(fence, 8);
|
||||
fence.OnCompletion(8u, ToMockFenceOnCompletion, this + 8);
|
||||
|
||||
WaitForAllOperations();
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(QueueTimelineTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
|
|
|
@ -31,11 +31,22 @@ static void ToMockDevicePopErrorScopeCallback(WGPUErrorType type,
|
|||
mockDevicePopErrorScopeCallback->Call(type, message, userdata);
|
||||
}
|
||||
|
||||
class MockQueueWorkDoneCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockQueueWorkDoneCallback> mockQueueWorkDoneCallback;
|
||||
static void ToMockQueueWorkDone(WGPUQueueWorkDoneStatus status, void* userdata) {
|
||||
mockQueueWorkDoneCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class ErrorScopeValidationTest : public ValidationTest {
|
||||
private:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
mockDevicePopErrorScopeCallback = std::make_unique<MockDevicePopErrorScopeCallback>();
|
||||
mockQueueWorkDoneCallback = std::make_unique<MockQueueWorkDoneCallback>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
|
@ -43,6 +54,7 @@ class ErrorScopeValidationTest : public ValidationTest {
|
|||
|
||||
// Delete mocks so that expectations are checked
|
||||
mockDevicePopErrorScopeCallback = nullptr;
|
||||
mockQueueWorkDoneCallback = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -141,31 +153,6 @@ TEST_F(ErrorScopeValidationTest, PushPopBalanced) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test that error scopes call their callbacks before an enclosed Queue::Submit
|
||||
// completes
|
||||
TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmit) {
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
|
||||
device.PushErrorScope(wgpu::ErrorFilter::OutOfMemory);
|
||||
|
||||
queue.Submit(0, nullptr);
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 1);
|
||||
|
||||
testing::Sequence seq;
|
||||
|
||||
MockCallback<WGPUFenceOnCompletionCallback> fenceCallback;
|
||||
fence.OnCompletion(1, fenceCallback.Callback(), fenceCallback.MakeUserdata(this));
|
||||
|
||||
MockCallback<WGPUErrorCallback> errorScopeCallback;
|
||||
EXPECT_CALL(errorScopeCallback, Call(WGPUErrorType_NoError, _, this + 1)).InSequence(seq);
|
||||
device.PopErrorScope(errorScopeCallback.Callback(), errorScopeCallback.MakeUserdata(this + 1));
|
||||
|
||||
EXPECT_CALL(fenceCallback, Call(WGPUFenceCompletionStatus_Success, this)).InSequence(seq);
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
// Test that parent error scopes also call their callbacks before an enclosed Queue::Submit
|
||||
// completes
|
||||
TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmitNested) {
|
||||
|
@ -175,15 +162,10 @@ TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmitNested) {
|
|||
device.PushErrorScope(wgpu::ErrorFilter::OutOfMemory);
|
||||
|
||||
queue.Submit(0, nullptr);
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 1);
|
||||
queue.OnSubmittedWorkDone(0u, ToMockQueueWorkDone, this);
|
||||
|
||||
testing::Sequence seq;
|
||||
|
||||
MockCallback<WGPUFenceOnCompletionCallback> fenceCallback;
|
||||
fence.OnCompletion(1, fenceCallback.Callback(), fenceCallback.MakeUserdata(this));
|
||||
|
||||
MockCallback<WGPUErrorCallback> errorScopeCallback2;
|
||||
EXPECT_CALL(errorScopeCallback2, Call(WGPUErrorType_NoError, _, this + 1)).InSequence(seq);
|
||||
device.PopErrorScope(errorScopeCallback2.Callback(),
|
||||
|
@ -194,7 +176,8 @@ TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmitNested) {
|
|||
device.PopErrorScope(errorScopeCallback1.Callback(),
|
||||
errorScopeCallback1.MakeUserdata(this + 2));
|
||||
|
||||
EXPECT_CALL(fenceCallback, Call(WGPUFenceCompletionStatus_Success, this)).InSequence(seq);
|
||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this))
|
||||
.InSequence(seq);
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
// Copyright 2018 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 <gmock/gmock.h>
|
||||
|
||||
using namespace testing;
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
struct FenceOnCompletionExpectation {
|
||||
wgpu::Fence fence;
|
||||
uint64_t value;
|
||||
WGPUFenceCompletionStatus status;
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
|
||||
static void ToMockFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class FenceValidationTest : public ValidationTest {
|
||||
protected:
|
||||
void TestOnCompletion(wgpu::Fence fence, uint64_t value, WGPUFenceCompletionStatus status) {
|
||||
FenceOnCompletionExpectation* expectation = new FenceOnCompletionExpectation;
|
||||
expectation->fence = fence;
|
||||
expectation->value = value;
|
||||
expectation->status = status;
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(status, expectation)).Times(1);
|
||||
fence.OnCompletion(value, ToMockFenceOnCompletion, expectation);
|
||||
}
|
||||
|
||||
wgpu::Queue queue;
|
||||
|
||||
private:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
|
||||
mockFenceOnCompletionCallback = std::make_unique<MockFenceOnCompletionCallback>();
|
||||
queue = device.GetQueue();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Delete mocks so that expectations are checked
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
|
||||
ValidationTest::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
// Test cases where creation should succeed
|
||||
TEST_F(FenceValidationTest, CreationSuccess) {
|
||||
// Success
|
||||
{
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 0;
|
||||
EXPECT_DEPRECATION_WARNING(queue.CreateFence(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Creation succeeds if no descriptor is provided
|
||||
TEST_F(FenceValidationTest, DefaultDescriptor) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, GetCompletedValue) {
|
||||
// Starts at initial value
|
||||
{
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 1u);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that OnCompletion handlers are called immediately for
|
||||
// already completed fence values
|
||||
TEST_F(FenceValidationTest, OnCompletionImmediate) {
|
||||
// TODO(crbug.com/dawn/653): This has wrong different behavior on the wire, but fences will be
|
||||
// removed soon.
|
||||
DAWN_SKIP_TEST_IF(UsesWire());
|
||||
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 0))
|
||||
.Times(1);
|
||||
fence.OnCompletion(0u, ToMockFenceOnCompletion, this + 0);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 1))
|
||||
.Times(1);
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 1);
|
||||
}
|
||||
|
||||
// Test setting OnCompletion handlers for values > signaled value
|
||||
TEST_F(FenceValidationTest, OnCompletionLargerThanSignaled) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
// Cannot signal for values > signaled value
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Error, nullptr))
|
||||
.Times(1);
|
||||
ASSERT_DEVICE_ERROR(fence.OnCompletion(2u, ToMockFenceOnCompletion, nullptr));
|
||||
|
||||
// Can set handler after signaling
|
||||
queue.Signal(fence, 2);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.Times(1);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, nullptr);
|
||||
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, GetCompletedValueInsideCallback) {
|
||||
// TODO(crbug.com/dawn/653): This has wrong different behavior on the wire, but fences will be
|
||||
// removed soon.
|
||||
DAWN_SKIP_TEST_IF(UsesWire());
|
||||
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
queue.Signal(fence, 3);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.WillOnce(Invoke([&](WGPUFenceCompletionStatus status, void* userdata) {
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 3u);
|
||||
}));
|
||||
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, GetCompletedValueAfterCallback) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.Times(1);
|
||||
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, SignalError) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
// value < fence signaled value
|
||||
ASSERT_DEVICE_ERROR(queue.Signal(fence, 0));
|
||||
|
||||
// value == fence signaled value
|
||||
ASSERT_DEVICE_ERROR(queue.Signal(fence, 1));
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, SignalSuccess) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
// Success
|
||||
queue.Signal(fence, 2);
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
|
||||
// Success increasing fence value by more than 1
|
||||
queue.Signal(fence, 6);
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 6u);
|
||||
}
|
||||
|
||||
// Test it is invalid to signal a fence on a different queue than it was created on
|
||||
// DISABLED until we have support for multiple queues
|
||||
TEST_F(FenceValidationTest, DISABLED_SignalWrongQueue) {
|
||||
wgpu::Queue queue2 = device.GetQueue();
|
||||
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
ASSERT_DEVICE_ERROR(queue2.Signal(fence, 2));
|
||||
}
|
||||
|
||||
// Test that signaling a fence on a wrong queue does not update fence signaled value
|
||||
// DISABLED until we have support for multiple queues
|
||||
TEST_F(FenceValidationTest, DISABLED_SignalWrongQueueDoesNotUpdateValue) {
|
||||
wgpu::Queue queue2 = device.GetQueue();
|
||||
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
ASSERT_DEVICE_ERROR(queue2.Signal(fence, 2));
|
||||
|
||||
// Fence value should be unchanged.
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 1u);
|
||||
|
||||
// Signaling with 2 on the correct queue should succeed
|
||||
queue.Signal(fence, 2);
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
// Copyright 2019 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/wire/WireTest.h"
|
||||
|
||||
#include "dawn_wire/WireClient.h"
|
||||
|
||||
using namespace testing;
|
||||
using namespace dawn_wire;
|
||||
|
||||
namespace {
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
std::unique_ptr<StrictMock<MockFenceOnCompletionCallback>> mockFenceOnCompletionCallback;
|
||||
void ToMockFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class WireFenceTests : public WireTest {
|
||||
public:
|
||||
WireFenceTests() {
|
||||
}
|
||||
~WireFenceTests() override = default;
|
||||
|
||||
void SetUp() override {
|
||||
WireTest::SetUp();
|
||||
|
||||
mockFenceOnCompletionCallback =
|
||||
std::make_unique<StrictMock<MockFenceOnCompletionCallback>>();
|
||||
|
||||
{
|
||||
WGPUFenceDescriptor descriptor = {};
|
||||
descriptor.initialValue = 1;
|
||||
|
||||
apiFence = api.GetNewFence();
|
||||
fence = wgpuQueueCreateFence(queue, &descriptor);
|
||||
|
||||
EXPECT_CALL(api, QueueCreateFence(apiQueue, _)).WillOnce(Return(apiFence));
|
||||
FlushClient();
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
WireTest::TearDown();
|
||||
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
}
|
||||
|
||||
void FlushServer() {
|
||||
WireTest::FlushServer();
|
||||
|
||||
Mock::VerifyAndClearExpectations(&mockFenceOnCompletionCallback);
|
||||
}
|
||||
|
||||
protected:
|
||||
void DoQueueSignal(uint64_t signalValue,
|
||||
WGPUFenceCompletionStatus status = WGPUFenceCompletionStatus_Success) {
|
||||
wgpuQueueSignal(queue, fence, signalValue);
|
||||
EXPECT_CALL(api, QueueSignal(apiQueue, apiFence, signalValue)).Times(1);
|
||||
|
||||
// This callback is generated to update the completedValue of the fence
|
||||
// on the client
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, signalValue, _, _))
|
||||
.WillOnce(
|
||||
InvokeWithoutArgs([=]() { api.CallFenceOnCompletionCallback(apiFence, status); }))
|
||||
.RetiresOnSaturation();
|
||||
}
|
||||
|
||||
// A successfully created fence
|
||||
WGPUFence fence;
|
||||
WGPUFence apiFence;
|
||||
};
|
||||
|
||||
// Check that signaling a fence succeeds
|
||||
TEST_F(WireFenceTests, QueueSignalSuccess) {
|
||||
DoQueueSignal(2u);
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 2u);
|
||||
}
|
||||
|
||||
// Check that signaling a fence twice succeeds
|
||||
TEST_F(WireFenceTests, QueueSignalIncreasing) {
|
||||
DoQueueSignal(2u);
|
||||
DoQueueSignal(3u);
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 3u);
|
||||
}
|
||||
|
||||
// Check that an error in queue signal does not update the completed value.
|
||||
TEST_F(WireFenceTests, QueueSignalValidationError) {
|
||||
DoQueueSignal(2u);
|
||||
DoQueueSignal(1u, WGPUFenceCompletionStatus_Error);
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
|
||||
// Value should stay at 2 and not be updated to 1.
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 2u);
|
||||
}
|
||||
|
||||
// Check that a success in the on completion callback is forwarded to the client.
|
||||
TEST_F(WireFenceTests, OnCompletionSuccess) {
|
||||
wgpuFenceOnCompletion(fence, 0, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, 0u, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallFenceOnCompletionCallback(apiFence, WGPUFenceCompletionStatus_Success);
|
||||
}));
|
||||
FlushClient();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, _))
|
||||
.Times(1);
|
||||
FlushServer();
|
||||
}
|
||||
|
||||
// Check that an error in the on completion callback is forwarded to the client.
|
||||
TEST_F(WireFenceTests, OnCompletionError) {
|
||||
wgpuFenceOnCompletion(fence, 0, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, 0u, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallFenceOnCompletionCallback(apiFence, WGPUFenceCompletionStatus_Error);
|
||||
}));
|
||||
FlushClient();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Error, _)).Times(1);
|
||||
FlushServer();
|
||||
}
|
||||
|
||||
// Test that registering a callback then wire disconnect calls the callback with
|
||||
// DeviceLost.
|
||||
TEST_F(WireFenceTests, OnCompletionThenDisconnect) {
|
||||
wgpuFenceOnCompletion(fence, 0, ToMockFenceOnCompletion, this);
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, 0u, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallFenceOnCompletionCallback(apiFence, WGPUFenceCompletionStatus_Success);
|
||||
}));
|
||||
FlushClient();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, this))
|
||||
.Times(1);
|
||||
GetWireClient()->Disconnect();
|
||||
}
|
||||
|
||||
// Test that registering a callback after wire disconnect calls the callback with
|
||||
// DeviceLost.
|
||||
TEST_F(WireFenceTests, OnCompletionAfterDisconnect) {
|
||||
GetWireClient()->Disconnect();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, this))
|
||||
.Times(1);
|
||||
wgpuFenceOnCompletion(fence, 0, ToMockFenceOnCompletion, this);
|
||||
}
|
||||
|
||||
// Without any flushes, it is valid to wait on a value less than or equal to
|
||||
// the last signaled value
|
||||
TEST_F(WireFenceTests, OnCompletionSynchronousValidationSuccess) {
|
||||
wgpuQueueSignal(queue, fence, 4u);
|
||||
wgpuFenceOnCompletion(fence, 2u, ToMockFenceOnCompletion, 0);
|
||||
wgpuFenceOnCompletion(fence, 3u, ToMockFenceOnCompletion, 0);
|
||||
wgpuFenceOnCompletion(fence, 4u, ToMockFenceOnCompletion, 0);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Unknown, _))
|
||||
.Times(3);
|
||||
}
|
||||
|
||||
// Check that the fence completed value is initialized
|
||||
TEST_F(WireFenceTests, GetCompletedValueInitialization) {
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 1u);
|
||||
}
|
||||
|
||||
// Check that the fence completed value updates after signaling the fence
|
||||
TEST_F(WireFenceTests, GetCompletedValueUpdate) {
|
||||
DoQueueSignal(3u);
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 3u);
|
||||
}
|
||||
|
||||
// Check that the fence completed value updates after signaling the fence
|
||||
TEST_F(WireFenceTests, GetCompletedValueUpdateInCallback) {
|
||||
// Signal the fence
|
||||
DoQueueSignal(3u);
|
||||
|
||||
// Register the callback
|
||||
wgpuFenceOnCompletion(fence, 3u, ToMockFenceOnCompletion, this);
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, 3u, _, _))
|
||||
.WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallFenceOnCompletionCallback(apiFence, WGPUFenceCompletionStatus_Success);
|
||||
}))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
FlushClient();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this))
|
||||
.WillOnce(InvokeWithoutArgs([&]() { EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 3u); }));
|
||||
FlushServer();
|
||||
}
|
||||
|
||||
// Check that the fence completed value does not update without a flush
|
||||
TEST_F(WireFenceTests, GetCompletedValueNoUpdate) {
|
||||
wgpuQueueSignal(queue, fence, 3u);
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 1u);
|
||||
}
|
||||
|
||||
// Check that the callback is called with UNKNOWN when the fence is destroyed
|
||||
// before the completed value is updated
|
||||
TEST_F(WireFenceTests, DestroyBeforeOnCompletionEnd) {
|
||||
wgpuQueueSignal(queue, fence, 3u);
|
||||
wgpuFenceOnCompletion(fence, 2u, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Unknown, _))
|
||||
.Times(1);
|
||||
}
|
||||
|
||||
// Test that signaling a fence on a wrong queue is invalid
|
||||
// DISABLED until we have support for multiple queues.
|
||||
TEST_F(WireFenceTests, DISABLED_SignalWrongQueue) {
|
||||
WGPUQueue queue2 = wgpuDeviceGetQueue(device);
|
||||
WGPUQueue apiQueue2 = api.GetNewQueue();
|
||||
EXPECT_CALL(api, DeviceGetQueue(apiDevice)).WillOnce(Return(apiQueue2));
|
||||
FlushClient();
|
||||
|
||||
wgpuQueueSignal(queue2, fence, 2u); // error
|
||||
EXPECT_CALL(api, DeviceInjectError(apiDevice, WGPUErrorType_Validation, ValidStringMessage()))
|
||||
.Times(1);
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test that signaling a fence on a wrong queue does not update fence signaled value
|
||||
// DISABLED until we have support for multiple queues.
|
||||
TEST_F(WireFenceTests, DISABLED_SignalWrongQueueDoesNotUpdateValue) {
|
||||
WGPUQueue queue2 = wgpuDeviceGetQueue(device);
|
||||
WGPUQueue apiQueue2 = api.GetNewQueue();
|
||||
EXPECT_CALL(api, DeviceGetQueue(apiDevice)).WillOnce(Return(apiQueue2));
|
||||
FlushClient();
|
||||
|
||||
wgpuQueueSignal(queue2, fence, 2u); // error
|
||||
EXPECT_CALL(api, DeviceInjectError(apiDevice, WGPUErrorType_Validation, ValidStringMessage()))
|
||||
.Times(1);
|
||||
FlushClient();
|
||||
|
||||
// Fence value should be unchanged.
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 1u);
|
||||
|
||||
// Signaling with 2 on the correct queue should succeed
|
||||
DoQueueSignal(2u); // success
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 2u);
|
||||
}
|
Loading…
Reference in New Issue