From 8b07e43dadf8cf49fa0aafe3343748b4ec079160 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Sat, 1 Dec 2018 03:20:19 +0000 Subject: [PATCH] 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 Commit-Queue: Austin Eng --- src/dawn_native/Device.h | 4 ++ src/dawn_native/d3d12/BufferD3D12.cpp | 2 +- .../d3d12/CommandAllocatorManager.cpp | 2 +- src/dawn_native/d3d12/CommandBufferD3D12.cpp | 2 +- .../d3d12/DescriptorHeapAllocator.cpp | 2 +- src/dawn_native/d3d12/DeviceD3D12.cpp | 44 +++++++++------- src/dawn_native/d3d12/DeviceD3D12.h | 9 ++-- .../d3d12/NativeSwapChainImplD3D12.cpp | 2 +- src/dawn_native/d3d12/ResourceAllocator.cpp | 2 +- src/dawn_native/metal/DeviceMTL.h | 8 +-- src/dawn_native/metal/DeviceMTL.mm | 46 ++++++++++------- src/dawn_native/null/NullBackend.cpp | 27 ++++++---- src/dawn_native/null/NullBackend.h | 6 ++- src/dawn_native/opengl/DeviceGL.cpp | 51 +++++++++++++++++++ src/dawn_native/opengl/DeviceGL.h | 15 ++++++ src/dawn_native/opengl/QueueGL.cpp | 4 ++ src/dawn_native/vulkan/BufferVk.cpp | 2 +- src/dawn_native/vulkan/DeviceVk.cpp | 29 +++++++---- src/dawn_native/vulkan/DeviceVk.h | 7 +-- src/dawn_native/vulkan/FencedDeleter.cpp | 28 +++++----- 20 files changed, 204 insertions(+), 88 deletions(-) diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h index 59c027212a..16b15d47e0 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 @@ namespace dawn_native { 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 @@ namespace dawn_native { 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 71b6b400e5..7483e3c7c1 100644 --- a/src/dawn_native/d3d12/BufferD3D12.cpp +++ b/src/dawn_native/d3d12/BufferD3D12.cpp @@ -237,7 +237,7 @@ namespace dawn_native { namespace d3d12 { 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 47072fcf6c..90f7a5a895 100644 --- a/src/dawn_native/d3d12/CommandAllocatorManager.cpp +++ b/src/dawn_native/d3d12/CommandAllocatorManager.cpp @@ -52,7 +52,7 @@ namespace dawn_native { namespace d3d12 { // 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 d2aff42bdc..8b90046971 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -71,7 +71,7 @@ namespace dawn_native { namespace d3d12 { // 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 9374dae33d..75d188db01 100644 --- a/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp +++ b/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp @@ -127,6 +127,6 @@ namespace dawn_native { namespace d3d12 { } 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 1d1f741509..6d47920554 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.cpp +++ b/src/dawn_native/d3d12/DeviceD3D12.cpp @@ -144,8 +144,8 @@ namespace dawn_native { namespace d3d12 { 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 @@ namespace dawn_native { namespace d3d12 { } 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 @@ namespace dawn_native { namespace d3d12 { 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 @@ namespace dawn_native { namespace d3d12 { 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 object) { - mUsedComObjectRefs.Enqueue(object, mSerial); + mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial()); } void Device::ExecuteCommandLists(std::initializer_list commandLists) { diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h index 3717e2453e..dfed5662fb 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.h +++ b/src/dawn_native/d3d12/DeviceD3D12.h @@ -52,6 +52,8 @@ namespace dawn_native { namespace d3d12 { 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 @@ namespace dawn_native { namespace d3d12 { void OpenCommandList(ComPtr* commandList); ComPtr GetPendingCommandList(); + Serial GetPendingCommandSerial() const; - uint64_t GetSerial() const; void NextSerial(); - void WaitForSerial(uint64_t serial); + void WaitForSerial(Serial serial); void ReferenceUntilUnused(ComPtr object); @@ -99,7 +101,8 @@ namespace dawn_native { namespace d3d12 { // D3D12 DLLs are unloaded before we are done using it. std::unique_ptr mFunctions; - uint64_t mSerial = 0; + Serial mCompletedSerial = 0; + Serial mLastSubmittedSerial = 0; ComPtr mFence; HANDLE mFenceEvent; diff --git a/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp b/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp index 99ac8f8091..577d8fa2bc 100644 --- a/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp +++ b/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp @@ -107,7 +107,7 @@ namespace dawn_native { namespace d3d12 { // 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 c50de5b5c4..e2822e64cf 100644 --- a/src/dawn_native/d3d12/ResourceAllocator.cpp +++ b/src/dawn_native/d3d12/ResourceAllocator.cpp @@ -67,7 +67,7 @@ namespace dawn_native { namespace d3d12 { void ResourceAllocator::Release(ComPtr 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 da586ee459..58335886b3 100644 --- a/src/dawn_native/metal/DeviceMTL.h +++ b/src/dawn_native/metal/DeviceMTL.h @@ -48,6 +48,8 @@ namespace dawn_native { namespace metal { 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 @@ namespace dawn_native { namespace metal { id GetMTLDevice(); id GetPendingCommandBuffer(); + Serial GetPendingCommandSerial() const; void SubmitPendingCommandBuffer(); - Serial GetPendingCommandSerial(); MapRequestTracker* GetMapTracker() const; ResourceUploader* GetResourceUploader() const; @@ -86,8 +88,8 @@ namespace dawn_native { namespace metal { std::unique_ptr mMapTracker; std::unique_ptr mResourceUploader; - Serial mFinishedCommandSerial = 0; - Serial mPendingCommandSerial = 1; + Serial mCompletedSerial = 0; + Serial mLastSubmittedSerial = 0; id mPendingCommands = nil; dawn_native::PCIInfo mPCIInfo; diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm index a01ab6a83e..0484e7aa87 100644 --- a/src/dawn_native/metal/DeviceMTL.mm +++ b/src/dawn_native/metal/DeviceMTL.mm @@ -144,7 +144,7 @@ namespace dawn_native { namespace metal { // 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 @@ namespace dawn_native { namespace metal { 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 @@ namespace dawn_native { namespace metal { // 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) { - 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 86fbca71e9..9512f0f3df 100644 --- a/src/dawn_native/null/NullBackend.cpp +++ b/src/dawn_native/null/NullBackend.cpp @@ -109,14 +109,29 @@ namespace dawn_native { namespace null { return mPCIInfo; } + Serial Device::GetCompletedCommandSerial() const { + return mCompletedSerial; + } + + Serial Device::GetLastSubmittedCommandSerial() const { + return mLastSubmittedSerial; + } + void Device::TickImpl() { + SubmitPendingOperations(); } void Device::AddPendingOperation(std::unique_ptr operation) { mPendingOperations.emplace_back(std::move(operation)); } - std::vector> 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 @@ namespace dawn_native { namespace null { } 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 0c50ae9493..b77f6cf648 100644 --- a/src/dawn_native/null/NullBackend.h +++ b/src/dawn_native/null/NullBackend.h @@ -106,12 +106,14 @@ namespace dawn_native { namespace null { 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 operation); - std::vector> AcquirePendingOperations(); + void SubmitPendingOperations(); private: ResultOrError CreateBindGroupLayoutImpl( @@ -131,6 +133,8 @@ namespace dawn_native { namespace null { const TextureViewDescriptor* descriptor) override; void InitFakePCIInfo(); + Serial mCompletedSerial = 0; + Serial mLastSubmittedSerial = 0; std::vector> mPendingOperations; dawn_native::PCIInfo mPCIInfo; }; diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp index f2dc8bcdae..e58fb02155 100644 --- a/src/dawn_native/opengl/DeviceGL.cpp +++ b/src/dawn_native/opengl/DeviceGL.cpp @@ -50,6 +50,17 @@ namespace dawn_native { namespace opengl { 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 @@ namespace dawn_native { namespace opengl { 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 2b39db54e4..90b14acf5c 100644 --- a/src/dawn_native/opengl/DeviceGL.h +++ b/src/dawn_native/opengl/DeviceGL.h @@ -23,6 +23,8 @@ #include "glad/glad.h" +#include + // 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 @@ namespace dawn_native { namespace opengl { 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 @@ namespace dawn_native { namespace opengl { 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 @@ namespace dawn_native { namespace opengl { const TextureViewDescriptor* descriptor) override; void CollectPCIInfo(); + void CheckPassedFences(); + + Serial mCompletedSerial = 0; + Serial mLastSubmittedSerial = 0; + std::queue> mFencesInFlight; + dawn_native::PCIInfo mPCIInfo; }; diff --git a/src/dawn_native/opengl/QueueGL.cpp b/src/dawn_native/opengl/QueueGL.cpp index ad17160307..a03fb180df 100644 --- a/src/dawn_native/opengl/QueueGL.cpp +++ b/src/dawn_native/opengl/QueueGL.cpp @@ -23,9 +23,13 @@ namespace dawn_native { namespace opengl { } 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 3c7d1370b7..73e1538419 100644 --- a/src/dawn_native/vulkan/BufferVk.cpp +++ b/src/dawn_native/vulkan/BufferVk.cpp @@ -252,7 +252,7 @@ namespace dawn_native { namespace vulkan { 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 5b3b976fa4..7b1cdd5331 100644 --- a/src/dawn_native/vulkan/DeviceVk.cpp +++ b/src/dawn_native/vulkan/DeviceVk.cpp @@ -170,7 +170,7 @@ namespace dawn_native { namespace vulkan { // 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 @@ namespace dawn_native { namespace vulkan { 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 @@ namespace dawn_native { namespace vulkan { 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 @@ namespace dawn_native { namespace vulkan { return mRenderPassCache.get(); } - Serial Device::GetSerial() const { - return mNextSerial; - } - VkCommandBuffer Device::GetPendingCommandBuffer() { if (mPendingCommands.pool == VK_NULL_HANDLE) { mPendingCommands = GetUnusedCommands(); @@ -395,16 +403,15 @@ namespace dawn_native { namespace vulkan { 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 c11427c2df..35fd591bd0 100644 --- a/src/dawn_native/vulkan/DeviceVk.h +++ b/src/dawn_native/vulkan/DeviceVk.h @@ -57,9 +57,8 @@ namespace dawn_native { namespace vulkan { MemoryAllocator* GetMemoryAllocator() const; RenderPassCache* GetRenderPassCache() const; - Serial GetSerial() const; - VkCommandBuffer GetPendingCommandBuffer(); + Serial GetPendingCommandSerial() const; void SubmitPendingCommands(); void AddWaitSemaphore(VkSemaphore semaphore); @@ -75,6 +74,8 @@ namespace dawn_native { namespace vulkan { 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 @@ namespace dawn_native { namespace vulkan { // have finished. std::queue> mFencesInFlight; std::vector 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 6503f7334d..729ea29ae8 100644 --- a/src/dawn_native/vulkan/FencedDeleter.cpp +++ b/src/dawn_native/vulkan/FencedDeleter.cpp @@ -39,59 +39,59 @@ namespace dawn_native { namespace vulkan { } 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) {