Avoid processing already processed tick
To avoid overly ticking, we only want to tick when: 1. the last submitted serial has moved beyond the completed serial 2. or the completed serial has not reached the future command serial added by the trackers (MapRequestTracker, FenceSignalTracker, ErrorScopeTracker). Bug: dawn:400 Change-Id: Ie7c65acc332846ac1a27f9a18f230149d96d2189 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/19062 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Natasha Lee <natlee@microsoft.com>
This commit is contained in:
parent
62b08f845f
commit
783cd5a79c
|
@ -126,7 +126,7 @@ namespace dawn_native {
|
||||||
// complete before proceeding with destruction.
|
// complete before proceeding with destruction.
|
||||||
// Assert that errors are device loss so that we can continue with destruction
|
// Assert that errors are device loss so that we can continue with destruction
|
||||||
AssertAndIgnoreDeviceLossError(WaitForIdleForDestruction());
|
AssertAndIgnoreDeviceLossError(WaitForIdleForDestruction());
|
||||||
ASSERT(mCompletedSerial == mLastSubmittedSerial);
|
AssumeCommandsComplete();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::BeingDisconnected:
|
case State::BeingDisconnected:
|
||||||
|
@ -139,6 +139,8 @@ namespace dawn_native {
|
||||||
case State::Disconnected:
|
case State::Disconnected:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ASSERT(mCompletedSerial == mLastSubmittedSerial);
|
||||||
|
ASSERT(mFutureCallbackSerial <= mCompletedSerial);
|
||||||
|
|
||||||
// Skip handling device facilities if they haven't even been created (or failed doing so)
|
// Skip handling device facilities if they haven't even been created (or failed doing so)
|
||||||
if (mState != State::BeingCreated) {
|
if (mState != State::BeingCreated) {
|
||||||
|
@ -163,6 +165,7 @@ namespace dawn_native {
|
||||||
mDynamicUploader = nullptr;
|
mDynamicUploader = nullptr;
|
||||||
mMapRequestTracker = nullptr;
|
mMapRequestTracker = nullptr;
|
||||||
|
|
||||||
|
AssumeCommandsComplete();
|
||||||
// Tell the backend that it can free all the objects now that the GPU timeline is empty.
|
// Tell the backend that it can free all the objects now that the GPU timeline is empty.
|
||||||
ShutDownImpl();
|
ShutDownImpl();
|
||||||
|
|
||||||
|
@ -181,8 +184,10 @@ namespace dawn_native {
|
||||||
mState = State::BeingDisconnected;
|
mState = State::BeingDisconnected;
|
||||||
|
|
||||||
// Assert that errors are device losses so that we can continue with destruction.
|
// Assert that errors are device losses so that we can continue with destruction.
|
||||||
|
// Assume all commands are complete after WaitForIdleForDestruction (because they were)
|
||||||
AssertAndIgnoreDeviceLossError(WaitForIdleForDestruction());
|
AssertAndIgnoreDeviceLossError(WaitForIdleForDestruction());
|
||||||
ASSERT(mCompletedSerial == mLastSubmittedSerial);
|
AssumeCommandsComplete();
|
||||||
|
ASSERT(mFutureCallbackSerial <= mCompletedSerial);
|
||||||
mState = State::Disconnected;
|
mState = State::Disconnected;
|
||||||
|
|
||||||
// Now everything is as if the device was lost.
|
// Now everything is as if the device was lost.
|
||||||
|
@ -320,24 +325,30 @@ namespace dawn_native {
|
||||||
return mLastSubmittedSerial;
|
return mLastSubmittedSerial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial DeviceBase::GetFutureCallbackSerial() const {
|
||||||
|
return mFutureCallbackSerial;
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceBase::IncrementLastSubmittedCommandSerial() {
|
void DeviceBase::IncrementLastSubmittedCommandSerial() {
|
||||||
mLastSubmittedSerial++;
|
mLastSubmittedSerial++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::ArtificiallyIncrementSerials() {
|
|
||||||
mCompletedSerial++;
|
|
||||||
mLastSubmittedSerial++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceBase::AssumeCommandsComplete() {
|
void DeviceBase::AssumeCommandsComplete() {
|
||||||
mLastSubmittedSerial++;
|
Serial maxSerial = std::max(mLastSubmittedSerial + 1, mFutureCallbackSerial);
|
||||||
mCompletedSerial = mLastSubmittedSerial;
|
mLastSubmittedSerial = maxSerial;
|
||||||
|
mCompletedSerial = maxSerial;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial DeviceBase::GetPendingCommandSerial() const {
|
Serial DeviceBase::GetPendingCommandSerial() const {
|
||||||
return mLastSubmittedSerial + 1;
|
return mLastSubmittedSerial + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceBase::AddFutureCallbackSerial(Serial serial) {
|
||||||
|
if (serial > mFutureCallbackSerial) {
|
||||||
|
mFutureCallbackSerial = serial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceBase::CheckPassedSerials() {
|
void DeviceBase::CheckPassedSerials() {
|
||||||
Serial completedSerial = CheckAndUpdateCompletedSerials();
|
Serial completedSerial = CheckAndUpdateCompletedSerials();
|
||||||
|
|
||||||
|
@ -712,17 +723,32 @@ namespace dawn_native {
|
||||||
if (ConsumedError(ValidateIsAlive())) {
|
if (ConsumedError(ValidateIsAlive())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ConsumedError(TickImpl())) {
|
// to avoid overly ticking, we only want to tick when:
|
||||||
return;
|
// 1. the last submitted serial has moved beyond the completed serial
|
||||||
}
|
// 2. or the completed serial has not reached the future serial set by the trackers
|
||||||
|
if (mLastSubmittedSerial > mCompletedSerial || mCompletedSerial < mFutureCallbackSerial) {
|
||||||
|
CheckPassedSerials();
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): decouple TickImpl from updating the serial so that we can
|
if (ConsumedError(TickImpl())) {
|
||||||
// tick the dynamic uploader before the backend resource allocators. This would allow
|
return;
|
||||||
// reclaiming resources one tick earlier.
|
}
|
||||||
mDynamicUploader->Deallocate(GetCompletedCommandSerial());
|
|
||||||
mErrorScopeTracker->Tick(GetCompletedCommandSerial());
|
// There is no GPU work in flight, we need to move the serials forward so that
|
||||||
mFenceSignalTracker->Tick(GetCompletedCommandSerial());
|
// so that CPU operations waiting on GPU completion can know they don't have to wait.
|
||||||
mMapRequestTracker->Tick(GetCompletedCommandSerial());
|
// AssumeCommandsComplete will assign the max serial we must tick to in order to
|
||||||
|
// fire the awaiting callbacks.
|
||||||
|
if (mCompletedSerial == mLastSubmittedSerial) {
|
||||||
|
AssumeCommandsComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(cwallez@chromium.org): decouple TickImpl from updating the serial so that we can
|
||||||
|
// tick the dynamic uploader before the backend resource allocators. This would allow
|
||||||
|
// reclaiming resources one tick earlier.
|
||||||
|
mDynamicUploader->Deallocate(mCompletedSerial);
|
||||||
|
mErrorScopeTracker->Tick(mCompletedSerial);
|
||||||
|
mFenceSignalTracker->Tick(mCompletedSerial);
|
||||||
|
mMapRequestTracker->Tick(mCompletedSerial);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::Reference() {
|
void DeviceBase::Reference() {
|
||||||
|
|
|
@ -90,6 +90,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
Serial GetCompletedCommandSerial() const;
|
Serial GetCompletedCommandSerial() const;
|
||||||
Serial GetLastSubmittedCommandSerial() const;
|
Serial GetLastSubmittedCommandSerial() const;
|
||||||
|
Serial GetFutureCallbackSerial() const;
|
||||||
Serial GetPendingCommandSerial() const;
|
Serial GetPendingCommandSerial() const;
|
||||||
virtual MaybeError TickImpl() = 0;
|
virtual MaybeError TickImpl() = 0;
|
||||||
|
|
||||||
|
@ -214,6 +215,7 @@ namespace dawn_native {
|
||||||
size_t GetDeprecationWarningCountForTesting();
|
size_t GetDeprecationWarningCountForTesting();
|
||||||
void EmitDeprecationWarning(const char* warning);
|
void EmitDeprecationWarning(const char* warning);
|
||||||
void LoseForTesting();
|
void LoseForTesting();
|
||||||
|
void AddFutureCallbackSerial(Serial serial);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetToggle(Toggle toggle, bool isEnabled);
|
void SetToggle(Toggle toggle, bool isEnabled);
|
||||||
|
@ -224,13 +226,6 @@ namespace dawn_native {
|
||||||
|
|
||||||
// Incrememt mLastSubmittedSerial when we submit the next serial
|
// Incrememt mLastSubmittedSerial when we submit the next serial
|
||||||
void IncrementLastSubmittedCommandSerial();
|
void IncrementLastSubmittedCommandSerial();
|
||||||
// If there's no GPU work in flight we still need to artificially increment the serial
|
|
||||||
// so that CPU operations waiting on GPU completion can know they don't have to wait.
|
|
||||||
void ArtificiallyIncrementSerials();
|
|
||||||
// During shut down of device, some operations might have been started since the last submit
|
|
||||||
// and waiting on a serial that doesn't have a corresponding fence enqueued. Fake serials to
|
|
||||||
// make all commands look completed.
|
|
||||||
void AssumeCommandsComplete();
|
|
||||||
// Check for passed fences and set the new completed serial
|
// Check for passed fences and set the new completed serial
|
||||||
void CheckPassedSerials();
|
void CheckPassedSerials();
|
||||||
|
|
||||||
|
@ -298,14 +293,21 @@ namespace dawn_native {
|
||||||
// Each backend should implement to check their passed fences if there are any and return a
|
// Each backend should implement to check their passed fences if there are any and return a
|
||||||
// completed serial. Return 0 should indicate no fences to check.
|
// completed serial. Return 0 should indicate no fences to check.
|
||||||
virtual Serial CheckAndUpdateCompletedSerials() = 0;
|
virtual Serial CheckAndUpdateCompletedSerials() = 0;
|
||||||
|
// During shut down of device, some operations might have been started since the last submit
|
||||||
|
// and waiting on a serial that doesn't have a corresponding fence enqueued. Fake serials to
|
||||||
|
// make all commands look completed.
|
||||||
|
void AssumeCommandsComplete();
|
||||||
// mCompletedSerial tracks the last completed command serial that the fence has returned.
|
// mCompletedSerial tracks the last completed command serial that the fence has returned.
|
||||||
// mLastSubmittedSerial tracks the last submitted command serial.
|
// mLastSubmittedSerial tracks the last submitted command serial.
|
||||||
// During device removal, the serials could be artificially incremented
|
// During device removal, the serials could be artificially incremented
|
||||||
// to make it appear as if commands have been compeleted. They can also be artificially
|
// to make it appear as if commands have been compeleted. They can also be artificially
|
||||||
// incremented when no work is being done in the GPU so CPU operations don't have to wait on
|
// incremented when no work is being done in the GPU so CPU operations don't have to wait on
|
||||||
// stale serials.
|
// stale serials.
|
||||||
|
// mFutureCallbackSerial tracks the largest serial we need to tick to for the callbacks to
|
||||||
|
// fire
|
||||||
Serial mCompletedSerial = 0;
|
Serial mCompletedSerial = 0;
|
||||||
Serial mLastSubmittedSerial = 0;
|
Serial mLastSubmittedSerial = 0;
|
||||||
|
Serial mFutureCallbackSerial = 0;
|
||||||
|
|
||||||
// ShutDownImpl is used to clean up and release resources used by device, does not wait for
|
// ShutDownImpl is used to clean up and release resources used by device, does not wait for
|
||||||
// GPU or check errors.
|
// GPU or check errors.
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
void ErrorScopeTracker::TrackUntilLastSubmitComplete(ErrorScope* scope) {
|
void ErrorScopeTracker::TrackUntilLastSubmitComplete(ErrorScope* scope) {
|
||||||
mScopesInFlight.Enqueue(scope, mDevice->GetLastSubmittedCommandSerial());
|
mScopesInFlight.Enqueue(scope, mDevice->GetLastSubmittedCommandSerial());
|
||||||
|
mDevice->AddFutureCallbackSerial(mDevice->GetPendingCommandSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorScopeTracker::Tick(Serial completedSerial) {
|
void ErrorScopeTracker::Tick(Serial completedSerial) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace dawn_native {
|
||||||
// the fence completed value once the last submitted serial has passed.
|
// the fence completed value once the last submitted serial has passed.
|
||||||
mFencesInFlight.Enqueue(FenceInFlight{fence, value},
|
mFencesInFlight.Enqueue(FenceInFlight{fence, value},
|
||||||
mDevice->GetLastSubmittedCommandSerial());
|
mDevice->GetLastSubmittedCommandSerial());
|
||||||
|
mDevice->AddFutureCallbackSerial(mDevice->GetPendingCommandSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FenceSignalTracker::Tick(Serial finishedSerial) {
|
void FenceSignalTracker::Tick(Serial finishedSerial) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace dawn_native {
|
||||||
request.isWrite = isWrite;
|
request.isWrite = isWrite;
|
||||||
|
|
||||||
mInflightRequests.Enqueue(std::move(request), mDevice->GetPendingCommandSerial());
|
mInflightRequests.Enqueue(std::move(request), mDevice->GetPendingCommandSerial());
|
||||||
|
mDevice->AddFutureCallbackSerial(mDevice->GetPendingCommandSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapRequestTracker::Tick(Serial finishedSerial) {
|
void MapRequestTracker::Tick(Serial finishedSerial) {
|
||||||
|
|
|
@ -212,8 +212,6 @@ namespace dawn_native { namespace d3d12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
CheckPassedSerials();
|
|
||||||
|
|
||||||
// Perform cleanup operations to free unused objects
|
// Perform cleanup operations to free unused objects
|
||||||
Serial completedSerial = GetCompletedCommandSerial();
|
Serial completedSerial = GetCompletedCommandSerial();
|
||||||
|
|
||||||
|
@ -245,6 +243,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
DAWN_TRY(CheckHRESULT(mFence->SetEventOnCompletion(serial, mFenceEvent),
|
DAWN_TRY(CheckHRESULT(mFence->SetEventOnCompletion(serial, mFenceEvent),
|
||||||
"D3D12 set event on completion"));
|
"D3D12 set event on completion"));
|
||||||
WaitForSingleObject(mFenceEvent, INFINITE);
|
WaitForSingleObject(mFenceEvent, INFINITE);
|
||||||
|
CheckPassedSerials();
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -462,9 +461,6 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
// Call tick one last time so resources are cleaned up.
|
// Call tick one last time so resources are cleaned up.
|
||||||
DAWN_TRY(TickImpl());
|
DAWN_TRY(TickImpl());
|
||||||
|
|
||||||
// Force all operations to look as if they were completed
|
|
||||||
AssumeCommandsComplete();
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,11 +515,6 @@ namespace dawn_native { namespace d3d12 {
|
||||||
// Immediately forget about all pending commands
|
// Immediately forget about all pending commands
|
||||||
mPendingCommands.Release();
|
mPendingCommands.Release();
|
||||||
|
|
||||||
// Some operations might have been started since the last submit and waiting
|
|
||||||
// on a serial that doesn't have a corresponding fence enqueued. Force all
|
|
||||||
// operations to look as if they were completed (because they were).
|
|
||||||
AssumeCommandsComplete();
|
|
||||||
|
|
||||||
if (mFenceEvent != nullptr) {
|
if (mFenceEvent != nullptr) {
|
||||||
::CloseHandle(mFenceEvent);
|
::CloseHandle(mFenceEvent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,9 +155,9 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
Serial Device::CheckAndUpdateCompletedSerials() {
|
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||||
if (GetCompletedCommandSerial() > mCompletedSerial) {
|
if (GetCompletedCommandSerial() > mCompletedSerial) {
|
||||||
// sometimes we artificially increase the serials, in which case the completed serial in
|
// sometimes we increase the serials, in which case the completed serial in
|
||||||
// the device base will surpass the completed serial we have in the metal backend, so we
|
// the device base will surpass the completed serial we have in the metal backend, so we
|
||||||
// must update ours when we see that the completed serial from the frontend has
|
// must update ours when we see that the completed serial from device base has
|
||||||
// increased.
|
// increased.
|
||||||
mCompletedSerial = GetCompletedCommandSerial();
|
mCompletedSerial = GetCompletedCommandSerial();
|
||||||
}
|
}
|
||||||
|
@ -166,15 +166,8 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
CheckPassedSerials();
|
|
||||||
Serial completedSerial = GetCompletedCommandSerial();
|
|
||||||
|
|
||||||
if (mCommandContext.GetCommands() != nil) {
|
if (mCommandContext.GetCommands() != nil) {
|
||||||
SubmitPendingCommandBuffer();
|
SubmitPendingCommandBuffer();
|
||||||
} else if (completedSerial == GetLastSubmittedCommandSerial()) {
|
|
||||||
// If there's no GPU work in flight we still need to artificially increment the serial
|
|
||||||
// so that CPU operations waiting on GPU completion can know they don't have to wait.
|
|
||||||
ArtificiallyIncrementSerials();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -300,14 +293,8 @@ namespace dawn_native { namespace metal {
|
||||||
CheckPassedSerials();
|
CheckPassedSerials();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Artificially increase the serials so work that was pending knows it can complete.
|
|
||||||
ArtificiallyIncrementSerials();
|
|
||||||
|
|
||||||
DAWN_TRY(TickImpl());
|
DAWN_TRY(TickImpl());
|
||||||
|
|
||||||
// Force all operations to look as if they were completed
|
|
||||||
AssumeCommandsComplete();
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,8 +185,6 @@ namespace dawn_native { namespace null {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::WaitForIdleForDestruction() {
|
MaybeError Device::WaitForIdleForDestruction() {
|
||||||
// Fake all commands being completed
|
|
||||||
AssumeCommandsComplete();
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,12 +153,6 @@ namespace dawn_native { namespace opengl {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
CheckPassedSerials();
|
|
||||||
if (GetCompletedCommandSerial() == GetLastSubmittedCommandSerial()) {
|
|
||||||
// If there's no GPU work in flight we still need to artificially increment the serial
|
|
||||||
// so that CPU operations waiting on GPU completion can know they don't have to wait.
|
|
||||||
ArtificiallyIncrementSerials();
|
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,11 +194,6 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
void Device::ShutDownImpl() {
|
void Device::ShutDownImpl() {
|
||||||
ASSERT(GetState() == State::Disconnected);
|
ASSERT(GetState() == State::Disconnected);
|
||||||
|
|
||||||
// Some operations might have been started since the last submit and waiting
|
|
||||||
// on a serial that doesn't have a corresponding fence enqueued. Force all
|
|
||||||
// operations to look as if they were completed (because they were).
|
|
||||||
AssumeCommandsComplete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::WaitForIdleForDestruction() {
|
MaybeError Device::WaitForIdleForDestruction() {
|
||||||
|
@ -213,8 +202,6 @@ namespace dawn_native { namespace opengl {
|
||||||
ASSERT(mFencesInFlight.empty());
|
ASSERT(mFencesInFlight.empty());
|
||||||
Tick();
|
Tick();
|
||||||
|
|
||||||
// Force all operations to look as if they were completed
|
|
||||||
AssumeCommandsComplete();
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,6 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
CheckPassedSerials();
|
|
||||||
RecycleCompletedCommands();
|
RecycleCompletedCommands();
|
||||||
|
|
||||||
Serial completedSerial = GetCompletedCommandSerial();
|
Serial completedSerial = GetCompletedCommandSerial();
|
||||||
|
@ -171,10 +170,6 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
if (mRecordingContext.used) {
|
if (mRecordingContext.used) {
|
||||||
DAWN_TRY(SubmitPendingCommands());
|
DAWN_TRY(SubmitPendingCommands());
|
||||||
} else if (completedSerial == GetLastSubmittedCommandSerial()) {
|
|
||||||
// If there's no GPU work in flight we still need to artificially increment the serial
|
|
||||||
// so that CPU operations waiting on GPU completion can know they don't have to wait.
|
|
||||||
ArtificiallyIncrementSerials();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -731,9 +726,6 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
mFencesInFlight.pop();
|
mFencesInFlight.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force all operations to look as if they were completed
|
|
||||||
AssumeCommandsComplete();
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,11 +765,6 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
mRecordingContext.signalSemaphores.clear();
|
mRecordingContext.signalSemaphores.clear();
|
||||||
|
|
||||||
// Some operations might have been started since the last submit and waiting
|
|
||||||
// on a serial that doesn't have a corresponding fence enqueued. Force all
|
|
||||||
// operations to look as if they were completed (because they were).
|
|
||||||
AssumeCommandsComplete();
|
|
||||||
|
|
||||||
// Assert that errors are device loss so that we can continue with destruction
|
// Assert that errors are device loss so that we can continue with destruction
|
||||||
AssertAndIgnoreDeviceLossError(TickImpl());
|
AssertAndIgnoreDeviceLossError(TickImpl());
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,43 @@ TEST_P(FenceTests, MultipleSignalOnCompletion) {
|
||||||
WaitForCompletedValue(fence, 4);
|
WaitForCompletedValue(fence, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test callbacks still occur if Queue::Signal and fence::OnCompletion happens multiple times
|
||||||
|
TEST_P(FenceTests, SignalOnCompletionWait) {
|
||||||
|
wgpu::Fence 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, ToMockFenceOnCompletionCallback, this + 2);
|
||||||
|
fence.OnCompletion(5u, ToMockFenceOnCompletionCallback, 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 = queue.CreateFence();
|
||||||
|
|
||||||
|
queue.Signal(fence, 2);
|
||||||
|
|
||||||
|
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||||
|
.Times(1);
|
||||||
|
fence.OnCompletion(1u, ToMockFenceOnCompletionCallback, this + 2);
|
||||||
|
|
||||||
|
queue.Signal(fence, 4);
|
||||||
|
|
||||||
|
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 4))
|
||||||
|
.Times(1);
|
||||||
|
fence.OnCompletion(3u, ToMockFenceOnCompletionCallback, this + 4);
|
||||||
|
|
||||||
|
WaitForCompletedValue(fence, 4);
|
||||||
|
}
|
||||||
|
|
||||||
// Test all callbacks are called if they are added for the same fence value
|
// Test all callbacks are called if they are added for the same fence value
|
||||||
TEST_P(FenceTests, OnCompletionMultipleCallbacks) {
|
TEST_P(FenceTests, OnCompletionMultipleCallbacks) {
|
||||||
wgpu::Fence fence = queue.CreateFence();
|
wgpu::Fence fence = queue.CreateFence();
|
||||||
|
|
Loading…
Reference in New Issue