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:
Austin Eng 2018-12-01 03:20:19 +00:00 committed by Commit Bot service account
parent 179db44c25
commit 8b07e43dad
20 changed files with 204 additions and 88 deletions

View File

@ -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();

View File

@ -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) {

View File

@ -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];
}

View File

@ -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,

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;

View File

@ -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 {

View File

@ -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

View File

@ -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;
};

View File

@ -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 {

View File

@ -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;
};

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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) {