Let DeviceBase know about Completed and LastSubmitted command Serials
This is needed to implement the timeline fence signal tracker in the frontend
Bug: dawn:26
Change-Id: Id6eb2afb81385de5093b57c5cb23ace93c8aab1b
Reviewed-on: https://dawn-review.googlesource.com/c/2741
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index 59c0272..16b15d4 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_DEVICEBASE_H_
#define DAWNNATIVE_DEVICEBASE_H_
+#include "common/Serial.h"
#include "dawn_native/Error.h"
#include "dawn_native/Forward.h"
#include "dawn_native/ObjectBase.h"
@@ -58,6 +59,8 @@
virtual RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) = 0;
virtual SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) = 0;
+ virtual Serial GetCompletedCommandSerial() const = 0;
+ virtual Serial GetLastSubmittedCommandSerial() const = 0;
virtual void TickImpl() = 0;
// Many Dawn objects are completely immutable once created which means that if two
@@ -99,6 +102,7 @@
const TextureViewDescriptor* descriptor);
void Tick();
+
void SetErrorCallback(dawn::DeviceErrorCallback callback, dawn::CallbackUserdata userdata);
void Reference();
void Release();
diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp
index 71b6b40..7483e3c 100644
--- a/src/dawn_native/d3d12/BufferD3D12.cpp
+++ b/src/dawn_native/d3d12/BufferD3D12.cpp
@@ -237,7 +237,7 @@
request.data = data;
request.isWrite = isWrite;
- mInflightRequests.Enqueue(std::move(request), mDevice->GetSerial());
+ mInflightRequests.Enqueue(std::move(request), mDevice->GetPendingCommandSerial());
}
void MapRequestTracker::Tick(Serial finishedSerial) {
diff --git a/src/dawn_native/d3d12/CommandAllocatorManager.cpp b/src/dawn_native/d3d12/CommandAllocatorManager.cpp
index 47072fc..90f7a5a 100644
--- a/src/dawn_native/d3d12/CommandAllocatorManager.cpp
+++ b/src/dawn_native/d3d12/CommandAllocatorManager.cpp
@@ -52,7 +52,7 @@
// Enqueue the command allocator. It will be scheduled for reset after the next
// ExecuteCommandLists
mInFlightCommandAllocators.Enqueue({mCommandAllocators[firstFreeIndex], firstFreeIndex},
- device->GetSerial());
+ device->GetPendingCommandSerial());
return mCommandAllocators[firstFreeIndex];
}
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index d2aff42..8b90046 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -71,7 +71,7 @@
// Descriptors don't need to be recorded if they have already been recorded in
// the heap. Indices are only updated when descriptors are recorded
- const uint64_t serial = device->GetSerial();
+ const uint64_t serial = device->GetPendingCommandSerial();
if (group->GetHeapSerial() != serial ||
group->GetIndexInSubmit() != indexInSubmit) {
group->RecordDescriptors(cbvSrvUavCPUDescriptorHeap, &cbvSrvUavDescriptorIndex,
diff --git a/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp b/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp
index 9374dae..75d188d 100644
--- a/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp
+++ b/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp
@@ -127,6 +127,6 @@
}
void DescriptorHeapAllocator::Release(DescriptorHeapHandle handle) {
- mReleasedHandles.Enqueue(handle, mDevice->GetSerial());
+ mReleasedHandles.Enqueue(handle, mDevice->GetPendingCommandSerial());
}
}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index 1d1f741..6d47920 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -144,8 +144,8 @@
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
ASSERT_SUCCESS(mD3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)));
- ASSERT_SUCCESS(
- mD3d12Device->CreateFence(mSerial, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence)));
+ ASSERT_SUCCESS(mD3d12Device->CreateFence(mLastSubmittedSerial, D3D12_FENCE_FLAG_NONE,
+ IID_PPV_ARGS(&mFence)));
mFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
ASSERT(mFenceEvent != nullptr);
@@ -160,9 +160,8 @@
}
Device::~Device() {
- const uint64_t currentSerial = GetSerial();
NextSerial();
- WaitForSerial(currentSerial); // Wait for all in-flight commands to finish executing
+ WaitForSerial(mLastSubmittedSerial); // Wait for all in-flight commands to finish executing
TickImpl(); // Call tick one last time so resources are cleaned up
ASSERT(mUsedComObjectRefs.Empty());
@@ -224,14 +223,26 @@
return mPendingCommands.commandList;
}
+ Serial Device::GetCompletedCommandSerial() const {
+ return mCompletedSerial;
+ }
+
+ Serial Device::GetLastSubmittedCommandSerial() const {
+ return mLastSubmittedSerial;
+ }
+
+ Serial Device::GetPendingCommandSerial() const {
+ return mLastSubmittedSerial + 1;
+ }
+
void Device::TickImpl() {
// Perform cleanup operations to free unused objects
- const uint64_t lastCompletedSerial = mFence->GetCompletedValue();
- mResourceAllocator->Tick(lastCompletedSerial);
- mCommandAllocatorManager->Tick(lastCompletedSerial);
- mDescriptorHeapAllocator->Tick(lastCompletedSerial);
- mMapRequestTracker->Tick(lastCompletedSerial);
- mUsedComObjectRefs.ClearUpTo(lastCompletedSerial);
+ mCompletedSerial = mFence->GetCompletedValue();
+ mResourceAllocator->Tick(mCompletedSerial);
+ mCommandAllocatorManager->Tick(mCompletedSerial);
+ mDescriptorHeapAllocator->Tick(mCompletedSerial);
+ mMapRequestTracker->Tick(mCompletedSerial);
+ mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
ExecuteCommandLists({});
NextSerial();
}
@@ -240,24 +251,21 @@
return mPCIInfo;
}
- uint64_t Device::GetSerial() const {
- return mSerial;
- }
-
void Device::NextSerial() {
- ASSERT_SUCCESS(mCommandQueue->Signal(mFence.Get(), mSerial++));
+ mLastSubmittedSerial++;
+ ASSERT_SUCCESS(mCommandQueue->Signal(mFence.Get(), mLastSubmittedSerial));
}
void Device::WaitForSerial(uint64_t serial) {
- const uint64_t lastCompletedSerial = mFence->GetCompletedValue();
- if (lastCompletedSerial < serial) {
+ mCompletedSerial = mFence->GetCompletedValue();
+ if (mCompletedSerial < serial) {
ASSERT_SUCCESS(mFence->SetEventOnCompletion(serial, mFenceEvent));
WaitForSingleObject(mFenceEvent, INFINITE);
}
}
void Device::ReferenceUntilUnused(ComPtr<IUnknown> object) {
- mUsedComObjectRefs.Enqueue(object, mSerial);
+ mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial());
}
void Device::ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists) {
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index 3717e24..dfed566 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -52,6 +52,8 @@
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
+ Serial GetCompletedCommandSerial() const final override;
+ Serial GetLastSubmittedCommandSerial() const final override;
void TickImpl() override;
const dawn_native::PCIInfo& GetPCIInfo() const override;
@@ -68,10 +70,10 @@
void OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList);
ComPtr<ID3D12GraphicsCommandList> GetPendingCommandList();
+ Serial GetPendingCommandSerial() const;
- uint64_t GetSerial() const;
void NextSerial();
- void WaitForSerial(uint64_t serial);
+ void WaitForSerial(Serial serial);
void ReferenceUntilUnused(ComPtr<IUnknown> object);
@@ -99,7 +101,8 @@
// D3D12 DLLs are unloaded before we are done using it.
std::unique_ptr<PlatformFunctions> mFunctions;
- uint64_t mSerial = 0;
+ Serial mCompletedSerial = 0;
+ Serial mLastSubmittedSerial = 0;
ComPtr<ID3D12Fence> mFence;
HANDLE mFenceEvent;
diff --git a/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp b/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp
index 99ac8f8..577d8fa 100644
--- a/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp
+++ b/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp
@@ -107,7 +107,7 @@
// TODO(cwallez@chromium.org): Make the serial ticking implicit.
mDevice->NextSerial();
- mBufferSerials[mCurrentBuffer] = mDevice->GetSerial();
+ mBufferSerials[mCurrentBuffer] = mDevice->GetPendingCommandSerial();
return DAWN_SWAP_CHAIN_NO_ERROR;
}
diff --git a/src/dawn_native/d3d12/ResourceAllocator.cpp b/src/dawn_native/d3d12/ResourceAllocator.cpp
index c50de5b..e2822e6 100644
--- a/src/dawn_native/d3d12/ResourceAllocator.cpp
+++ b/src/dawn_native/d3d12/ResourceAllocator.cpp
@@ -67,7 +67,7 @@
void ResourceAllocator::Release(ComPtr<ID3D12Resource> resource) {
// Resources may still be in use on the GPU. Enqueue them so that we hold onto them until
// GPU execution has completed
- mReleasedResources.Enqueue(resource, mDevice->GetSerial());
+ mReleasedResources.Enqueue(resource, mDevice->GetPendingCommandSerial());
}
void ResourceAllocator::Tick(uint64_t lastCompletedSerial) {
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index da586ee..5833588 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -48,6 +48,8 @@
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
+ Serial GetCompletedCommandSerial() const final override;
+ Serial GetLastSubmittedCommandSerial() const final override;
void TickImpl() override;
const dawn_native::PCIInfo& GetPCIInfo() const override;
@@ -55,8 +57,8 @@
id<MTLDevice> GetMTLDevice();
id<MTLCommandBuffer> GetPendingCommandBuffer();
+ Serial GetPendingCommandSerial() const;
void SubmitPendingCommandBuffer();
- Serial GetPendingCommandSerial();
MapRequestTracker* GetMapTracker() const;
ResourceUploader* GetResourceUploader() const;
@@ -86,8 +88,8 @@
std::unique_ptr<MapRequestTracker> mMapTracker;
std::unique_ptr<ResourceUploader> mResourceUploader;
- Serial mFinishedCommandSerial = 0;
- Serial mPendingCommandSerial = 1;
+ Serial mCompletedSerial = 0;
+ Serial mLastSubmittedSerial = 0;
id<MTLCommandBuffer> mPendingCommands = nil;
dawn_native::PCIInfo mPCIInfo;
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index a01ab6a..0484e7a 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -144,7 +144,7 @@
// store the pendingSerial before SubmitPendingCommandBuffer then wait for it to be passed.
// Instead we submit and wait for the serial before the next pendingCommandSerial.
SubmitPendingCommandBuffer();
- while (mFinishedCommandSerial != mPendingCommandSerial - 1) {
+ while (mCompletedSerial != mLastSubmittedSerial) {
usleep(100);
}
Tick();
@@ -224,13 +224,30 @@
return new TextureView(texture, descriptor);
}
- void Device::TickImpl() {
- mResourceUploader->Tick(mFinishedCommandSerial);
- mMapTracker->Tick(mFinishedCommandSerial);
+ Serial Device::GetCompletedCommandSerial() const {
+ return mCompletedSerial;
+ }
- // Code above might have added GPU work, submit it. This also makes sure
- // that even when no GPU work is happening, the serial number keeps incrementing.
- SubmitPendingCommandBuffer();
+ Serial Device::GetLastSubmittedCommandSerial() const {
+ return mLastSubmittedSerial;
+ }
+
+ Serial Device::GetPendingCommandSerial() const {
+ return mLastSubmittedSerial + 1;
+ }
+
+ void Device::TickImpl() {
+ mResourceUploader->Tick(mCompletedSerial);
+ mMapTracker->Tick(mCompletedSerial);
+
+ if (mPendingCommands != nil) {
+ SubmitPendingCommandBuffer();
+ } else if (mCompletedSerial == mLastSubmittedSerial) {
+ // 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.
+ mCompletedSerial++;
+ mLastSubmittedSerial++;
+ }
}
const dawn_native::PCIInfo& Device::GetPCIInfo() const {
@@ -258,24 +275,15 @@
// so this-> works as expected. However it is unclear how members are captured, (are they
// captured using this-> or by value?) so we make a copy of the pendingCommandSerial on the
// stack.
- Serial pendingSerial = mPendingCommandSerial;
+ mLastSubmittedSerial++;
+ Serial pendingSerial = mLastSubmittedSerial;
[mPendingCommands addCompletedHandler:^(id<MTLCommandBuffer>) {
- this->mFinishedCommandSerial = pendingSerial;
+ this->mCompletedSerial = pendingSerial;
}];
[mPendingCommands commit];
[mPendingCommands release];
mPendingCommands = nil;
- mPendingCommandSerial++;
- }
-
- uint64_t Device::GetPendingCommandSerial() {
- // If this is called, then it means some piece of code somewhere will wait for this serial
- // to complete. Make sure the pending command buffer is created so that it is on the worst
- // case enqueued on the next Tick() and eventually increments the serial. Otherwise if no
- // GPU work happens we could be waiting for this serial forever.
- GetPendingCommandBuffer();
- return mPendingCommandSerial;
}
MapRequestTracker* Device::GetMapTracker() const {
diff --git a/src/dawn_native/null/NullBackend.cpp b/src/dawn_native/null/NullBackend.cpp
index 86fbca7..9512f0f 100644
--- a/src/dawn_native/null/NullBackend.cpp
+++ b/src/dawn_native/null/NullBackend.cpp
@@ -109,14 +109,29 @@
return mPCIInfo;
}
+ Serial Device::GetCompletedCommandSerial() const {
+ return mCompletedSerial;
+ }
+
+ Serial Device::GetLastSubmittedCommandSerial() const {
+ return mLastSubmittedSerial;
+ }
+
void Device::TickImpl() {
+ SubmitPendingOperations();
}
void Device::AddPendingOperation(std::unique_ptr<PendingOperation> operation) {
mPendingOperations.emplace_back(std::move(operation));
}
- std::vector<std::unique_ptr<PendingOperation>> Device::AcquirePendingOperations() {
- return std::move(mPendingOperations);
+ void Device::SubmitPendingOperations() {
+ for (auto& operation : mPendingOperations) {
+ operation->Execute();
+ }
+ mPendingOperations.clear();
+
+ mCompletedSerial = mLastSubmittedSerial;
+ mLastSubmittedSerial++;
}
// Buffer
@@ -200,13 +215,7 @@
}
void Queue::SubmitImpl(uint32_t, CommandBufferBase* const*) {
- auto operations = ToBackend(GetDevice())->AcquirePendingOperations();
-
- for (auto& operation : operations) {
- operation->Execute();
- }
-
- operations.clear();
+ ToBackend(GetDevice())->SubmitPendingOperations();
}
// SwapChain
diff --git a/src/dawn_native/null/NullBackend.h b/src/dawn_native/null/NullBackend.h
index 0c50ae9..b77f6cf 100644
--- a/src/dawn_native/null/NullBackend.h
+++ b/src/dawn_native/null/NullBackend.h
@@ -106,12 +106,14 @@
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
+ Serial GetCompletedCommandSerial() const final override;
+ Serial GetLastSubmittedCommandSerial() const final override;
void TickImpl() override;
const dawn_native::PCIInfo& GetPCIInfo() const override;
void AddPendingOperation(std::unique_ptr<PendingOperation> operation);
- std::vector<std::unique_ptr<PendingOperation>> AcquirePendingOperations();
+ void SubmitPendingOperations();
private:
ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
@@ -131,6 +133,8 @@
const TextureViewDescriptor* descriptor) override;
void InitFakePCIInfo();
+ Serial mCompletedSerial = 0;
+ Serial mLastSubmittedSerial = 0;
std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
dawn_native::PCIInfo mPCIInfo;
};
diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp
index f2dc8bc..e58fb02 100644
--- a/src/dawn_native/opengl/DeviceGL.cpp
+++ b/src/dawn_native/opengl/DeviceGL.cpp
@@ -50,6 +50,17 @@
CollectPCIInfo();
}
+ Device::~Device() {
+ CheckPassedFences();
+ ASSERT(mFencesInFlight.empty());
+
+ // 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).
+ mCompletedSerial = mLastSubmittedSerial + 1;
+ Tick();
+ }
+
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
return new BindGroup(builder);
}
@@ -112,7 +123,47 @@
return new TextureView(texture, descriptor);
}
+ void Device::SubmitFenceSync() {
+ GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ mLastSubmittedSerial++;
+ mFencesInFlight.emplace(sync, mLastSubmittedSerial);
+ }
+
+ Serial Device::GetCompletedCommandSerial() const {
+ return mCompletedSerial;
+ }
+
+ Serial Device::GetLastSubmittedCommandSerial() const {
+ return mLastSubmittedSerial;
+ }
+
void Device::TickImpl() {
+ CheckPassedFences();
+ }
+
+ void Device::CheckPassedFences() {
+ while (!mFencesInFlight.empty()) {
+ GLsync sync = mFencesInFlight.front().first;
+ Serial fenceSerial = mFencesInFlight.front().second;
+
+ GLint status = 0;
+ GLsizei length;
+ glGetSynciv(sync, GL_SYNC_CONDITION, sizeof(GLint), &length, &status);
+ ASSERT(length == 1);
+
+ // Fence are added in order, so we can stop searching as soon
+ // as we see one that's not ready.
+ if (!status) {
+ return;
+ }
+
+ glDeleteSync(sync);
+
+ mFencesInFlight.pop();
+
+ ASSERT(fenceSerial > mCompletedSerial);
+ mCompletedSerial = fenceSerial;
+ }
}
const dawn_native::PCIInfo& Device::GetPCIInfo() const {
diff --git a/src/dawn_native/opengl/DeviceGL.h b/src/dawn_native/opengl/DeviceGL.h
index 2b39db5..90b14ac 100644
--- a/src/dawn_native/opengl/DeviceGL.h
+++ b/src/dawn_native/opengl/DeviceGL.h
@@ -23,6 +23,8 @@
#include "glad/glad.h"
+#include <queue>
+
// Remove windows.h macros after glad's include of windows.h
#if defined(DAWN_PLATFORM_WINDOWS)
# include "common/windows_with_undefs.h"
@@ -33,6 +35,11 @@
class Device : public DeviceBase {
public:
Device();
+ ~Device();
+
+ void SubmitFenceSync();
+
+ // Dawn API
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
@@ -44,6 +51,8 @@
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
+ Serial GetCompletedCommandSerial() const final override;
+ Serial GetLastSubmittedCommandSerial() const final override;
void TickImpl() override;
const dawn_native::PCIInfo& GetPCIInfo() const override;
@@ -66,6 +75,12 @@
const TextureViewDescriptor* descriptor) override;
void CollectPCIInfo();
+ void CheckPassedFences();
+
+ Serial mCompletedSerial = 0;
+ Serial mLastSubmittedSerial = 0;
+ std::queue<std::pair<GLsync, Serial>> mFencesInFlight;
+
dawn_native::PCIInfo mPCIInfo;
};
diff --git a/src/dawn_native/opengl/QueueGL.cpp b/src/dawn_native/opengl/QueueGL.cpp
index ad17160..a03fb18 100644
--- a/src/dawn_native/opengl/QueueGL.cpp
+++ b/src/dawn_native/opengl/QueueGL.cpp
@@ -23,9 +23,13 @@
}
void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) {
+ Device* device = ToBackend(GetDevice());
+
for (uint32_t i = 0; i < numCommands; ++i) {
ToBackend(commands[i])->Execute();
}
+
+ device->SubmitFenceSync();
}
}} // namespace dawn_native::opengl
diff --git a/src/dawn_native/vulkan/BufferVk.cpp b/src/dawn_native/vulkan/BufferVk.cpp
index 3c7d137..73e1538 100644
--- a/src/dawn_native/vulkan/BufferVk.cpp
+++ b/src/dawn_native/vulkan/BufferVk.cpp
@@ -252,7 +252,7 @@
request.data = data;
request.isWrite = isWrite;
- mInflightRequests.Enqueue(std::move(request), mDevice->GetSerial());
+ mInflightRequests.Enqueue(std::move(request), mDevice->GetPendingCommandSerial());
}
void MapRequestTracker::Tick(Serial finishedSerial) {
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 5b3b976..7b1cdd5 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -170,7 +170,7 @@
// 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).
- mCompletedSerial = mNextSerial;
+ mCompletedSerial = mLastSubmittedSerial + 1;
Tick();
ASSERT(mCommandsInFlight.Empty());
@@ -277,6 +277,18 @@
return new TextureView(texture, descriptor);
}
+ Serial Device::GetCompletedCommandSerial() const {
+ return mCompletedSerial;
+ }
+
+ Serial Device::GetLastSubmittedCommandSerial() const {
+ return mLastSubmittedSerial;
+ }
+
+ Serial Device::GetPendingCommandSerial() const {
+ return mLastSubmittedSerial + 1;
+ }
+
void Device::TickImpl() {
CheckPassedFences();
RecycleCompletedCommands();
@@ -289,11 +301,11 @@
if (mPendingCommands.pool != VK_NULL_HANDLE) {
SubmitPendingCommands();
- } else if (mCompletedSerial == mNextSerial - 1) {
+ } else if (mCompletedSerial == mLastSubmittedSerial) {
// 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.
mCompletedSerial++;
- mNextSerial++;
+ mLastSubmittedSerial++;
}
}
@@ -345,10 +357,6 @@
return mRenderPassCache.get();
}
- Serial Device::GetSerial() const {
- return mNextSerial;
- }
-
VkCommandBuffer Device::GetPendingCommandBuffer() {
if (mPendingCommands.pool == VK_NULL_HANDLE) {
mPendingCommands = GetUnusedCommands();
@@ -395,16 +403,15 @@
ASSERT(false);
}
- mCommandsInFlight.Enqueue(mPendingCommands, mNextSerial);
+ mLastSubmittedSerial++;
+ mCommandsInFlight.Enqueue(mPendingCommands, mLastSubmittedSerial);
mPendingCommands = CommandPoolAndBuffer();
- mFencesInFlight.emplace(fence, mNextSerial);
+ mFencesInFlight.emplace(fence, mLastSubmittedSerial);
for (VkSemaphore semaphore : mWaitSemaphores) {
mDeleter->DeleteWhenUnused(semaphore);
}
mWaitSemaphores.clear();
-
- mNextSerial++;
}
void Device::AddWaitSemaphore(VkSemaphore semaphore) {
diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h
index c11427c..35fd591 100644
--- a/src/dawn_native/vulkan/DeviceVk.h
+++ b/src/dawn_native/vulkan/DeviceVk.h
@@ -57,9 +57,8 @@
MemoryAllocator* GetMemoryAllocator() const;
RenderPassCache* GetRenderPassCache() const;
- Serial GetSerial() const;
-
VkCommandBuffer GetPendingCommandBuffer();
+ Serial GetPendingCommandSerial() const;
void SubmitPendingCommands();
void AddWaitSemaphore(VkSemaphore semaphore);
@@ -75,6 +74,8 @@
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
+ Serial GetCompletedCommandSerial() const final override;
+ Serial GetLastSubmittedCommandSerial() const final override;
void TickImpl() override;
const dawn_native::PCIInfo& GetPCIInfo() const override;
@@ -143,8 +144,8 @@
// have finished.
std::queue<std::pair<VkFence, Serial>> mFencesInFlight;
std::vector<VkFence> mUnusedFences;
- Serial mNextSerial = 1;
Serial mCompletedSerial = 0;
+ Serial mLastSubmittedSerial = 0;
struct CommandPoolAndBuffer {
VkCommandPool pool = VK_NULL_HANDLE;
diff --git a/src/dawn_native/vulkan/FencedDeleter.cpp b/src/dawn_native/vulkan/FencedDeleter.cpp
index 6503f73..729ea29 100644
--- a/src/dawn_native/vulkan/FencedDeleter.cpp
+++ b/src/dawn_native/vulkan/FencedDeleter.cpp
@@ -39,59 +39,59 @@
}
void FencedDeleter::DeleteWhenUnused(VkBuffer buffer) {
- mBuffersToDelete.Enqueue(buffer, mDevice->GetSerial());
+ mBuffersToDelete.Enqueue(buffer, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkDescriptorPool pool) {
- mDescriptorPoolsToDelete.Enqueue(pool, mDevice->GetSerial());
+ mDescriptorPoolsToDelete.Enqueue(pool, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkDeviceMemory memory) {
- mMemoriesToDelete.Enqueue(memory, mDevice->GetSerial());
+ mMemoriesToDelete.Enqueue(memory, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkFramebuffer framebuffer) {
- mFramebuffersToDelete.Enqueue(framebuffer, mDevice->GetSerial());
+ mFramebuffersToDelete.Enqueue(framebuffer, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkImage image) {
- mImagesToDelete.Enqueue(image, mDevice->GetSerial());
+ mImagesToDelete.Enqueue(image, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkImageView view) {
- mImageViewsToDelete.Enqueue(view, mDevice->GetSerial());
+ mImageViewsToDelete.Enqueue(view, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkPipeline pipeline) {
- mPipelinesToDelete.Enqueue(pipeline, mDevice->GetSerial());
+ mPipelinesToDelete.Enqueue(pipeline, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkPipelineLayout layout) {
- mPipelineLayoutsToDelete.Enqueue(layout, mDevice->GetSerial());
+ mPipelineLayoutsToDelete.Enqueue(layout, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkRenderPass renderPass) {
- mRenderPassesToDelete.Enqueue(renderPass, mDevice->GetSerial());
+ mRenderPassesToDelete.Enqueue(renderPass, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkSampler sampler) {
- mSamplersToDelete.Enqueue(sampler, mDevice->GetSerial());
+ mSamplersToDelete.Enqueue(sampler, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkSemaphore semaphore) {
- mSemaphoresToDelete.Enqueue(semaphore, mDevice->GetSerial());
+ mSemaphoresToDelete.Enqueue(semaphore, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkShaderModule module) {
- mShaderModulesToDelete.Enqueue(module, mDevice->GetSerial());
+ mShaderModulesToDelete.Enqueue(module, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkSurfaceKHR surface) {
- mSurfacesToDelete.Enqueue(surface, mDevice->GetSerial());
+ mSurfacesToDelete.Enqueue(surface, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::DeleteWhenUnused(VkSwapchainKHR swapChain) {
- mSwapChainsToDelete.Enqueue(swapChain, mDevice->GetSerial());
+ mSwapChainsToDelete.Enqueue(swapChain, mDevice->GetPendingCommandSerial());
}
void FencedDeleter::Tick(Serial completedSerial) {