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>
This commit is contained in:
parent
179db44c25
commit
8b07e43dad
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<IUnknown> object) {
|
||||
mUsedComObjectRefs.Enqueue(object, mSerial);
|
||||
mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial());
|
||||
}
|
||||
|
||||
void Device::ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists) {
|
||||
|
|
|
@ -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<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 @@ namespace dawn_native { namespace d3d12 {
|
|||
// 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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
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) {
|
||||
|
|
|
@ -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<MTLDevice> GetMTLDevice();
|
||||
|
||||
id<MTLCommandBuffer> 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<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;
|
||||
|
|
|
@ -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<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 {
|
||||
|
|
|
@ -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<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 @@ 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
|
||||
|
|
|
@ -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<PendingOperation> operation);
|
||||
std::vector<std::unique_ptr<PendingOperation>> AcquirePendingOperations();
|
||||
void SubmitPendingOperations();
|
||||
|
||||
private:
|
||||
ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
|
||||
|
@ -131,6 +133,8 @@ namespace dawn_native { namespace null {
|
|||
const TextureViewDescriptor* descriptor) override;
|
||||
void InitFakePCIInfo();
|
||||
|
||||
Serial mCompletedSerial = 0;
|
||||
Serial mLastSubmittedSerial = 0;
|
||||
std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
|
||||
dawn_native::PCIInfo mPCIInfo;
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 @@ 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<std::pair<GLsync, Serial>> mFencesInFlight;
|
||||
|
||||
dawn_native::PCIInfo mPCIInfo;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue