mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-09 05:29:17 +00:00
Refactor Serial tracking to be owned by Device frontend.
Move mCompletedSerial and mLastSubmittedSerial to Device frontend and add getters and setters for the device backend to access such. This is to aid the Device in taking more ownership of Serials and Ticking. Bug: dawn:400 Change-Id: Ifa53ac294a871e484716842a3d212373b57847c4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/20480 Commit-Queue: Natasha Lee <natlee@microsoft.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
4f3811c064
commit
351c95a477
@ -124,6 +124,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);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::BeingDisconnected:
|
case State::BeingDisconnected:
|
||||||
@ -173,6 +174,7 @@ namespace dawn_native {
|
|||||||
|
|
||||||
// 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.
|
||||||
AssertAndIgnoreDeviceLossError(WaitForIdleForDestruction());
|
AssertAndIgnoreDeviceLossError(WaitForIdleForDestruction());
|
||||||
|
ASSERT(mCompletedSerial == mLastSubmittedSerial);
|
||||||
mState = State::Disconnected;
|
mState = State::Disconnected;
|
||||||
|
|
||||||
// Now everything is as if the device was lost.
|
// Now everything is as if the device was lost.
|
||||||
@ -292,6 +294,45 @@ namespace dawn_native {
|
|||||||
return mFenceSignalTracker.get();
|
return mFenceSignalTracker.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial DeviceBase::GetCompletedCommandSerial() const {
|
||||||
|
return mCompletedSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial DeviceBase::GetLastSubmittedCommandSerial() const {
|
||||||
|
return mLastSubmittedSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceBase::IncrementLastSubmittedCommandSerial() {
|
||||||
|
mLastSubmittedSerial++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceBase::ArtificiallyIncrementSerials() {
|
||||||
|
mCompletedSerial++;
|
||||||
|
mLastSubmittedSerial++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceBase::AssumeCommandsComplete() {
|
||||||
|
mLastSubmittedSerial++;
|
||||||
|
mCompletedSerial = mLastSubmittedSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial DeviceBase::GetPendingCommandSerial() const {
|
||||||
|
return mLastSubmittedSerial + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceBase::CheckPassedSerials() {
|
||||||
|
Serial completedSerial = CheckAndUpdateCompletedSerials();
|
||||||
|
|
||||||
|
ASSERT(completedSerial <= mLastSubmittedSerial);
|
||||||
|
// completedSerial should not be less than mCompletedSerial unless it is 0.
|
||||||
|
// It can be 0 when there's no fences to check.
|
||||||
|
ASSERT(completedSerial >= mCompletedSerial || completedSerial == 0);
|
||||||
|
|
||||||
|
if (completedSerial > mCompletedSerial) {
|
||||||
|
mCompletedSerial = completedSerial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ResultOrError<const Format*> DeviceBase::GetInternalFormat(wgpu::TextureFormat format) const {
|
ResultOrError<const Format*> DeviceBase::GetInternalFormat(wgpu::TextureFormat format) const {
|
||||||
size_t index = ComputeFormatIndex(format);
|
size_t index = ComputeFormatIndex(format);
|
||||||
if (index >= mFormatTable.size()) {
|
if (index >= mFormatTable.size()) {
|
||||||
|
@ -86,9 +86,9 @@ namespace dawn_native {
|
|||||||
CommandEncoder* encoder,
|
CommandEncoder* encoder,
|
||||||
const CommandBufferDescriptor* descriptor) = 0;
|
const CommandBufferDescriptor* descriptor) = 0;
|
||||||
|
|
||||||
virtual Serial GetCompletedCommandSerial() const = 0;
|
Serial GetCompletedCommandSerial() const;
|
||||||
virtual Serial GetLastSubmittedCommandSerial() const = 0;
|
Serial GetLastSubmittedCommandSerial() const;
|
||||||
virtual Serial GetPendingCommandSerial() const = 0;
|
Serial GetPendingCommandSerial() const;
|
||||||
virtual MaybeError TickImpl() = 0;
|
virtual MaybeError TickImpl() = 0;
|
||||||
|
|
||||||
// Many Dawn objects are completely immutable once created which means that if two
|
// Many Dawn objects are completely immutable once created which means that if two
|
||||||
@ -220,6 +220,18 @@ namespace dawn_native {
|
|||||||
MaybeError Initialize(QueueBase* defaultQueue);
|
MaybeError Initialize(QueueBase* defaultQueue);
|
||||||
void ShutDownBase();
|
void ShutDownBase();
|
||||||
|
|
||||||
|
// Incrememt mLastSubmittedSerial when we submit the next serial
|
||||||
|
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
|
||||||
|
void CheckPassedSerials();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ResultOrError<BindGroupBase*> CreateBindGroupImpl(
|
virtual ResultOrError<BindGroupBase*> CreateBindGroupImpl(
|
||||||
const BindGroupDescriptor* descriptor) = 0;
|
const BindGroupDescriptor* descriptor) = 0;
|
||||||
@ -281,6 +293,18 @@ namespace dawn_native {
|
|||||||
|
|
||||||
void ConsumeError(std::unique_ptr<ErrorData> error);
|
void ConsumeError(std::unique_ptr<ErrorData> error);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
virtual Serial CheckAndUpdateCompletedSerials() = 0;
|
||||||
|
// mCompletedSerial tracks the last completed command serial that the fence has returned.
|
||||||
|
// mLastSubmittedSerial tracks the last submitted command serial.
|
||||||
|
// During device removal, the serials could be artificially incremented
|
||||||
|
// 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
|
||||||
|
// stale serials.
|
||||||
|
Serial mCompletedSerial = 0;
|
||||||
|
Serial mLastSubmittedSerial = 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.
|
||||||
virtual void ShutDownImpl() = 0;
|
virtual void ShutDownImpl() = 0;
|
||||||
|
@ -72,8 +72,9 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
// value.
|
// value.
|
||||||
mCommandQueue.As(&mD3d12SharingContract);
|
mCommandQueue.As(&mD3d12SharingContract);
|
||||||
|
|
||||||
DAWN_TRY(CheckHRESULT(mD3d12Device->CreateFence(mLastSubmittedSerial, D3D12_FENCE_FLAG_NONE,
|
DAWN_TRY(
|
||||||
IID_PPV_ARGS(&mFence)),
|
CheckHRESULT(mD3d12Device->CreateFence(GetLastSubmittedCommandSerial(),
|
||||||
|
D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence)),
|
||||||
"D3D12 create fence"));
|
"D3D12 create fence"));
|
||||||
|
|
||||||
mFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
mFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||||
@ -198,44 +199,35 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
return &mPendingCommands;
|
return &mPendingCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial Device::GetCompletedCommandSerial() const {
|
|
||||||
return mCompletedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetLastSubmittedCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetPendingCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
// Perform cleanup operations to free unused objects
|
CheckPassedSerials();
|
||||||
mCompletedSerial = mFence->GetCompletedValue();
|
|
||||||
|
|
||||||
mResourceAllocatorManager->Tick(mCompletedSerial);
|
// Perform cleanup operations to free unused objects
|
||||||
DAWN_TRY(mCommandAllocatorManager->Tick(mCompletedSerial));
|
Serial completedSerial = GetCompletedCommandSerial();
|
||||||
mViewShaderVisibleDescriptorAllocator->Tick(mCompletedSerial);
|
|
||||||
mSamplerShaderVisibleDescriptorAllocator->Tick(mCompletedSerial);
|
mResourceAllocatorManager->Tick(completedSerial);
|
||||||
mRenderTargetViewAllocator->Tick(mCompletedSerial);
|
DAWN_TRY(mCommandAllocatorManager->Tick(completedSerial));
|
||||||
mDepthStencilViewAllocator->Tick(mCompletedSerial);
|
mViewShaderVisibleDescriptorAllocator->Tick(completedSerial);
|
||||||
mMapRequestTracker->Tick(mCompletedSerial);
|
mSamplerShaderVisibleDescriptorAllocator->Tick(completedSerial);
|
||||||
mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
|
mRenderTargetViewAllocator->Tick(completedSerial);
|
||||||
|
mDepthStencilViewAllocator->Tick(completedSerial);
|
||||||
|
mMapRequestTracker->Tick(completedSerial);
|
||||||
|
mUsedComObjectRefs.ClearUpTo(completedSerial);
|
||||||
DAWN_TRY(ExecutePendingCommandContext());
|
DAWN_TRY(ExecutePendingCommandContext());
|
||||||
DAWN_TRY(NextSerial());
|
DAWN_TRY(NextSerial());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::NextSerial() {
|
MaybeError Device::NextSerial() {
|
||||||
mLastSubmittedSerial++;
|
IncrementLastSubmittedCommandSerial();
|
||||||
return CheckHRESULT(mCommandQueue->Signal(mFence.Get(), mLastSubmittedSerial),
|
|
||||||
|
return CheckHRESULT(mCommandQueue->Signal(mFence.Get(), GetLastSubmittedCommandSerial()),
|
||||||
"D3D12 command queue signal fence");
|
"D3D12 command queue signal fence");
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::WaitForSerial(uint64_t serial) {
|
MaybeError Device::WaitForSerial(uint64_t serial) {
|
||||||
mCompletedSerial = mFence->GetCompletedValue();
|
CheckPassedSerials();
|
||||||
if (mCompletedSerial < serial) {
|
if (GetCompletedCommandSerial() < serial) {
|
||||||
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);
|
||||||
@ -243,6 +235,10 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||||
|
return mFence->GetCompletedValue();
|
||||||
|
}
|
||||||
|
|
||||||
void Device::ReferenceUntilUnused(ComPtr<IUnknown> object) {
|
void Device::ReferenceUntilUnused(ComPtr<IUnknown> object) {
|
||||||
mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial());
|
mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial());
|
||||||
}
|
}
|
||||||
@ -447,11 +443,13 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
|
|
||||||
DAWN_TRY(NextSerial());
|
DAWN_TRY(NextSerial());
|
||||||
// Wait for all in-flight commands to finish executing
|
// Wait for all in-flight commands to finish executing
|
||||||
DAWN_TRY(WaitForSerial(mLastSubmittedSerial));
|
DAWN_TRY(WaitForSerial(GetLastSubmittedCommandSerial()));
|
||||||
|
|
||||||
// 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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,16 +459,16 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
// Immediately forget about all pending commands
|
// Immediately forget about all pending commands
|
||||||
mPendingCommands.Release();
|
mPendingCommands.Release();
|
||||||
|
|
||||||
// GPU is no longer executing commands. Existing objects do not get freed until the device
|
// Some operations might have been started since the last submit and waiting
|
||||||
// is destroyed. To ensure objects are always released, force the completed serial to be
|
// on a serial that doesn't have a corresponding fence enqueued. Force all
|
||||||
// MAX.
|
// operations to look as if they were completed (because they were).
|
||||||
mCompletedSerial = std::numeric_limits<Serial>::max();
|
AssumeCommandsComplete();
|
||||||
|
|
||||||
if (mFenceEvent != nullptr) {
|
if (mFenceEvent != nullptr) {
|
||||||
::CloseHandle(mFenceEvent);
|
::CloseHandle(mFenceEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
|
mUsedComObjectRefs.ClearUpTo(GetCompletedCommandSerial());
|
||||||
|
|
||||||
ASSERT(mUsedComObjectRefs.Empty());
|
ASSERT(mUsedComObjectRefs.Empty());
|
||||||
ASSERT(!mPendingCommands.IsOpen());
|
ASSERT(!mPendingCommands.IsOpen());
|
||||||
|
@ -55,8 +55,6 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
||||||
const CommandBufferDescriptor* descriptor) override;
|
const CommandBufferDescriptor* descriptor) override;
|
||||||
|
|
||||||
Serial GetCompletedCommandSerial() const final override;
|
|
||||||
Serial GetLastSubmittedCommandSerial() const final override;
|
|
||||||
MaybeError TickImpl() override;
|
MaybeError TickImpl() override;
|
||||||
|
|
||||||
ID3D12Device* GetD3D12Device() const;
|
ID3D12Device* GetD3D12Device() const;
|
||||||
@ -75,7 +73,6 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
ComPtr<IDXGIFactory4> GetFactory() const;
|
ComPtr<IDXGIFactory4> GetFactory() const;
|
||||||
|
|
||||||
ResultOrError<CommandRecordingContext*> GetPendingCommandContext();
|
ResultOrError<CommandRecordingContext*> GetPendingCommandContext();
|
||||||
Serial GetPendingCommandSerial() const override;
|
|
||||||
|
|
||||||
const D3D12DeviceInfo& GetDeviceInfo() const;
|
const D3D12DeviceInfo& GetDeviceInfo() const;
|
||||||
|
|
||||||
@ -156,10 +153,9 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
void ShutDownImpl() override;
|
void ShutDownImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
|
|
||||||
Serial mCompletedSerial = 0;
|
|
||||||
Serial mLastSubmittedSerial = 0;
|
|
||||||
ComPtr<ID3D12Fence> mFence;
|
ComPtr<ID3D12Fence> mFence;
|
||||||
HANDLE mFenceEvent = nullptr;
|
HANDLE mFenceEvent = nullptr;
|
||||||
|
Serial CheckAndUpdateCompletedSerials() override;
|
||||||
|
|
||||||
ComPtr<ID3D12Device> mD3d12Device; // Device is owned by adapter and will not be outlived.
|
ComPtr<ID3D12Device> mD3d12Device; // Device is owned by adapter and will not be outlived.
|
||||||
ComPtr<ID3D12CommandQueue> mCommandQueue;
|
ComPtr<ID3D12CommandQueue> mCommandQueue;
|
||||||
|
@ -46,15 +46,12 @@ namespace dawn_native { namespace metal {
|
|||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
||||||
const CommandBufferDescriptor* descriptor) override;
|
const CommandBufferDescriptor* descriptor) override;
|
||||||
|
|
||||||
Serial GetCompletedCommandSerial() const final override;
|
|
||||||
Serial GetLastSubmittedCommandSerial() const final override;
|
|
||||||
MaybeError TickImpl() override;
|
MaybeError TickImpl() override;
|
||||||
|
|
||||||
id<MTLDevice> GetMTLDevice();
|
id<MTLDevice> GetMTLDevice();
|
||||||
id<MTLCommandQueue> GetMTLQueue();
|
id<MTLCommandQueue> GetMTLQueue();
|
||||||
|
|
||||||
CommandRecordingContext* GetPendingCommandContext();
|
CommandRecordingContext* GetPendingCommandContext();
|
||||||
Serial GetPendingCommandSerial() const override;
|
|
||||||
void SubmitPendingCommandBuffer();
|
void SubmitPendingCommandBuffer();
|
||||||
|
|
||||||
MapRequestTracker* GetMapTracker() const;
|
MapRequestTracker* GetMapTracker() const;
|
||||||
@ -103,12 +100,12 @@ namespace dawn_native { namespace metal {
|
|||||||
void InitTogglesFromDriver();
|
void InitTogglesFromDriver();
|
||||||
void ShutDownImpl() override;
|
void ShutDownImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
|
Serial CheckAndUpdateCompletedSerials() override;
|
||||||
|
|
||||||
id<MTLDevice> mMtlDevice = nil;
|
id<MTLDevice> mMtlDevice = nil;
|
||||||
id<MTLCommandQueue> mCommandQueue = nil;
|
id<MTLCommandQueue> mCommandQueue = nil;
|
||||||
std::unique_ptr<MapRequestTracker> mMapTracker;
|
std::unique_ptr<MapRequestTracker> mMapTracker;
|
||||||
|
|
||||||
Serial mLastSubmittedSerial = 0;
|
|
||||||
CommandRecordingContext mCommandContext;
|
CommandRecordingContext mCommandContext;
|
||||||
|
|
||||||
// The completed serial is updated in a Metal completion handler that can be fired on a
|
// The completed serial is updated in a Metal completion handler that can be fired on a
|
||||||
|
@ -154,31 +154,30 @@ namespace dawn_native { namespace metal {
|
|||||||
return new TextureView(texture, descriptor);
|
return new TextureView(texture, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial Device::GetCompletedCommandSerial() const {
|
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||||
|
if (GetCompletedCommandSerial() > mCompletedSerial) {
|
||||||
|
// sometimes we artificially 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
|
||||||
|
// must update ours when we see that the completed serial from the frontend has
|
||||||
|
// increased.
|
||||||
|
mCompletedSerial = GetCompletedCommandSerial();
|
||||||
|
}
|
||||||
static_assert(std::is_same<Serial, uint64_t>::value, "");
|
static_assert(std::is_same<Serial, uint64_t>::value, "");
|
||||||
return mCompletedSerial.load();
|
return mCompletedSerial.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial Device::GetLastSubmittedCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetPendingCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
|
CheckPassedSerials();
|
||||||
Serial completedSerial = GetCompletedCommandSerial();
|
Serial completedSerial = GetCompletedCommandSerial();
|
||||||
|
|
||||||
mMapTracker->Tick(completedSerial);
|
mMapTracker->Tick(completedSerial);
|
||||||
|
|
||||||
if (mCommandContext.GetCommands() != nil) {
|
if (mCommandContext.GetCommands() != nil) {
|
||||||
SubmitPendingCommandBuffer();
|
SubmitPendingCommandBuffer();
|
||||||
} else if (completedSerial == mLastSubmittedSerial) {
|
} else if (completedSerial == GetLastSubmittedCommandSerial()) {
|
||||||
// If there's no GPU work in flight we still need to artificially increment the serial
|
// 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.
|
// so that CPU operations waiting on GPU completion can know they don't have to wait.
|
||||||
mCompletedSerial++;
|
ArtificiallyIncrementSerials();
|
||||||
mLastSubmittedSerial++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@ -208,7 +207,7 @@ namespace dawn_native { namespace metal {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastSubmittedSerial++;
|
IncrementLastSubmittedCommandSerial();
|
||||||
|
|
||||||
// Acquire the pending command buffer, which is retained. It must be released later.
|
// Acquire the pending command buffer, which is retained. It must be released later.
|
||||||
id<MTLCommandBuffer> pendingCommands = mCommandContext.AcquireCommands();
|
id<MTLCommandBuffer> pendingCommands = mCommandContext.AcquireCommands();
|
||||||
@ -231,7 +230,8 @@ namespace dawn_native { namespace metal {
|
|||||||
|
|
||||||
// Update the completed serial once the completed handler is fired. Make a local copy of
|
// Update the completed serial once the completed handler is fired. Make a local copy of
|
||||||
// mLastSubmittedSerial so it is captured by value.
|
// mLastSubmittedSerial so it is captured by value.
|
||||||
Serial pendingSerial = mLastSubmittedSerial;
|
Serial pendingSerial = GetLastSubmittedCommandSerial();
|
||||||
|
// this ObjC block runs on a different thread
|
||||||
[pendingCommands addCompletedHandler:^(id<MTLCommandBuffer>) {
|
[pendingCommands addCompletedHandler:^(id<MTLCommandBuffer>) {
|
||||||
TRACE_EVENT_ASYNC_END0(GetPlatform(), GPUWork, "DeviceMTL::SubmitPendingCommandBuffer",
|
TRACE_EVENT_ASYNC_END0(GetPlatform(), GPUWork, "DeviceMTL::SubmitPendingCommandBuffer",
|
||||||
pendingSerial);
|
pendingSerial);
|
||||||
@ -299,17 +299,22 @@ namespace dawn_native { namespace metal {
|
|||||||
|
|
||||||
MaybeError Device::WaitForIdleForDestruction() {
|
MaybeError Device::WaitForIdleForDestruction() {
|
||||||
[mCommandContext.AcquireCommands() release];
|
[mCommandContext.AcquireCommands() release];
|
||||||
|
CheckPassedSerials();
|
||||||
|
|
||||||
// Wait for all commands to be finished so we can free resources
|
// Wait for all commands to be finished so we can free resources
|
||||||
while (GetCompletedCommandSerial() != mLastSubmittedSerial) {
|
while (GetCompletedCommandSerial() != GetLastSubmittedCommandSerial()) {
|
||||||
usleep(100);
|
usleep(100);
|
||||||
|
CheckPassedSerials();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Artificially increase the serials so work that was pending knows it can complete.
|
// Artificially increase the serials so work that was pending knows it can complete.
|
||||||
mCompletedSerial++;
|
ArtificiallyIncrementSerials();
|
||||||
mLastSubmittedSerial++;
|
|
||||||
|
|
||||||
DAWN_TRY(TickImpl());
|
DAWN_TRY(TickImpl());
|
||||||
|
|
||||||
|
// Force all operations to look as if they were completed
|
||||||
|
AssumeCommandsComplete();
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ namespace dawn_native { namespace null {
|
|||||||
|
|
||||||
MaybeError Device::WaitForIdleForDestruction() {
|
MaybeError Device::WaitForIdleForDestruction() {
|
||||||
// Fake all commands being completed
|
// Fake all commands being completed
|
||||||
mCompletedSerial = mLastSubmittedSerial;
|
AssumeCommandsComplete();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,23 +221,15 @@ namespace dawn_native { namespace null {
|
|||||||
mMemoryUsage -= bytes;
|
mMemoryUsage -= bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial Device::GetCompletedCommandSerial() const {
|
|
||||||
return mCompletedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetLastSubmittedCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetPendingCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
SubmitPendingOperations();
|
SubmitPendingOperations();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||||
|
return GetLastSubmittedCommandSerial();
|
||||||
|
}
|
||||||
|
|
||||||
void Device::AddPendingOperation(std::unique_ptr<PendingOperation> operation) {
|
void Device::AddPendingOperation(std::unique_ptr<PendingOperation> operation) {
|
||||||
mPendingOperations.emplace_back(std::move(operation));
|
mPendingOperations.emplace_back(std::move(operation));
|
||||||
}
|
}
|
||||||
@ -247,8 +239,8 @@ namespace dawn_native { namespace null {
|
|||||||
}
|
}
|
||||||
mPendingOperations.clear();
|
mPendingOperations.clear();
|
||||||
|
|
||||||
mCompletedSerial = mLastSubmittedSerial;
|
CheckPassedSerials();
|
||||||
mLastSubmittedSerial++;
|
IncrementLastSubmittedCommandSerial();
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindGroupDataHolder
|
// BindGroupDataHolder
|
||||||
|
@ -91,9 +91,6 @@ namespace dawn_native { namespace null {
|
|||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
||||||
const CommandBufferDescriptor* descriptor) override;
|
const CommandBufferDescriptor* descriptor) override;
|
||||||
|
|
||||||
Serial GetCompletedCommandSerial() const final override;
|
|
||||||
Serial GetLastSubmittedCommandSerial() const final override;
|
|
||||||
Serial GetPendingCommandSerial() const override;
|
|
||||||
MaybeError TickImpl() override;
|
MaybeError TickImpl() override;
|
||||||
|
|
||||||
void AddPendingOperation(std::unique_ptr<PendingOperation> operation);
|
void AddPendingOperation(std::unique_ptr<PendingOperation> operation);
|
||||||
@ -138,11 +135,11 @@ namespace dawn_native { namespace null {
|
|||||||
TextureBase* texture,
|
TextureBase* texture,
|
||||||
const TextureViewDescriptor* descriptor) override;
|
const TextureViewDescriptor* descriptor) override;
|
||||||
|
|
||||||
|
Serial CheckAndUpdateCompletedSerials() override;
|
||||||
|
|
||||||
void ShutDownImpl() override;
|
void ShutDownImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
|
|
||||||
Serial mCompletedSerial = 0;
|
|
||||||
Serial mLastSubmittedSerial = 0;
|
|
||||||
std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
|
std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
|
||||||
|
|
||||||
static constexpr size_t kMaxMemoryUsage = 256 * 1024 * 1024;
|
static constexpr size_t kMaxMemoryUsage = 256 * 1024 * 1024;
|
||||||
|
@ -147,46 +147,37 @@ namespace dawn_native { namespace opengl {
|
|||||||
|
|
||||||
void Device::SubmitFenceSync() {
|
void Device::SubmitFenceSync() {
|
||||||
GLsync sync = gl.FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
GLsync sync = gl.FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
mLastSubmittedSerial++;
|
IncrementLastSubmittedCommandSerial();
|
||||||
mFencesInFlight.emplace(sync, mLastSubmittedSerial);
|
mFencesInFlight.emplace(sync, GetLastSubmittedCommandSerial());
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetCompletedCommandSerial() const {
|
|
||||||
return mCompletedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetLastSubmittedCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetPendingCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
CheckPassedFences();
|
CheckPassedSerials();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::CheckPassedFences() {
|
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||||
|
Serial fenceSerial = 0;
|
||||||
while (!mFencesInFlight.empty()) {
|
while (!mFencesInFlight.empty()) {
|
||||||
GLsync sync = mFencesInFlight.front().first;
|
GLsync sync = mFencesInFlight.front().first;
|
||||||
Serial fenceSerial = mFencesInFlight.front().second;
|
Serial tentativeSerial = mFencesInFlight.front().second;
|
||||||
|
|
||||||
// Fence are added in order, so we can stop searching as soon
|
// Fence are added in order, so we can stop searching as soon
|
||||||
// as we see one that's not ready.
|
// as we see one that's not ready.
|
||||||
GLenum result = gl.ClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
|
GLenum result = gl.ClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
|
||||||
if (result == GL_TIMEOUT_EXPIRED) {
|
if (result == GL_TIMEOUT_EXPIRED) {
|
||||||
continue;
|
return fenceSerial;
|
||||||
}
|
}
|
||||||
|
// Update fenceSerial since fence is ready.
|
||||||
|
fenceSerial = tentativeSerial;
|
||||||
|
|
||||||
gl.DeleteSync(sync);
|
gl.DeleteSync(sync);
|
||||||
|
|
||||||
mFencesInFlight.pop();
|
mFencesInFlight.pop();
|
||||||
|
|
||||||
ASSERT(fenceSerial > mCompletedSerial);
|
ASSERT(fenceSerial > GetCompletedCommandSerial());
|
||||||
mCompletedSerial = fenceSerial;
|
|
||||||
}
|
}
|
||||||
|
return fenceSerial;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
|
ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
|
||||||
@ -207,14 +198,17 @@ namespace dawn_native { namespace opengl {
|
|||||||
// Some operations might have been started since the last submit and waiting
|
// 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
|
// on a serial that doesn't have a corresponding fence enqueued. Force all
|
||||||
// operations to look as if they were completed (because they were).
|
// operations to look as if they were completed (because they were).
|
||||||
mCompletedSerial = mLastSubmittedSerial + 1;
|
AssumeCommandsComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::WaitForIdleForDestruction() {
|
MaybeError Device::WaitForIdleForDestruction() {
|
||||||
gl.Finish();
|
gl.Finish();
|
||||||
CheckPassedFences();
|
CheckPassedSerials();
|
||||||
ASSERT(mFencesInFlight.empty());
|
ASSERT(mFencesInFlight.empty());
|
||||||
Tick();
|
Tick();
|
||||||
|
|
||||||
|
// Force all operations to look as if they were completed
|
||||||
|
AssumeCommandsComplete();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,9 +52,6 @@ namespace dawn_native { namespace opengl {
|
|||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
||||||
const CommandBufferDescriptor* descriptor) override;
|
const CommandBufferDescriptor* descriptor) override;
|
||||||
|
|
||||||
Serial GetCompletedCommandSerial() const final override;
|
|
||||||
Serial GetLastSubmittedCommandSerial() const final override;
|
|
||||||
Serial GetPendingCommandSerial() const override;
|
|
||||||
MaybeError TickImpl() override;
|
MaybeError TickImpl() override;
|
||||||
|
|
||||||
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
|
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
|
||||||
@ -96,12 +93,10 @@ namespace dawn_native { namespace opengl {
|
|||||||
const TextureViewDescriptor* descriptor) override;
|
const TextureViewDescriptor* descriptor) override;
|
||||||
|
|
||||||
void InitTogglesFromDriver();
|
void InitTogglesFromDriver();
|
||||||
void CheckPassedFences();
|
Serial CheckAndUpdateCompletedSerials() override;
|
||||||
void ShutDownImpl() override;
|
void ShutDownImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
|
|
||||||
Serial mCompletedSerial = 0;
|
|
||||||
Serial mLastSubmittedSerial = 0;
|
|
||||||
std::queue<std::pair<GLsync, Serial>> mFencesInFlight;
|
std::queue<std::pair<GLsync, Serial>> mFencesInFlight;
|
||||||
|
|
||||||
GLFormatTable mFormatTable;
|
GLFormatTable mFormatTable;
|
||||||
|
@ -155,39 +155,28 @@ namespace dawn_native { namespace vulkan {
|
|||||||
return TextureView::Create(texture, descriptor);
|
return TextureView::Create(texture, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial Device::GetCompletedCommandSerial() const {
|
|
||||||
return mCompletedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetLastSubmittedCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial Device::GetPendingCommandSerial() const {
|
|
||||||
return mLastSubmittedSerial + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
CheckPassedFences();
|
CheckPassedSerials();
|
||||||
RecycleCompletedCommands();
|
RecycleCompletedCommands();
|
||||||
|
|
||||||
for (Ref<BindGroupLayout>& bgl :
|
Serial completedSerial = GetCompletedCommandSerial();
|
||||||
mBindGroupLayoutsPendingDeallocation.IterateUpTo(mCompletedSerial)) {
|
|
||||||
bgl->FinishDeallocation(mCompletedSerial);
|
|
||||||
}
|
|
||||||
mBindGroupLayoutsPendingDeallocation.ClearUpTo(mCompletedSerial);
|
|
||||||
|
|
||||||
mMapRequestTracker->Tick(mCompletedSerial);
|
for (Ref<BindGroupLayout>& bgl :
|
||||||
mResourceMemoryAllocator->Tick(mCompletedSerial);
|
mBindGroupLayoutsPendingDeallocation.IterateUpTo(completedSerial)) {
|
||||||
mDeleter->Tick(mCompletedSerial);
|
bgl->FinishDeallocation(completedSerial);
|
||||||
|
}
|
||||||
|
mBindGroupLayoutsPendingDeallocation.ClearUpTo(completedSerial);
|
||||||
|
|
||||||
|
mMapRequestTracker->Tick(completedSerial);
|
||||||
|
mResourceMemoryAllocator->Tick(completedSerial);
|
||||||
|
mDeleter->Tick(completedSerial);
|
||||||
|
|
||||||
if (mRecordingContext.used) {
|
if (mRecordingContext.used) {
|
||||||
DAWN_TRY(SubmitPendingCommands());
|
DAWN_TRY(SubmitPendingCommands());
|
||||||
} else if (mCompletedSerial == mLastSubmittedSerial) {
|
} else if (completedSerial == GetLastSubmittedCommandSerial()) {
|
||||||
// If there's no GPU work in flight we still need to artificially increment the serial
|
// 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.
|
// so that CPU operations waiting on GPU completion can know they don't have to wait.
|
||||||
mCompletedSerial++;
|
ArtificiallyIncrementSerials();
|
||||||
mLastSubmittedSerial++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
@ -271,12 +260,13 @@ namespace dawn_native { namespace vulkan {
|
|||||||
mDeleter->DeleteWhenUnused(semaphore);
|
mDeleter->DeleteWhenUnused(semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastSubmittedSerial++;
|
IncrementLastSubmittedCommandSerial();
|
||||||
mFencesInFlight.emplace(fence, mLastSubmittedSerial);
|
Serial lastSubmittedSerial = GetLastSubmittedCommandSerial();
|
||||||
|
mFencesInFlight.emplace(fence, lastSubmittedSerial);
|
||||||
|
|
||||||
CommandPoolAndBuffer submittedCommands = {mRecordingContext.commandPool,
|
CommandPoolAndBuffer submittedCommands = {mRecordingContext.commandPool,
|
||||||
mRecordingContext.commandBuffer};
|
mRecordingContext.commandBuffer};
|
||||||
mCommandsInFlight.Enqueue(submittedCommands, mLastSubmittedSerial);
|
mCommandsInFlight.Enqueue(submittedCommands, lastSubmittedSerial);
|
||||||
mRecordingContext = CommandRecordingContext();
|
mRecordingContext = CommandRecordingContext();
|
||||||
DAWN_TRY(PrepareRecordingContext());
|
DAWN_TRY(PrepareRecordingContext());
|
||||||
|
|
||||||
@ -468,11 +458,11 @@ namespace dawn_native { namespace vulkan {
|
|||||||
return fence;
|
return fence;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::CheckPassedFences() {
|
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||||
|
Serial fenceSerial = 0;
|
||||||
while (!mFencesInFlight.empty()) {
|
while (!mFencesInFlight.empty()) {
|
||||||
VkFence fence = mFencesInFlight.front().first;
|
VkFence fence = mFencesInFlight.front().first;
|
||||||
Serial fenceSerial = mFencesInFlight.front().second;
|
Serial tentativeSerial = mFencesInFlight.front().second;
|
||||||
|
|
||||||
VkResult result = VkResult::WrapUnsafe(
|
VkResult result = VkResult::WrapUnsafe(
|
||||||
INJECT_ERROR_OR_RUN(fn.GetFenceStatus(mVkDevice, fence), VK_ERROR_DEVICE_LOST));
|
INJECT_ERROR_OR_RUN(fn.GetFenceStatus(mVkDevice, fence), VK_ERROR_DEVICE_LOST));
|
||||||
// TODO: Handle DeviceLost error.
|
// TODO: Handle DeviceLost error.
|
||||||
@ -481,15 +471,17 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Fence are added in order, so we can stop searching as soon
|
// Fence are added in order, so we can stop searching as soon
|
||||||
// as we see one that's not ready.
|
// as we see one that's not ready.
|
||||||
if (result == VK_NOT_READY) {
|
if (result == VK_NOT_READY) {
|
||||||
return;
|
return fenceSerial;
|
||||||
}
|
}
|
||||||
|
// Update fenceSerial since fence is ready.
|
||||||
|
fenceSerial = tentativeSerial;
|
||||||
|
|
||||||
mUnusedFences.push_back(fence);
|
mUnusedFences.push_back(fence);
|
||||||
mFencesInFlight.pop();
|
|
||||||
|
|
||||||
ASSERT(fenceSerial > mCompletedSerial);
|
ASSERT(fenceSerial > GetCompletedCommandSerial());
|
||||||
mCompletedSerial = fenceSerial;
|
mFencesInFlight.pop();
|
||||||
}
|
}
|
||||||
|
return fenceSerial;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::PrepareRecordingContext() {
|
MaybeError Device::PrepareRecordingContext() {
|
||||||
@ -542,10 +534,10 @@ namespace dawn_native { namespace vulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Device::RecycleCompletedCommands() {
|
void Device::RecycleCompletedCommands() {
|
||||||
for (auto& commands : mCommandsInFlight.IterateUpTo(mCompletedSerial)) {
|
for (auto& commands : mCommandsInFlight.IterateUpTo(GetCompletedCommandSerial())) {
|
||||||
mUnusedCommands.push_back(commands);
|
mUnusedCommands.push_back(commands);
|
||||||
}
|
}
|
||||||
mCommandsInFlight.ClearUpTo(mCompletedSerial);
|
mCommandsInFlight.ClearUpTo(GetCompletedCommandSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
|
ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
|
||||||
@ -726,13 +718,11 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// (so they are as good as waited on) or success.
|
// (so they are as good as waited on) or success.
|
||||||
DAWN_UNUSED(waitIdleResult);
|
DAWN_UNUSED(waitIdleResult);
|
||||||
|
|
||||||
CheckPassedFences();
|
|
||||||
|
|
||||||
// Make sure all fences are complete by explicitly waiting on them all
|
// Make sure all fences are complete by explicitly waiting on them all
|
||||||
while (!mFencesInFlight.empty()) {
|
while (!mFencesInFlight.empty()) {
|
||||||
VkFence fence = mFencesInFlight.front().first;
|
VkFence fence = mFencesInFlight.front().first;
|
||||||
Serial fenceSerial = mFencesInFlight.front().second;
|
Serial fenceSerial = mFencesInFlight.front().second;
|
||||||
ASSERT(fenceSerial > mCompletedSerial);
|
ASSERT(fenceSerial > GetCompletedCommandSerial());
|
||||||
|
|
||||||
VkResult result = VkResult::WrapUnsafe(VK_TIMEOUT);
|
VkResult result = VkResult::WrapUnsafe(VK_TIMEOUT);
|
||||||
do {
|
do {
|
||||||
@ -746,8 +736,10 @@ namespace dawn_native { namespace vulkan {
|
|||||||
fn.DestroyFence(mVkDevice, fence, nullptr);
|
fn.DestroyFence(mVkDevice, fence, nullptr);
|
||||||
|
|
||||||
mFencesInFlight.pop();
|
mFencesInFlight.pop();
|
||||||
mCompletedSerial = fenceSerial;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force all operations to look as if they were completed
|
||||||
|
AssumeCommandsComplete();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,7 +782,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Some operations might have been started since the last submit and waiting
|
// 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
|
// on a serial that doesn't have a corresponding fence enqueued. Force all
|
||||||
// operations to look as if they were completed (because they were).
|
// operations to look as if they were completed (because they were).
|
||||||
mCompletedSerial = mLastSubmittedSerial + 1;
|
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());
|
||||||
@ -808,7 +800,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
|
|
||||||
// Releasing the uploader enqueues buffers to be released.
|
// Releasing the uploader enqueues buffers to be released.
|
||||||
// Call Tick() again to clear them before releasing the deleter.
|
// Call Tick() again to clear them before releasing the deleter.
|
||||||
mDeleter->Tick(mCompletedSerial);
|
mDeleter->Tick(GetCompletedCommandSerial());
|
||||||
|
|
||||||
mMapRequestTracker = nullptr;
|
mMapRequestTracker = nullptr;
|
||||||
|
|
||||||
|
@ -63,7 +63,6 @@ namespace dawn_native { namespace vulkan {
|
|||||||
RenderPassCache* GetRenderPassCache() const;
|
RenderPassCache* GetRenderPassCache() const;
|
||||||
|
|
||||||
CommandRecordingContext* GetPendingRecordingContext();
|
CommandRecordingContext* GetPendingRecordingContext();
|
||||||
Serial GetPendingCommandSerial() const override;
|
|
||||||
MaybeError SubmitPendingCommands();
|
MaybeError SubmitPendingCommands();
|
||||||
|
|
||||||
void EnqueueDeferredDeallocation(BindGroupLayout* bindGroupLayout);
|
void EnqueueDeferredDeallocation(BindGroupLayout* bindGroupLayout);
|
||||||
@ -82,8 +81,6 @@ namespace dawn_native { namespace vulkan {
|
|||||||
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
CommandBufferBase* CreateCommandBuffer(CommandEncoder* encoder,
|
||||||
const CommandBufferDescriptor* descriptor) override;
|
const CommandBufferDescriptor* descriptor) override;
|
||||||
|
|
||||||
Serial GetCompletedCommandSerial() const final override;
|
|
||||||
Serial GetLastSubmittedCommandSerial() const final override;
|
|
||||||
MaybeError TickImpl() override;
|
MaybeError TickImpl() override;
|
||||||
|
|
||||||
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
|
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
|
||||||
@ -158,7 +155,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
std::unique_ptr<external_semaphore::Service> mExternalSemaphoreService;
|
std::unique_ptr<external_semaphore::Service> mExternalSemaphoreService;
|
||||||
|
|
||||||
ResultOrError<VkFence> GetUnusedFence();
|
ResultOrError<VkFence> GetUnusedFence();
|
||||||
void CheckPassedFences();
|
Serial CheckAndUpdateCompletedSerials() override;
|
||||||
|
|
||||||
// We track which operations are in flight on the GPU with an increasing serial.
|
// We track which operations are in flight on the GPU with an increasing serial.
|
||||||
// This works only because we have a single queue. Each submit to a queue is associated
|
// This works only because we have a single queue. Each submit to a queue is associated
|
||||||
@ -167,8 +164,6 @@ namespace dawn_native { namespace vulkan {
|
|||||||
std::queue<std::pair<VkFence, Serial>> mFencesInFlight;
|
std::queue<std::pair<VkFence, Serial>> mFencesInFlight;
|
||||||
// Fences in the unused list aren't reset yet.
|
// Fences in the unused list aren't reset yet.
|
||||||
std::vector<VkFence> mUnusedFences;
|
std::vector<VkFence> mUnusedFences;
|
||||||
Serial mCompletedSerial = 0;
|
|
||||||
Serial mLastSubmittedSerial = 0;
|
|
||||||
|
|
||||||
MaybeError PrepareRecordingContext();
|
MaybeError PrepareRecordingContext();
|
||||||
void RecycleCompletedCommands();
|
void RecycleCompletedCommands();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user