mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-11 22:49:16 +00:00
Use QueueBase to track fences in flight and map requests so that they can be resolved in the order they were added. Before these tasks were separately tracked in FenceSignalTracker and MapRequestTracker, so tasks would be resolving out of order. Bug: dawn:404 Change-Id: I8b58fb72c99f43bc4593f56e08920d48ac506157 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/29441 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Natasha Lee <natlee@microsoft.com>
161 lines
5.0 KiB
C++
161 lines
5.0 KiB
C++
// 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);
|
|
}
|
|
~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::GetCompletedValue() const {
|
|
if (IsError()) {
|
|
return 0;
|
|
}
|
|
return uint64_t(mCompletedValue);
|
|
}
|
|
|
|
void Fence::OnCompletion(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) {
|
|
ASSERT(!IsError());
|
|
ASSERT(completedValue <= mSignalValue);
|
|
ASSERT(completedValue > mCompletedValue);
|
|
mCompletedValue = completedValue;
|
|
|
|
for (auto& request : mRequests.IterateUpTo(mCompletedValue)) {
|
|
if (GetDevice()->IsLost()) {
|
|
request.completionCallback(WGPUFenceCompletionStatus_DeviceLost, request.userdata);
|
|
} else {
|
|
request.completionCallback(WGPUFenceCompletionStatus_Success, 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()->GetDefaultQueue()->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
|