Change Device::Tick To Return Bool

Changes Device::Tick to return a boolean that denotes whether or not
Tick needs to be called again.

Bug: dawn:119
Change-Id: I9d4c7e291536d676b33fc61d652667c1fbff8c62
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/29980
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Brandon Jones <brandon1.jones@intel.com>
This commit is contained in:
Brandon Jones 2020-10-15 16:21:03 +00:00 committed by Commit Bot service account
parent 294f71c5c9
commit 4ad35865b0
6 changed files with 57 additions and 30 deletions

View File

@ -196,6 +196,11 @@ namespace dawn_native {
return GetProcMapNamesForTestingInternal(); return GetProcMapNamesForTestingInternal();
} }
DAWN_NATIVE_EXPORT bool DeviceTick(WGPUDevice device) {
dawn_native::DeviceBase* deviceBase = reinterpret_cast<dawn_native::DeviceBase*>(device);
return deviceBase->Tick();
}
// ExternalImageDescriptor // ExternalImageDescriptor
ExternalImageDescriptor::ExternalImageDescriptor(ExternalImageType type) : type(type) { ExternalImageDescriptor::ExternalImageDescriptor(ExternalImageType type) : type(type) {

View File

@ -139,7 +139,7 @@ namespace dawn_native {
break; break;
} }
ASSERT(mCompletedSerial == mLastSubmittedSerial); ASSERT(mCompletedSerial == mLastSubmittedSerial);
ASSERT(mFutureCallbackSerial <= mCompletedSerial); ASSERT(mFutureSerial <= 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) {
@ -189,7 +189,7 @@ namespace dawn_native {
IgnoreErrors(WaitForIdleForDestruction()); IgnoreErrors(WaitForIdleForDestruction());
IgnoreErrors(TickImpl()); IgnoreErrors(TickImpl());
AssumeCommandsComplete(); AssumeCommandsComplete();
ASSERT(mFutureCallbackSerial <= mCompletedSerial); ASSERT(mFutureSerial <= 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.
@ -319,8 +319,8 @@ namespace dawn_native {
return mLastSubmittedSerial; return mLastSubmittedSerial;
} }
ExecutionSerial DeviceBase::GetFutureCallbackSerial() const { ExecutionSerial DeviceBase::GetFutureSerial() const {
return mFutureCallbackSerial; return mFutureSerial;
} }
void DeviceBase::IncrementLastSubmittedCommandSerial() { void DeviceBase::IncrementLastSubmittedCommandSerial() {
@ -328,19 +328,27 @@ namespace dawn_native {
} }
void DeviceBase::AssumeCommandsComplete() { void DeviceBase::AssumeCommandsComplete() {
ExecutionSerial maxSerial = ExecutionSerial( ExecutionSerial maxSerial =
std::max(mLastSubmittedSerial + ExecutionSerial(1), mFutureCallbackSerial)); ExecutionSerial(std::max(mLastSubmittedSerial + ExecutionSerial(1), mFutureSerial));
mLastSubmittedSerial = maxSerial; mLastSubmittedSerial = maxSerial;
mCompletedSerial = maxSerial; mCompletedSerial = maxSerial;
} }
bool DeviceBase::IsDeviceIdle() {
ExecutionSerial maxSerial = std::max(mLastSubmittedSerial, mFutureSerial);
if (mCompletedSerial == maxSerial) {
return true;
}
return false;
}
ExecutionSerial DeviceBase::GetPendingCommandSerial() const { ExecutionSerial DeviceBase::GetPendingCommandSerial() const {
return mLastSubmittedSerial + ExecutionSerial(1); return mLastSubmittedSerial + ExecutionSerial(1);
} }
void DeviceBase::AddFutureCallbackSerial(ExecutionSerial serial) { void DeviceBase::AddFutureSerial(ExecutionSerial serial) {
if (serial > mFutureCallbackSerial) { if (serial > mFutureSerial) {
mFutureCallbackSerial = serial; mFutureSerial = serial;
} }
} }
@ -713,18 +721,19 @@ namespace dawn_native {
// Other Device API methods // Other Device API methods
void DeviceBase::Tick() { // Returns true if future ticking is needed.
bool DeviceBase::Tick() {
if (ConsumedError(ValidateIsAlive())) { if (ConsumedError(ValidateIsAlive())) {
return; return false;
} }
// to avoid overly ticking, we only want to tick when: // to avoid overly ticking, we only want to tick when:
// 1. the last submitted serial has moved beyond the completed serial // 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 // 2. or the completed serial has not reached the future serial set by the trackers
if (mLastSubmittedSerial > mCompletedSerial || mCompletedSerial < mFutureCallbackSerial) { if (mLastSubmittedSerial > mCompletedSerial || mCompletedSerial < mFutureSerial) {
CheckPassedSerials(); CheckPassedSerials();
if (ConsumedError(TickImpl())) { if (ConsumedError(TickImpl())) {
return; return false;
} }
// There is no GPU work in flight, we need to move the serials forward so that // There is no GPU work in flight, we need to move the serials forward so that
@ -742,6 +751,8 @@ namespace dawn_native {
mErrorScopeTracker->Tick(mCompletedSerial); mErrorScopeTracker->Tick(mCompletedSerial);
GetDefaultQueue()->Tick(mCompletedSerial); GetDefaultQueue()->Tick(mCompletedSerial);
} }
return !IsDeviceIdle();
} }
void DeviceBase::Reference() { void DeviceBase::Reference() {

View File

@ -86,7 +86,7 @@ namespace dawn_native {
ExecutionSerial GetCompletedCommandSerial() const; ExecutionSerial GetCompletedCommandSerial() const;
ExecutionSerial GetLastSubmittedCommandSerial() const; ExecutionSerial GetLastSubmittedCommandSerial() const;
ExecutionSerial GetFutureCallbackSerial() const; ExecutionSerial GetFutureSerial() const;
ExecutionSerial GetPendingCommandSerial() const; ExecutionSerial GetPendingCommandSerial() const;
virtual MaybeError TickImpl() = 0; virtual MaybeError TickImpl() = 0;
@ -161,7 +161,7 @@ namespace dawn_native {
QueueBase* GetDefaultQueue(); QueueBase* GetDefaultQueue();
void InjectError(wgpu::ErrorType type, const char* message); void InjectError(wgpu::ErrorType type, const char* message);
void Tick(); bool Tick();
void SetDeviceLostCallback(wgpu::DeviceLostCallback callback, void* userdata); void SetDeviceLostCallback(wgpu::DeviceLostCallback callback, void* userdata);
void SetUncapturedErrorCallback(wgpu::ErrorCallback callback, void* userdata); void SetUncapturedErrorCallback(wgpu::ErrorCallback callback, void* userdata);
@ -221,14 +221,15 @@ namespace dawn_native {
size_t GetDeprecationWarningCountForTesting(); size_t GetDeprecationWarningCountForTesting();
void EmitDeprecationWarning(const char* warning); void EmitDeprecationWarning(const char* warning);
void LoseForTesting(); void LoseForTesting();
// AddFutureCallbackSerial is used to update the mFutureCallbackSerial with the max
// serial needed to be ticked in order to clean up all pending callback work. It should be // AddFutureSerial is used to update the mFutureSerial with the max serial needed to be
// given the serial that a callback is tracked with, so that once that serial is completed, // ticked in order to clean up all pending callback work or to execute asynchronous resource
// it can be resolved and cleaned up. This is so that when there is no gpu work (the last // writes. It should be given the serial that a callback is tracked with, so that once that
// submitted serial has not moved beyond the completed serial), Tick can still check if we // serial is completed, it can be resolved and cleaned up. This is so that when there is no
// have pending callback work to take care of, rather than hanging and never reaching the // gpu work (the last submitted serial has not moved beyond the completed serial), Tick can
// serial the callbacks are enqueued on. // still check if we have pending work to take care of, rather than hanging and never
void AddFutureCallbackSerial(ExecutionSerial serial); // reaching the serial the work will be executed on.
void AddFutureSerial(ExecutionSerial serial);
virtual uint32_t GetOptimalBytesPerRowAlignment() const = 0; virtual uint32_t GetOptimalBytesPerRowAlignment() const = 0;
virtual uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const = 0; virtual uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const = 0;
@ -320,17 +321,19 @@ namespace dawn_native {
// and waiting on a serial that doesn't have a corresponding fence enqueued. Fake serials to // and waiting on a serial that doesn't have a corresponding fence enqueued. Fake serials to
// make all commands look completed. // make all commands look completed.
void AssumeCommandsComplete(); void AssumeCommandsComplete();
bool IsDeviceIdle();
// 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 // mFutureSerial tracks the largest serial we need to tick to for asynchronous commands or
// fire // callbacks to fire
ExecutionSerial mCompletedSerial = ExecutionSerial(0); ExecutionSerial mCompletedSerial = ExecutionSerial(0);
ExecutionSerial mLastSubmittedSerial = ExecutionSerial(0); ExecutionSerial mLastSubmittedSerial = ExecutionSerial(0);
ExecutionSerial mFutureCallbackSerial = ExecutionSerial(0); ExecutionSerial mFutureSerial = ExecutionSerial(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.

View File

@ -36,7 +36,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()); mDevice->AddFutureSerial(mDevice->GetPendingCommandSerial());
} }
void ErrorScopeTracker::Tick(ExecutionSerial completedSerial) { void ErrorScopeTracker::Tick(ExecutionSerial completedSerial) {

View File

@ -179,7 +179,7 @@ namespace dawn_native {
void QueueBase::TrackTask(std::unique_ptr<TaskInFlight> task, ExecutionSerial serial) { void QueueBase::TrackTask(std::unique_ptr<TaskInFlight> task, ExecutionSerial serial) {
mTasksInFlight.Enqueue(std::move(task), serial); mTasksInFlight.Enqueue(std::move(task), serial);
GetDevice()->AddFutureCallbackSerial(serial); GetDevice()->AddFutureSerial(serial);
} }
void QueueBase::Tick(ExecutionSerial finishedSerial) { void QueueBase::Tick(ExecutionSerial finishedSerial) {
@ -234,6 +234,8 @@ namespace dawn_native {
memcpy(uploadHandle.mappedBuffer, data, size); memcpy(uploadHandle.mappedBuffer, data, size);
device->AddFutureSerial(device->GetPendingCommandSerial());
return device->CopyFromStagingToBuffer(uploadHandle.stagingBuffer, uploadHandle.startOffset, return device->CopyFromStagingToBuffer(uploadHandle.stagingBuffer, uploadHandle.startOffset,
buffer, bufferOffset, size); buffer, bufferOffset, size);
} }
@ -297,8 +299,12 @@ namespace dawn_native {
textureCopy.origin = destination.origin; textureCopy.origin = destination.origin;
textureCopy.aspect = ConvertAspect(destination.texture->GetFormat(), destination.aspect); textureCopy.aspect = ConvertAspect(destination.texture->GetFormat(), destination.aspect);
return GetDevice()->CopyFromStagingToTexture(uploadHandle.stagingBuffer, passDataLayout, DeviceBase* device = GetDevice();
&textureCopy, writeSizePixel);
device->AddFutureSerial(device->GetPendingCommandSerial());
return device->CopyFromStagingToTexture(uploadHandle.stagingBuffer, passDataLayout,
&textureCopy, writeSizePixel);
} }
MaybeError QueueBase::ValidateSubmit(uint32_t commandCount, MaybeError QueueBase::ValidateSubmit(uint32_t commandCount,
CommandBufferBase* const* commands) const { CommandBufferBase* const* commands) const {

View File

@ -193,6 +193,8 @@ namespace dawn_native {
// Backdoor to get the order of the ProcMap for testing // Backdoor to get the order of the ProcMap for testing
DAWN_NATIVE_EXPORT std::vector<const char*> GetProcMapNamesForTesting(); DAWN_NATIVE_EXPORT std::vector<const char*> GetProcMapNamesForTesting();
DAWN_NATIVE_EXPORT bool DeviceTick(WGPUDevice device);
// ErrorInjector functions used for testing only. Defined in dawn_native/ErrorInjector.cpp // ErrorInjector functions used for testing only. Defined in dawn_native/ErrorInjector.cpp
DAWN_NATIVE_EXPORT void EnableErrorInjector(); DAWN_NATIVE_EXPORT void EnableErrorInjector();
DAWN_NATIVE_EXPORT void DisableErrorInjector(); DAWN_NATIVE_EXPORT void DisableErrorInjector();