diff --git a/filament/backend/CMakeLists.txt b/filament/backend/CMakeLists.txt index 0a07c82836d..f0dd0309008 100644 --- a/filament/backend/CMakeLists.txt +++ b/filament/backend/CMakeLists.txt @@ -221,9 +221,6 @@ if (FILAMENT_SUPPORTS_VULKAN) src/vulkan/VulkanSwapChain.h src/vulkan/VulkanReadPixels.cpp src/vulkan/VulkanReadPixels.h - src/vulkan/VulkanResourceAllocator.h - src/vulkan/VulkanResources.cpp - src/vulkan/VulkanResources.h src/vulkan/VulkanTexture.cpp src/vulkan/VulkanTexture.h src/vulkan/VulkanUtility.cpp diff --git a/filament/backend/src/vulkan/VulkanAsyncHandles.cpp b/filament/backend/src/vulkan/VulkanAsyncHandles.cpp index 46d6ed38bf6..82963b05c4d 100644 --- a/filament/backend/src/vulkan/VulkanAsyncHandles.cpp +++ b/filament/backend/src/vulkan/VulkanAsyncHandles.cpp @@ -19,8 +19,7 @@ namespace filament::backend { VulkanTimerQuery::VulkanTimerQuery(std::tuple indices) - : VulkanThreadSafeResource(VulkanResourceType::TIMER_QUERY), - mStartingQueryIndex(std::get<0>(indices)), + : mStartingQueryIndex(std::get<0>(indices)), mStoppingQueryIndex(std::get<1>(indices)) {} void VulkanTimerQuery::setFence(std::shared_ptr fence) noexcept { diff --git a/filament/backend/src/vulkan/VulkanAsyncHandles.h b/filament/backend/src/vulkan/VulkanAsyncHandles.h index 4e7920fd4da..eb626871ae3 100644 --- a/filament/backend/src/vulkan/VulkanAsyncHandles.h +++ b/filament/backend/src/vulkan/VulkanAsyncHandles.h @@ -21,7 +21,7 @@ #include "DriverBase.h" -#include "VulkanResources.h" +#include "vulkan/memory/Resource.h" #include #include @@ -47,17 +47,12 @@ struct VulkanCmdFence { std::atomic status; }; -struct VulkanFence : public HwFence, VulkanResource { - VulkanFence() : VulkanResource(VulkanResourceType::FENCE) {} - - explicit VulkanFence(std::shared_ptr fence) - : VulkanResource(VulkanResourceType::FENCE), - fence(fence) {} - +struct VulkanFence : public HwFence, fvkmemory::ThreadSafeResource { + VulkanFence() {} std::shared_ptr fence; }; -struct VulkanTimerQuery : public HwTimerQuery, VulkanThreadSafeResource { +struct VulkanTimerQuery : public HwTimerQuery, fvkmemory::ThreadSafeResource { explicit VulkanTimerQuery(std::tuple indices); ~VulkanTimerQuery(); diff --git a/filament/backend/src/vulkan/VulkanCommands.cpp b/filament/backend/src/vulkan/VulkanCommands.cpp index c3548d5cbbc..3dd8fd95a60 100644 --- a/filament/backend/src/vulkan/VulkanCommands.cpp +++ b/filament/backend/src/vulkan/VulkanCommands.cpp @@ -110,14 +110,13 @@ bool VulkanGroupMarkers::empty() const noexcept { #endif // FVK_DEBUG_GROUP_MARKERS -VulkanCommandBuffer::VulkanCommandBuffer(VulkanContext* context, VulkanResourceAllocator* allocator, - VkDevice device, VkQueue queue, VkCommandPool pool, bool isProtected) +VulkanCommandBuffer::VulkanCommandBuffer(VulkanContext* context, VkDevice device, VkQueue queue, + VkCommandPool pool, bool isProtected) : mContext(context), mMarkerCount(0), isProtected(isProtected), mDevice(device), mQueue(queue), - mResourceManager(allocator), mBuffer(createCommandBuffer(device, pool)), mFenceStatus(std::make_shared(VK_INCOMPLETE)) { VkSemaphoreCreateInfo sci{.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO}; @@ -134,7 +133,7 @@ VulkanCommandBuffer::~VulkanCommandBuffer() { void VulkanCommandBuffer::reset() noexcept { mMarkerCount = 0; - mResourceManager.clear(); + mResources.clear(); mWaitSemaphores.clear(); // Internally we use the VK_INCOMPLETE status to mean "not yet submitted". When this fence @@ -257,8 +256,8 @@ VkSemaphore VulkanCommandBuffer::submit() { return mSubmission; } -CommandBufferPool::CommandBufferPool(VulkanContext* context, VulkanResourceAllocator* allocator, - VkDevice device, VkQueue queue, uint8_t queueFamilyIndex, bool isProtected) +CommandBufferPool::CommandBufferPool(VulkanContext* context, VkDevice device, VkQueue queue, + uint8_t queueFamilyIndex, bool isProtected) : mDevice(device), mRecording(INVALID) { VkCommandPoolCreateInfo createInfo = { @@ -271,8 +270,8 @@ CommandBufferPool::CommandBufferPool(VulkanContext* context, VulkanResourceAlloc vkCreateCommandPool(device, &createInfo, VKALLOC, &mPool); for (size_t i = 0; i < CAPACITY; ++i) { - mBuffers.emplace_back(std::make_unique(context, allocator, device, - queue, mPool, isProtected)); + mBuffers.emplace_back( + std::make_unique(context, device, queue, mPool, isProtected)); } } @@ -370,16 +369,12 @@ void CommandBufferPool::insertEvent(char const* marker) { } VulkanCommands::VulkanCommands(VkDevice device, VkQueue queue, uint32_t queueFamilyIndex, - VkQueue protectedQueue, uint32_t protectedQueueFamilyIndex, VulkanContext* context, - VulkanResourceAllocator* allocator) + VkQueue protectedQueue, uint32_t protectedQueueFamilyIndex, VulkanContext* context) : mDevice(device), mProtectedQueue(protectedQueue), mProtectedQueueFamilyIndex(protectedQueueFamilyIndex), - mAllocator(allocator), mContext(context), - mPool(std::make_unique(context, allocator, device, queue, queueFamilyIndex, - false)) { -} + mPool(std::make_unique(context, device, queue, queueFamilyIndex, false)) {} void VulkanCommands::terminate() { mPool.reset(); @@ -395,14 +390,19 @@ VulkanCommandBuffer& VulkanCommands::getProtected() { assert_invariant(mProtectedQueue != VK_NULL_HANDLE); if (!mProtectedPool) { - mProtectedPool = std::make_unique(mContext, mAllocator, mDevice, - mProtectedQueue, mProtectedQueueFamilyIndex, true); + mProtectedPool = std::make_unique(mContext, mDevice, mProtectedQueue, + mProtectedQueueFamilyIndex, true); } auto& ret = mProtectedPool->getRecording(); return ret; } bool VulkanCommands::flush() { + // It's possible to call flush and wait at "terminate", in which case, we'll just return. + if (!mPool && !mProtectedPool) { + return false; + } + VkSemaphore dependency = mInjectedDependency; VkSemaphore lastSubmit = mLastSubmit; bool hasFlushed = false; @@ -434,6 +434,11 @@ bool VulkanCommands::flush() { } void VulkanCommands::wait() { + // It's possible to call flush and wait at "terminate", in which case, we'll just return. + if (!mPool && !mProtectedPool) { + return; + } + FVK_SYSTRACE_CONTEXT(); FVK_SYSTRACE_START("commands::wait"); diff --git a/filament/backend/src/vulkan/VulkanCommands.h b/filament/backend/src/vulkan/VulkanCommands.h index 25b839ec49e..e7354fbe6bd 100644 --- a/filament/backend/src/vulkan/VulkanCommands.h +++ b/filament/backend/src/vulkan/VulkanCommands.h @@ -23,8 +23,8 @@ #include "VulkanAsyncHandles.h" #include "VulkanConstants.h" -#include "VulkanResources.h" #include "VulkanUtility.h" +#include "vulkan/memory/ResourcePointer.h" #include #include @@ -39,6 +39,8 @@ namespace filament::backend { +using namespace fvkmemory; + struct VulkanContext; #if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS) @@ -65,7 +67,7 @@ class VulkanGroupMarkers { // DriverApi fence object and should not be destroyed until both the DriverApi object is freed and // we're done waiting on the most recent submission of the given command buffer. struct VulkanCommandBuffer { - VulkanCommandBuffer(VulkanContext* mContext, VulkanResourceAllocator* allocator, + VulkanCommandBuffer(VulkanContext* mContext, VkDevice device, VkQueue queue, VkCommandPool pool, bool isProtected); VulkanCommandBuffer(VulkanCommandBuffer const&) = delete; @@ -73,13 +75,10 @@ struct VulkanCommandBuffer { ~VulkanCommandBuffer(); - inline void acquire(VulkanResource* resource) { - mResourceManager.acquire(resource); + inline void acquire(fvkmemory::resource_ptr resource) { + mResources.push_back(resource); } - inline void acquire(VulkanAcquireOnlyResourceManager* srcResources) { - mResourceManager.acquireAll(srcResources); - } void reset() noexcept; inline void insertWait(VkSemaphore sem) { @@ -119,21 +118,20 @@ struct VulkanCommandBuffer { bool const isProtected; VkDevice mDevice; VkQueue mQueue; - VulkanAcquireOnlyResourceManager mResourceManager; CappedArray mWaitSemaphores; VkCommandBuffer mBuffer; VkSemaphore mSubmission; VkFence mFence; std::shared_ptr mFenceStatus; - + std::vector> mResources; }; struct CommandBufferPool { using ActiveBuffers = utils::bitset32; static constexpr int8_t INVALID = -1; - CommandBufferPool(VulkanContext* context, VulkanResourceAllocator* allocator, VkDevice device, - VkQueue queue, uint8_t queueFamilyIndex, bool isProtected); + CommandBufferPool(VulkanContext* context, VkDevice device, VkQueue queue, + uint8_t queueFamilyIndex, bool isProtected); ~CommandBufferPool(); VulkanCommandBuffer& getRecording(); @@ -189,8 +187,7 @@ struct CommandBufferPool { class VulkanCommands { public: VulkanCommands(VkDevice device, VkQueue queue, uint32_t queueFamilyIndex, - VkQueue protectedQueue, uint32_t protectedQueueFamilyIndex, VulkanContext* context, - VulkanResourceAllocator* allocator); + VkQueue protectedQueue, uint32_t protectedQueueFamilyIndex, VulkanContext* context); void terminate(); @@ -241,7 +238,6 @@ class VulkanCommands { VkQueue const mProtectedQueue; // For defered initialization if/when we need protected content uint32_t const mProtectedQueueFamilyIndex; - VulkanResourceAllocator* mAllocator; VulkanContext* mContext; std::unique_ptr mPool; diff --git a/filament/backend/src/vulkan/VulkanConstants.h b/filament/backend/src/vulkan/VulkanConstants.h index c291a0c4f13..79b388a7136 100644 --- a/filament/backend/src/vulkan/VulkanConstants.h +++ b/filament/backend/src/vulkan/VulkanConstants.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2021 The Android Open Source Project * -* Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * @@ -63,7 +63,7 @@ #define FVK_DEBUG_SHADER_MODULE 0x00000800 #define FVK_DEBUG_READ_PIXELS 0x00001000 #define FVK_DEBUG_PIPELINE_CACHE 0x00002000 -#define FVK_DEBUG_ALLOCATION 0x00004000 +#define FVK_DEBUG_STAGING_ALLOCATION 0x00004000 // Enable the debug utils extension if it is available. #define FVK_DEBUG_DEBUG_UTILS 0x00008000 diff --git a/filament/backend/src/vulkan/VulkanContext.cpp b/filament/backend/src/vulkan/VulkanContext.cpp index 576fff38e17..7c11a47551f 100644 --- a/filament/backend/src/vulkan/VulkanContext.cpp +++ b/filament/backend/src/vulkan/VulkanContext.cpp @@ -25,15 +25,11 @@ #include #include -#include #include // for std::max using namespace bluevk; -using utils::FixedCapacityVector; - - namespace { } // end anonymous namespace @@ -113,7 +109,7 @@ void VulkanTimestamps::clearQuery(uint32_t queryIndex) { } void VulkanTimestamps::beginQuery(VulkanCommandBuffer const* commands, - VulkanTimerQuery* query) { + fvkmemory::resource_ptr query) { uint32_t const index = query->getStartingQueryIndex(); auto const cmdbuffer = commands->buffer(); @@ -125,19 +121,20 @@ void VulkanTimestamps::beginQuery(VulkanCommandBuffer const* commands, } void VulkanTimestamps::endQuery(VulkanCommandBuffer const* commands, - VulkanTimerQuery const* query) { + fvkmemory::resource_ptr query) { uint32_t const index = query->getStoppingQueryIndex(); vkCmdWriteTimestamp(commands->buffer(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, mPool, index); } -VulkanTimestamps::QueryResult VulkanTimestamps::getResult(VulkanTimerQuery const* query) { +VulkanTimestamps::QueryResult VulkanTimestamps::getResult( + fvkmemory::resource_ptr query) { uint32_t const index = query->getStartingQueryIndex(); QueryResult result; size_t const dataSize = result.size() * sizeof(uint64_t); VkDeviceSize const stride = sizeof(uint64_t) * 2; VkResult vkresult = - vkGetQueryPoolResults(mDevice, mPool, index, 2, dataSize, (void*) result.data(), - stride, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT); + vkGetQueryPoolResults(mDevice, mPool, index, 2, dataSize, (void*) result.data(), stride, + VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT); FILAMENT_CHECK_POSTCONDITION(vkresult == VK_SUCCESS || vkresult == VK_NOT_READY) << "vkGetQueryPoolResults error: " << static_cast(vkresult); if (vkresult == VK_NOT_READY) { diff --git a/filament/backend/src/vulkan/VulkanContext.h b/filament/backend/src/vulkan/VulkanContext.h index 68c44dfdcee..0a55adc440a 100644 --- a/filament/backend/src/vulkan/VulkanContext.h +++ b/filament/backend/src/vulkan/VulkanContext.h @@ -21,6 +21,8 @@ #include "VulkanImageUtility.h" #include "VulkanUtility.h" +#include "vulkan/memory/ResourcePointer.h" + #include #include #include @@ -41,10 +43,10 @@ struct VulkanTimerQuery; struct VulkanCommandBuffer; struct VulkanAttachment { - VulkanTexture* texture = nullptr; + fvkmemory::resource_ptr texture; uint8_t level = 0; uint8_t layerCount = 1; - uint16_t layer = 0; + uint8_t layer = 0; bool isDepth() const; VkImage getImage() const; @@ -70,9 +72,11 @@ class VulkanTimestamps { std::tuple getNextQuery(); void clearQuery(uint32_t queryIndex); - void beginQuery(VulkanCommandBuffer const* commands, VulkanTimerQuery* query); - void endQuery(VulkanCommandBuffer const* commands, VulkanTimerQuery const* query); - QueryResult getResult(VulkanTimerQuery const* query); + void beginQuery(VulkanCommandBuffer const* commands, + fvkmemory::resource_ptr query); + void endQuery(VulkanCommandBuffer const* commands, + fvkmemory::resource_ptr query); + QueryResult getResult(fvkmemory::resource_ptr query); private: VkDevice mDevice; @@ -82,7 +86,7 @@ class VulkanTimestamps { }; struct VulkanRenderPass { - VulkanRenderTarget* renderTarget; + fvkmemory::resource_ptr renderTarget; VkRenderPass renderPass; RenderPassParams params; int currentSubpass; diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index bb72633af65..b03f98352b5 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -26,6 +26,8 @@ #include "VulkanHandles.h" #include "VulkanMemory.h" #include "VulkanTexture.h" +#include "memory/ResourceManager.h" +#include "memory/ResourcePointer.h" #include @@ -194,23 +196,21 @@ Dispatcher VulkanDriver::getDispatcher() const noexcept { VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& context, Platform::DriverConfig const& driverConfig) noexcept : mPlatform(platform), + mResourceManager(driverConfig.handleArenaSize, driverConfig.disableHandleUseAfterFreeCheck), mAllocator(createAllocator(mPlatform->getInstance(), mPlatform->getPhysicalDevice(), mPlatform->getDevice())), mContext(context), - mResourceAllocator(driverConfig.handleArenaSize, driverConfig.disableHandleUseAfterFreeCheck), - mResourceManager(&mResourceAllocator), - mThreadSafeResourceManager(&mResourceAllocator), mCommands(mPlatform->getDevice(), mPlatform->getGraphicsQueue(), mPlatform->getGraphicsQueueFamilyIndex(), - nullptr, 0, &mContext, &mResourceAllocator), - mPipelineLayoutCache(mPlatform->getDevice(), &mResourceAllocator), + nullptr, 0, &mContext), + mPipelineLayoutCache(mPlatform->getDevice()), mPipelineCache(mPlatform->getDevice(), mAllocator), mStagePool(mAllocator, &mCommands), mFramebufferCache(mPlatform->getDevice()), mSamplerCache(mPlatform->getDevice()), mBlitter(mPlatform->getPhysicalDevice(), &mCommands), mReadPixels(mPlatform->getDevice()), - mDescriptorSetManager(mPlatform->getDevice(), &mResourceAllocator), + mDescriptorSetManager(mPlatform->getDevice(), &mResourceManager), mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported), mStereoscopicType(driverConfig.stereoscopicType) { @@ -300,11 +300,10 @@ void VulkanDriver::terminate() { // to those commands are no longer referenced. finish(0); - // Command buffers should come first since it might have commands depending on resources that - // are about to be destroyed. - mCommands.terminate(); + mCurrentSwapChain = {}; + mDefaultRenderTarget = {}; + mBoundPipeline = {}; - mResourceManager.clear(); mTimestamps.reset(); mBlitter.terminate(); @@ -313,6 +312,8 @@ void VulkanDriver::terminate() { // Allow the stage pool to clean up. mStagePool.gc(); + mCommands.terminate(); + mStagePool.terminate(); mPipelineCache.terminate(); mFramebufferCache.reset(); @@ -320,8 +321,11 @@ void VulkanDriver::terminate() { mDescriptorSetManager.terminate(); mPipelineLayoutCache.terminate(); + // Before terminating ResourceManager, we must make sure all of the resource_ptrs have been unset. + mResourceManager.terminate(); + #if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK) - mResourceAllocator.print(); + mResourceManager.print(); #endif vmaDestroyAllocator(mAllocator); @@ -348,15 +352,17 @@ void VulkanDriver::tick(int) { // been destroyed for safe destruction, due to outstanding command buffers and triple buffering. void VulkanDriver::collectGarbage() { FVK_SYSTRACE_SCOPE(); - // Command buffers need to be submitted and completed before other resources can be gc'd. And - // its gc() function carrys out the *wait*. + // Command buffers need to be submitted and completed before other resources can be gc'd. mCommands.gc(); + mDescriptorSetManager.clearHistory(); mStagePool.gc(); mFramebufferCache.gc(); mPipelineCache.gc(); + mResourceManager.gc(); + #if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK) - mResourceAllocator.print(); + mResourceManager.print(); #endif } void VulkanDriver::beginFrame(int64_t monotonic_clock_ns, @@ -388,13 +394,10 @@ void VulkanDriver::updateDescriptorSetBuffer( backend::BufferObjectHandle boh, uint32_t offset, uint32_t size) { - FVK_SYSTRACE_CONTEXT(); - FVK_SYSTRACE_START("updateDescriptorSetBuffer"); - - VulkanDescriptorSet* set = mResourceAllocator.handle_cast(dsh); - VulkanBufferObject* obj = mResourceAllocator.handle_cast(boh); - mDescriptorSetManager.updateBuffer(set, binding, obj, offset, size); - FVK_SYSTRACE_END(); + FVK_SYSTRACE_SCOPE(); + auto set = resource_ptr::cast(&mResourceManager, dsh); + auto buffer = resource_ptr::cast(&mResourceManager, boh); + mDescriptorSetManager.updateBuffer(set, binding, buffer, offset, size); } void VulkanDriver::updateDescriptorSetTexture( @@ -402,13 +405,12 @@ void VulkanDriver::updateDescriptorSetTexture( backend::descriptor_binding_t binding, backend::TextureHandle th, SamplerParams params) { - FVK_SYSTRACE_CONTEXT(); - FVK_SYSTRACE_START("updateDescriptorSetTexture"); - VulkanDescriptorSet* set = mResourceAllocator.handle_cast(dsh); - VulkanTexture* texture = mResourceAllocator.handle_cast(th); + FVK_SYSTRACE_SCOPE(); + auto set = resource_ptr::cast(&mResourceManager, dsh); + auto texture = resource_ptr::cast(&mResourceManager, th); + VkSampler const vksampler = mSamplerCache.getSampler(params); mDescriptorSetManager.updateSampler(set, binding, texture, vksampler); - FVK_SYSTRACE_END(); } void VulkanDriver::flush(int) { @@ -428,129 +430,117 @@ void VulkanDriver::finish(int dummy) { void VulkanDriver::createRenderPrimitiveR(Handle rph, Handle vbh, Handle ibh, PrimitiveType pt) { - auto rp = mResourceAllocator.construct(rph, - &mResourceAllocator, pt, vbh, ibh); - mResourceManager.acquire(rp); + auto vb = resource_ptr::cast(&mResourceManager, vbh); + auto ib = resource_ptr::cast(&mResourceManager, ibh); + auto ptr = resource_ptr::make(&mResourceManager, rph, pt, vb, ib); + ptr.inc(); } void VulkanDriver::destroyRenderPrimitive(Handle rph) { if (!rph) { return; } - auto rp = mResourceAllocator.handle_cast(rph); - mResourceManager.release(rp); + auto ptr = resource_ptr::cast(&mResourceManager, rph); + ptr.dec(); } void VulkanDriver::createVertexBufferInfoR(Handle vbih, uint8_t bufferCount, uint8_t attributeCount, AttributeArray attributes) { - auto vbi = mResourceAllocator.construct(vbih, - bufferCount, attributeCount, attributes); - mResourceManager.acquire(vbi); + auto vbi = resource_ptr::make(&mResourceManager, vbih, bufferCount, + attributeCount, attributes); + vbi.inc(); } void VulkanDriver::destroyVertexBufferInfo(Handle vbih) { if (!vbih) { return; } - auto vbi = mResourceAllocator.handle_cast(vbih); - mResourceManager.release(vbi); + auto vbi = resource_ptr::cast(&mResourceManager, vbih); + vbi.dec(); } - -void VulkanDriver::createVertexBufferR(Handle vbh, - uint32_t vertexCount, Handle vbih) { - auto vertexBuffer = mResourceAllocator.construct(vbh, - mContext, mStagePool, &mResourceAllocator, vertexCount, vbih); - mResourceManager.acquire(vertexBuffer); +void VulkanDriver::createVertexBufferR(Handle vbh, uint32_t vertexCount, + Handle vbih) { + auto vbi = resource_ptr::cast(&mResourceManager, vbih); + auto vb = resource_ptr::make(&mResourceManager, vbh, mContext, mStagePool, + vertexCount, vbi); + vb.inc(); } void VulkanDriver::destroyVertexBuffer(Handle vbh) { if (!vbh) { return; } - auto vertexBuffer = mResourceAllocator.handle_cast(vbh); - mResourceManager.release(vertexBuffer); + auto vb = resource_ptr::cast(&mResourceManager, vbh); + vb.dec(); } void VulkanDriver::createIndexBufferR(Handle ibh, ElementType elementType, uint32_t indexCount, BufferUsage usage) { auto elementSize = (uint8_t) getElementTypeSize(elementType); - auto indexBuffer = mResourceAllocator.construct(ibh, mAllocator, mStagePool, + auto ib = resource_ptr::make(&mResourceManager, ibh, mAllocator, mStagePool, elementSize, indexCount); - mResourceManager.acquire(indexBuffer); + ib.inc(); } void VulkanDriver::destroyIndexBuffer(Handle ibh) { if (!ibh) { return; } - auto indexBuffer = mResourceAllocator.handle_cast(ibh); - mResourceManager.release(indexBuffer); + auto ib = resource_ptr::cast(&mResourceManager, ibh); + ib.dec(); } void VulkanDriver::createBufferObjectR(Handle boh, uint32_t byteCount, BufferObjectBinding bindingType, BufferUsage usage) { - auto bufferObject = mResourceAllocator.construct(boh, mAllocator, - mStagePool, byteCount, bindingType); - mResourceManager.acquire(bufferObject); + auto bo = resource_ptr::make(&mResourceManager, boh, mAllocator, mStagePool, + byteCount, bindingType); + bo.inc(); } void VulkanDriver::destroyBufferObject(Handle boh) { if (!boh) { return; } - auto bufferObject = mResourceAllocator.handle_cast(boh); - mResourceManager.release(bufferObject); + auto bo = resource_ptr::cast(&mResourceManager, boh); + bo.dec(); } void VulkanDriver::createTextureR(Handle th, SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth, TextureUsage usage) { - FVK_SYSTRACE_CONTEXT(); - FVK_SYSTRACE_START("createTexture"); + FVK_SYSTRACE_SCOPE(); + auto texture = resource_ptr::make(&mResourceManager, th, mPlatform->getDevice(), + mPlatform->getPhysicalDevice(), mContext, mAllocator, &mResourceManager, &mCommands, + target, levels, format, samples, w, h, depth, usage, mStagePool); - auto vktexture = mResourceAllocator.construct(th, mPlatform->getDevice(), - mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, &mResourceAllocator, - target, levels, - format, samples, w, h, depth, usage, mStagePool); - mResourceManager.acquire(vktexture); + // Do transition to default layout. + VulkanCommandBuffer& commandsBuf = mCommands.get(); + auto const& primaryViewRange = texture->getPrimaryViewRange(); + auto const defaultLayout = texture->getDefaultLayout(); + texture->transitionLayout(&commandsBuf, primaryViewRange, defaultLayout); - FVK_SYSTRACE_END(); + texture.inc(); } -//void VulkanDriver::createTextureSwizzledR(Handle th, SamplerType target, uint8_t levels, -// TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth, -// TextureUsage usage, -// TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) { -// TextureSwizzle swizzleArray[] = {r, g, b, a}; -// const VkComponentMapping swizzleMap = getSwizzleMap(swizzleArray); -// auto vktexture = mResourceAllocator.construct(th, mPlatform->getDevice(), -// mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, &mResourceAllocator, -// target, levels, format, samples, w, h, depth, usage, mStagePool, -// false /*heap allocated */, swizzleMap); -// mResourceManager.acquire(vktexture); -//} - void VulkanDriver::createTextureViewR(Handle th, Handle srch, uint8_t baseLevel, uint8_t levelCount) { - VulkanTexture const* src = mResourceAllocator.handle_cast(srch); - auto vktexture = mResourceAllocator.construct(th, mPlatform->getDevice(), - mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, &mResourceAllocator, - src, baseLevel, levelCount); - mResourceManager.acquire(vktexture); + auto src = resource_ptr::cast(&mResourceManager, srch); + auto texture = resource_ptr::make(&mResourceManager, th, mPlatform->getDevice(), + mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, baseLevel, + levelCount); + texture.inc(); } void VulkanDriver::createTextureViewSwizzleR(Handle th, Handle srch, backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b, backend::TextureSwizzle a) { - TextureSwizzle const swizzleArray[] = {r, g, b, a}; - VkComponentMapping const swizzle = getSwizzleMap(swizzleArray); - - VulkanTexture const* src = mResourceAllocator.handle_cast(srch); - auto vktexture = mResourceAllocator.construct(th, mPlatform->getDevice(), - mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, &mResourceAllocator, - src, swizzle); - mResourceManager.acquire(vktexture); + TextureSwizzle const swizzleArray[] = {r, g, b, a}; + VkComponentMapping const swizzle = getSwizzleMap(swizzleArray); + auto src = resource_ptr::cast(&mResourceManager, srch); + auto texture = resource_ptr::make(&mResourceManager, th, mPlatform->getDevice(), + mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, swizzle); + texture.inc(); } void VulkanDriver::createTextureExternalImageR(Handle th, backend::TextureFormat format, @@ -573,39 +563,36 @@ void VulkanDriver::destroyTexture(Handle th) { if (!th) { return; } - auto texture = mResourceAllocator.handle_cast(th); - mResourceManager.release(texture); + auto texture = resource_ptr::cast(&mResourceManager, th); + texture.dec(); } void VulkanDriver::createProgramR(Handle ph, Program&& program) { - FVK_SYSTRACE_CONTEXT(); - FVK_SYSTRACE_START("createProgram"); - auto vkprogram - = mResourceAllocator.construct(ph, mPlatform->getDevice(), program); - mResourceManager.acquire(vkprogram); - FVK_SYSTRACE_END(); + FVK_SYSTRACE_SCOPE(); + auto vprogram = resource_ptr::make(&mResourceManager, ph, mPlatform->getDevice(), + program); + vprogram.inc(); } void VulkanDriver::destroyProgram(Handle ph) { if (!ph) { return; } - auto vkprogram = mResourceAllocator.handle_cast(ph); - mResourceManager.release(vkprogram); + auto vprogram = resource_ptr::cast(&mResourceManager, ph); + vprogram.dec(); } void VulkanDriver::createDefaultRenderTargetR(Handle rth, int) { - assert_invariant(mDefaultRenderTarget == nullptr); - VulkanRenderTarget* renderTarget = mResourceAllocator.construct(rth); + assert_invariant(!mDefaultRenderTarget); + auto renderTarget = resource_ptr::make(&mResourceManager, rth); mDefaultRenderTarget = renderTarget; - mResourceManager.acquire(renderTarget); } void VulkanDriver::createRenderTargetR(Handle rth, TargetBufferFlags targets, uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, MRT color, TargetBufferInfo depth, TargetBufferInfo stencil) { - FVK_SYSTRACE_CONTEXT(); - FVK_SYSTRACE_START("createRenderTarget"); + + FVK_SYSTRACE_SCOPE(); UTILS_UNUSED_IN_RELEASE math::vec2 tmin = {std::numeric_limits::max()}; UTILS_UNUSED_IN_RELEASE math::vec2 tmax = {0}; @@ -615,10 +602,10 @@ void VulkanDriver::createRenderTargetR(Handle rth, for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) { if (color[i].handle) { colorTargets[i] = { - .texture = mResourceAllocator.handle_cast(color[i].handle), + .texture = resource_ptr::cast(&mResourceManager, color[i].handle), .level = color[i].level, .layerCount = layerCount, - .layer = color[i].layer, + .layer = (uint8_t) color[i].layer, }; UTILS_UNUSED_IN_RELEASE VkExtent2D extent = colorTargets[i].getExtent2D(); tmin = { std::min(tmin.x, extent.width), std::min(tmin.y, extent.height) }; @@ -630,10 +617,10 @@ void VulkanDriver::createRenderTargetR(Handle rth, VulkanAttachment depthStencil[2] = {}; if (depth.handle) { depthStencil[0] = { - .texture = mResourceAllocator.handle_cast(depth.handle), + .texture = resource_ptr::cast(&mResourceManager, depth.handle), .level = depth.level, .layerCount = layerCount, - .layer = depth.layer, + .layer = (uint8_t) depth.layer, }; UTILS_UNUSED_IN_RELEASE VkExtent2D extent = depthStencil[0].getExtent2D(); tmin = { std::min(tmin.x, extent.width), std::min(tmin.y, extent.height) }; @@ -643,10 +630,10 @@ void VulkanDriver::createRenderTargetR(Handle rth, if (stencil.handle) { depthStencil[1] = { - .texture = mResourceAllocator.handle_cast(stencil.handle), + .texture = resource_ptr::cast(&mResourceManager, stencil.handle), .level = stencil.level, .layerCount = layerCount, - .layer = stencil.layer, + .layer = (uint8_t) stencil.layer, }; UTILS_UNUSED_IN_RELEASE VkExtent2D extent = depthStencil[1].getExtent2D(); tmin = { std::min(tmin.x, extent.width), std::min(tmin.y, extent.height) }; @@ -660,13 +647,10 @@ void VulkanDriver::createRenderTargetR(Handle rth, assert_invariant(tmin == tmax); assert_invariant(tmin.x >= width && tmin.y >= height); - auto renderTarget = mResourceAllocator.construct(rth, - mPlatform->getDevice(), mPlatform->getPhysicalDevice(), mContext, mAllocator, - &mCommands, &mResourceAllocator, width, height, samples, colorTargets, depthStencil, - mStagePool, layerCount); - mResourceManager.acquire(renderTarget); - - FVK_SYSTRACE_END(); + auto rt = resource_ptr::make(&mResourceManager, rth, mPlatform->getDevice(), + mPlatform->getPhysicalDevice(), mContext, &mResourceManager, mAllocator, &mCommands, + width, height, samples, colorTargets, depthStencil, mStagePool, layerCount); + rt.inc(); } void VulkanDriver::destroyRenderTarget(Handle rth) { @@ -674,16 +658,21 @@ void VulkanDriver::destroyRenderTarget(Handle rth) { return; } - VulkanRenderTarget* rt = mResourceAllocator.handle_cast(rth); + auto rt = resource_ptr::cast(&mResourceManager, rth); if (UTILS_UNLIKELY(rt == mDefaultRenderTarget)) { - mDefaultRenderTarget = nullptr; + mDefaultRenderTarget = {}; + } else { + rt.dec(); } - mResourceManager.release(rt); } void VulkanDriver::createFenceR(Handle fh, int) { - VulkanCommandBuffer* cmdbuf = &mCommands.get(); - mResourceAllocator.construct(fh, cmdbuf->getFenceStatus()); + VulkanCommandBuffer const& commandBuffer = mCommands.get(); + // Note at this point, the fence has already been constructed via createFenceS, so we just tag + // it with appropriate VulkanCmdFence, which is associated with the current, recording command + // buffer. + auto fence = resource_ptr::cast(&mResourceManager, fh); + fence->fence = commandBuffer.getFenceStatus(); } void VulkanDriver::createSwapChainR(Handle sch, void* nativeWindow, uint64_t flags) { @@ -692,9 +681,9 @@ void VulkanDriver::createSwapChainR(Handle sch, void* nativeWindow, << utils::io::endl; flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE); } - auto swapChain = mResourceAllocator.construct(sch, mPlatform, mContext, - mAllocator, &mCommands, &mResourceAllocator, mStagePool, nativeWindow, flags); - mResourceManager.acquire(swapChain); + auto swapChain = resource_ptr::make(&mResourceManager, sch, mPlatform, + mContext, &mResourceManager, mAllocator, &mCommands, mStagePool, nativeWindow, flags); + swapChain.inc(); } void VulkanDriver::createSwapChainHeadlessR(Handle sch, uint32_t width, @@ -705,10 +694,10 @@ void VulkanDriver::createSwapChainHeadlessR(Handle sch, uint32_t wi flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE); } assert_invariant(width > 0 && height > 0 && "Vulkan requires non-zero swap chain dimensions."); - auto swapChain = mResourceAllocator.construct(sch, mPlatform, mContext, - mAllocator, &mCommands, &mResourceAllocator, mStagePool, - nullptr, flags, VkExtent2D{width, height}); - mResourceManager.acquire(swapChain); + auto swapChain = resource_ptr::make(&mResourceManager, sch, mPlatform, + mContext, &mResourceManager, mAllocator, &mCommands, mStagePool, nullptr, flags, + VkExtent2D{width, height}); + swapChain.inc(); } void VulkanDriver::createTimerQueryR(Handle tqh, int) { @@ -717,123 +706,117 @@ void VulkanDriver::createTimerQueryR(Handle tqh, int) { void VulkanDriver::createDescriptorSetLayoutR(Handle dslh, backend::DescriptorSetLayout&& info) { - VulkanDescriptorSetLayout* layout = mResourceAllocator.construct( - dslh, info); - - // This will create a VkDescriptorSetLayout (which is cached) for this object. + auto layout = resource_ptr::make(&mResourceManager, dslh, info); mDescriptorSetManager.initVkLayout(layout); - mResourceManager.acquire(layout); + layout.inc(); } void VulkanDriver::createDescriptorSetR(Handle dsh, Handle dslh) { - FVK_SYSTRACE_CONTEXT(); - FVK_SYSTRACE_START("createDescriptorSet"); - - auto layout = mResourceAllocator.handle_cast(dslh); - mDescriptorSetManager.createSet(dsh, layout); - - auto set = mResourceAllocator.handle_cast(dsh); - mResourceManager.acquire(set); - - FVK_SYSTRACE_END(); + FVK_SYSTRACE_SCOPE(); + fvkmemory::resource_ptr layout = + fvkmemory::resource_ptr::cast(&mResourceManager, dslh); + auto set = mDescriptorSetManager.createSet(dsh, layout); + set.inc(); } Handle VulkanDriver::createVertexBufferInfoS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createVertexBufferS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createIndexBufferS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createBufferObjectS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createTextureS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createTextureViewS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createTextureViewSwizzleS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createTextureExternalImageS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createTextureExternalImagePlaneS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::importTextureS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createRenderPrimitiveS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createProgramS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createDefaultRenderTargetS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createRenderTargetS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createFenceS() noexcept { - return mResourceAllocator.initHandle(); + auto handle = mResourceManager.allocHandle(); + auto fence = resource_ptr::make(&mResourceManager, handle); + fence.inc(); + return handle; } Handle VulkanDriver::createSwapChainS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createSwapChainHeadlessS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createTimerQueryS() noexcept { // The handle must be constructed here, as a synchronous call to getTimerQueryValue might happen // before createTimerQueryR is executed. - Handle tqh - = mResourceAllocator.initHandle(mTimestamps->getNextQuery()); - auto query = mResourceAllocator.handle_cast(tqh); - mThreadSafeResourceManager.acquire(query); - return tqh; + auto query = resource_ptr::construct(&mResourceManager, + mTimestamps->getNextQuery()); + query.inc(); + return Handle(query.id()); } Handle VulkanDriver::createDescriptorSetLayoutS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } Handle VulkanDriver::createDescriptorSetS() noexcept { - return mResourceAllocator.allocHandle(); + return mResourceManager.allocHandle(); } void VulkanDriver::destroySwapChain(Handle sch) { if (!sch) { return; } - VulkanSwapChain* swapChain = mResourceAllocator.handle_cast(sch); + auto swapChain = resource_ptr::cast(&mResourceManager, sch); if (mCurrentSwapChain == swapChain) { - mCurrentSwapChain = nullptr; + mCurrentSwapChain = {}; } - mResourceManager.release(swapChain); + swapChain.dec(); } void VulkanDriver::destroyStream(Handle sh) { @@ -843,19 +826,18 @@ void VulkanDriver::destroyTimerQuery(Handle tqh) { if (!tqh) { return; } - auto vtq = mResourceAllocator.handle_cast(tqh); - mThreadSafeResourceManager.release(vtq); + auto vtq = resource_ptr::cast(&mResourceManager, tqh); + vtq.dec(); } void VulkanDriver::destroyDescriptorSetLayout(Handle dslh) { - VulkanDescriptorSetLayout* layout = mResourceAllocator.handle_cast(dslh); - mResourceManager.release(layout); + auto layout = resource_ptr::cast(&mResourceManager, dslh); + layout.dec(); } void VulkanDriver::destroyDescriptorSet(Handle dsh) { - mDescriptorSetManager.destroySet(dsh); - VulkanDescriptorSet* set = mResourceAllocator.handle_cast(dsh); - mResourceManager.release(set); + auto set = resource_ptr::cast(&mResourceManager, dsh); + set.dec(); } Handle VulkanDriver::createStreamNative(void* nativeStream) { @@ -881,11 +863,14 @@ void VulkanDriver::updateStreams(CommandStream* driver) { } void VulkanDriver::destroyFence(Handle fh) { - mResourceAllocator.destruct(fh); + auto fence = resource_ptr::cast(&mResourceManager, fh); + fence.dec(); } FenceStatus VulkanDriver::getFenceStatus(Handle fh) { - auto& cmdfence = mResourceAllocator.handle_cast(fh)->fence; + auto fence = resource_ptr::cast(&mResourceManager, fh); + + auto& cmdfence = fence->fence; if (!cmdfence) { // If wait is called before a fence actually exists, we return timeout. This matches the // current behavior in OpenGLDriver, but we should eventually reconsider a different error @@ -899,10 +884,11 @@ FenceStatus VulkanDriver::getFenceStatus(Handle fh) { return FenceStatus::CONDITION_SATISFIED; } + // Two other states are possible: - // - VK_INCOMPLETE: the corresponding buffer has not yet been submitted. - // - VK_NOT_READY: the buffer has been submitted but not yet signaled. - // In either case, we return TIMEOUT_EXPIRED to indicate the fence has not been signaled. + // - VK_INCOMPLETE: the corresponding buffer has not yet been submitted. + // - VK_NOT_READY: the buffer has been submitted but not yet signaled. + // In either case, we return TIMEOUT_EXPIRED to indicate the fence has not been signaled. return FenceStatus::TIMEOUT_EXPIRED; } @@ -1088,16 +1074,16 @@ size_t VulkanDriver::getMaxUniformBufferSize() { void VulkanDriver::setVertexBufferObject(Handle vbh, uint32_t index, Handle boh) { - auto vb = mResourceAllocator.handle_cast(vbh); - auto bo = mResourceAllocator.handle_cast(boh); + auto vb = resource_ptr::cast(&mResourceManager, vbh); + auto bo = resource_ptr::cast(&mResourceManager, boh); assert_invariant(bo->bindingType == BufferObjectBinding::VERTEX); - vb->setBuffer(mResourceAllocator, bo, index); + vb->setBuffer(bo, index); } void VulkanDriver::updateIndexBuffer(Handle ibh, BufferDescriptor&& p, uint32_t byteOffset) { VulkanCommandBuffer& commands = mCommands.get(); - auto ib = mResourceAllocator.handle_cast(ibh); + auto ib = resource_ptr::cast(&mResourceManager, ibh); commands.acquire(ib); ib->buffer.loadFromCpu(commands.buffer(), p.buffer, byteOffset, p.size); @@ -1108,7 +1094,7 @@ void VulkanDriver::updateBufferObject(Handle boh, BufferDescript uint32_t byteOffset) { VulkanCommandBuffer& commands = mCommands.get(); - auto bo = mResourceAllocator.handle_cast(boh); + auto bo = resource_ptr::cast(&mResourceManager, boh); commands.acquire(bo); bo->buffer.loadFromCpu(commands.buffer(), bd.buffer, byteOffset, bd.size); @@ -1118,11 +1104,10 @@ void VulkanDriver::updateBufferObject(Handle boh, BufferDescript void VulkanDriver::updateBufferObjectUnsynchronized(Handle boh, BufferDescriptor&& bd, uint32_t byteOffset) { VulkanCommandBuffer& commands = mCommands.get(); - auto bo = mResourceAllocator.handle_cast(boh); + auto bo = resource_ptr::cast(&mResourceManager, boh); commands.acquire(bo); // TODO: implement unsynchronized version bo->buffer.loadFromCpu(commands.buffer(), bd.buffer, byteOffset, bd.size); - mResourceManager.acquire(bo); scheduleDestroy(std::move(bd)); } @@ -1138,8 +1123,8 @@ void VulkanDriver::resetBufferObject(Handle boh) { void VulkanDriver::update3DImage(Handle th, uint32_t level, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t width, uint32_t height, uint32_t depth, PixelBufferDescriptor&& data) { - mResourceAllocator.handle_cast(th)->updateImage(data, width, height, depth, - xoffset, yoffset, zoffset, level); + auto texture = resource_ptr::cast(&mResourceManager, th); + texture->updateImage(data, width, height, depth, xoffset, yoffset, zoffset, level); scheduleDestroy(std::move(data)); } @@ -1147,7 +1132,7 @@ void VulkanDriver::setupExternalImage(void* image) { } TimerQueryResult VulkanDriver::getTimerQueryValue(Handle tqh, uint64_t* elapsedTime) { - VulkanTimerQuery* vtq = mResourceAllocator.handle_cast(tqh); + auto vtq = resource_ptr::cast(&mResourceManager, tqh); if (!vtq->isCompleted()) { return TimerQueryResult::NOT_READY; } @@ -1185,7 +1170,7 @@ void VulkanDriver::setExternalStream(Handle th, Handle sh) } void VulkanDriver::generateMipmaps(Handle th) { - auto* const t = mResourceAllocator.handle_cast(th); + auto t = resource_ptr::cast(&mResourceManager, th); assert_invariant(t); int32_t layerCount = int32_t(t->depth); @@ -1194,9 +1179,10 @@ void VulkanDriver::generateMipmaps(Handle th) { layerCount *= 6; } + assert_invariant(layerCount < 1 << (sizeof(VulkanAttachment::layerCount) * 8)); + // FIXME: the loop below can perform many layout transitions and back. We should be // able to optimize that. - uint8_t level = 0; int32_t srcw = int32_t(t->width); int32_t srch = int32_t(t->height); @@ -1208,12 +1194,18 @@ void VulkanDriver::generateMipmaps(Handle th) { // TODO: there should be a way to do this using layerCount in vkBlitImage // TODO: vkBlitImage should be able to handle 3D textures too - for (int32_t layer = 0; layer < layerCount; layer++) { - mBlitter.blit(VK_FILTER_LINEAR, - { .texture = t, .level = uint8_t(level + 1), .layer = (uint16_t)layer }, - dstOffsets, - { .texture = t, .level = uint8_t(level ), .layer = (uint16_t)layer }, - srcOffsets); + for (uint8_t layer = 0; layer < layerCount; layer++) { + VulkanAttachment dst { + .level = uint8_t(level + 1), + .layer = layer, + }; + dst.texture = t; + VulkanAttachment src { + .level = uint8_t(level), + .layer = layer, + }; + src.texture = t; + mBlitter.blit(VK_FILTER_LINEAR, dst, dstOffsets, src, srcOffsets); } level++; @@ -1232,8 +1224,9 @@ void VulkanDriver::compilePrograms(CompilerPriorityQueue priority, void VulkanDriver::beginRenderPass(Handle rth, const RenderPassParams& params) { FVK_SYSTRACE_SCOPE(); - VulkanRenderTarget* const rt = mResourceAllocator.handle_cast(rth); - VkExtent2D const& extent = rt->getExtent(); + auto rt = resource_ptr::cast(&mResourceManager, rth); + VkExtent2D const extent = rt->getExtent(); + assert_invariant(rt == mDefaultRenderTarget || extent.width > 0 && extent.height > 0); // Filament has the expectation that the contents of the swap chain are not preserved on the @@ -1241,7 +1234,7 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP // passes, due to multiple views. TargetBufferFlags discardStart = params.flags.discardStart; if (rt->isSwapChain()) { - VulkanSwapChain* sc = mCurrentSwapChain; + fvkmemory::resource_ptr sc = mCurrentSwapChain; assert_invariant(sc); if (sc->isFirstRenderPass()) { discardStart |= TargetBufferFlags::COLOR; @@ -1281,6 +1274,7 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP // Create the VkRenderPass or fetch it from cache. + VulkanFboCache::RenderPassKey rpkey = rt->getRenderPassKey(); rpkey.clear = clearVal; rpkey.discardStart = discardStart; @@ -1383,7 +1377,7 @@ void VulkanDriver::endRenderPass(int) { VkCommandBuffer cmdbuffer = commands.buffer(); vkCmdEndRenderPass(cmdbuffer); - VulkanRenderTarget* rt = mCurrentRenderPass.renderTarget; + auto rt = mCurrentRenderPass.renderTarget; assert_invariant(rt); // Since we might soon be sampling from the render target that we just wrote to, we need a @@ -1391,7 +1385,7 @@ void VulkanDriver::endRenderPass(int) { rt->emitBarriersEndRenderPass(commands); mRenderPassFboInfo = {}; - mCurrentRenderPass.renderTarget = nullptr; + mCurrentRenderPass.renderTarget = {}; mCurrentRenderPass.renderPass = VK_NULL_HANDLE; } @@ -1399,7 +1393,7 @@ void VulkanDriver::nextSubpass(int) { FILAMENT_CHECK_PRECONDITION(mCurrentRenderPass.currentSubpass == 0) << "Only two subpasses are currently supported."; - VulkanRenderTarget* renderTarget = mCurrentRenderPass.renderTarget; + auto renderTarget = mCurrentRenderPass.renderTarget; assert_invariant(renderTarget); assert_invariant(mCurrentRenderPass.params.subpassMask); @@ -1409,7 +1403,7 @@ void VulkanDriver::nextSubpass(int) { ++mCurrentRenderPass.currentSubpass); if (mCurrentRenderPass.params.subpassMask & 0x1) { - VulkanAttachment subpassInput = renderTarget->getColor0(); + VulkanAttachment& subpassInput = renderTarget->getColor0(); mDescriptorSetManager.updateInputAttachment({}, subpassInput); } } @@ -1419,8 +1413,10 @@ void VulkanDriver::makeCurrent(Handle drawSch, Handle ASSERT_PRECONDITION_NON_FATAL(drawSch == readSch, "Vulkan driver does not support distinct draw/read swap chains."); - VulkanSwapChain* swapChain = mCurrentSwapChain - = mResourceAllocator.handle_cast(drawSch); + + resource_ptr swapChain = + resource_ptr::cast(&mResourceManager, drawSch); + mCurrentSwapChain = swapChain; bool resized = false; swapChain->acquire(resized); @@ -1430,14 +1426,14 @@ void VulkanDriver::makeCurrent(Handle drawSch, Handle } if (UTILS_LIKELY(mDefaultRenderTarget)) { - mDefaultRenderTarget->bindToSwapChain(*swapChain); + mDefaultRenderTarget->bindToSwapChain(swapChain); } } void VulkanDriver::commit(Handle sch) { FVK_SYSTRACE_SCOPE(); - VulkanSwapChain* swapChain = mResourceAllocator.handle_cast(sch); + auto swapChain = resource_ptr::cast(&mResourceManager, sch); // Present the backbuffer after the most recent command buffer submission has finished. swapChain->present(); @@ -1480,7 +1476,7 @@ void VulkanDriver::stopCapture(int) {} void VulkanDriver::readPixels(Handle src, uint32_t x, uint32_t y, uint32_t width, uint32_t height, PixelBufferDescriptor&& pbd) { - VulkanRenderTarget* srcTarget = mResourceAllocator.handle_cast(src); + auto srcTarget = resource_ptr::cast(&mResourceManager, src); mCommands.flush(); mReadPixels.run( srcTarget, x, y, width, height, mPlatform->getGraphicsQueueFamilyIndex(), @@ -1507,8 +1503,9 @@ void VulkanDriver::resolve( FILAMENT_CHECK_PRECONDITION(mCurrentRenderPass.renderPass == VK_NULL_HANDLE) << "resolve() cannot be invoked inside a render pass."; - auto* const srcTexture = mResourceAllocator.handle_cast(src); - auto* const dstTexture = mResourceAllocator.handle_cast(dst); + auto srcTexture = resource_ptr::cast(&mResourceManager, src); + auto dstTexture = resource_ptr::cast(&mResourceManager, dst); + assert_invariant(srcTexture); assert_invariant(dstTexture); @@ -1549,8 +1546,8 @@ void VulkanDriver::blit( FILAMENT_CHECK_PRECONDITION(mCurrentRenderPass.renderPass == VK_NULL_HANDLE) << "blit() cannot be invoked inside a render pass."; - auto* const srcTexture = mResourceAllocator.handle_cast(src); - auto* const dstTexture = mResourceAllocator.handle_cast(dst); + auto srcTexture = resource_ptr::cast(&mResourceManager, src); + auto dstTexture = resource_ptr::cast(&mResourceManager, dst); FILAMENT_CHECK_PRECONDITION(any(dstTexture->usage & TextureUsage::BLIT_DST)) << "texture doesn't have BLIT_DST"; @@ -1598,8 +1595,8 @@ void VulkanDriver::blitDEPRECATED(TargetBufferFlags buffers, srcRect.left >= 0 && srcRect.bottom >= 0 && dstRect.left >= 0 && dstRect.bottom >= 0) << "Source and destination rects must be positive."; - VulkanRenderTarget* dstTarget = mResourceAllocator.handle_cast(dst); - VulkanRenderTarget* srcTarget = mResourceAllocator.handle_cast(src); + auto dstTarget = resource_ptr::cast(&mResourceManager, dst); + auto srcTarget = resource_ptr::cast(&mResourceManager, src); VkFilter const vkfilter = (filter == SamplerMagFilter::NEAREST) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; @@ -1629,18 +1626,18 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) { FVK_SYSTRACE_SCOPE(); VulkanCommandBuffer* commands = &mCommands.get(); - const VulkanVertexBufferInfo& vbi = - *mResourceAllocator.handle_cast(pipelineState.vertexBufferInfo); + auto vbi = resource_ptr::cast(&mResourceManager, + pipelineState.vertexBufferInfo); Handle programHandle = pipelineState.program; RasterState const& rasterState = pipelineState.rasterState; PolygonOffset const& depthOffset = pipelineState.polygonOffset; - auto* program = mResourceAllocator.handle_cast(programHandle); + auto program = resource_ptr::cast(&mResourceManager, programHandle); commands->acquire(program); // Update the VK raster state. - const VulkanRenderTarget* rt = mCurrentRenderPass.renderTarget; + auto rt = mCurrentRenderPass.renderTarget; VulkanPipelineCache::RasterState const vulkanRasterState{ .cullMode = getCullMode(rasterState.culling), @@ -1669,14 +1666,14 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) { VulkanPipelineCache::getPrimitiveTopology(pipelineState.primitiveType); // Declare fixed-size arrays that get passed to the pipeCache and to vkCmdBindVertexBuffers. - VkVertexInputAttributeDescription const* attribDesc = vbi.getAttribDescriptions(); - VkVertexInputBindingDescription const* bufferDesc = vbi.getBufferDescriptions(); + VkVertexInputAttributeDescription const* attribDesc = vbi->getAttribDescriptions(); + VkVertexInputBindingDescription const* bufferDesc = vbi->getBufferDescriptions(); // Push state changes to the VulkanPipelineCache instance. This is fast and does not make VK calls. mPipelineCache.bindProgram(program); mPipelineCache.bindRasterState(vulkanRasterState); mPipelineCache.bindPrimitiveTopology(topology); - mPipelineCache.bindVertexArray(attribDesc, bufferDesc, vbi.getAttributeCount()); + mPipelineCache.bindVertexArray(attribDesc, bufferDesc, vbi->getAttributeCount()); auto& setLayouts = pipelineState.pipelineLayout.setLayout; VulkanDescriptorSetLayout::DescriptorSetLayoutArray layoutList; @@ -1686,7 +1683,8 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) { if (!handle) { return VK_NULL_HANDLE; } - auto layout = mResourceAllocator.handle_cast(handle); + auto layout = + resource_ptr::cast(&mResourceManager, handle); layoutCount++; return layout->getVkLayout(); }); @@ -1709,25 +1707,23 @@ void VulkanDriver::bindRenderPrimitive(Handle rph) { VulkanCommandBuffer* commands = &mCommands.get(); VkCommandBuffer cmdbuffer = commands->buffer(); - const VulkanRenderPrimitive& prim = *mResourceAllocator.handle_cast(rph); - commands->acquire(prim.indexBuffer); - commands->acquire(prim.vertexBuffer); + auto prim = resource_ptr::cast(&mResourceManager, rph); + commands->acquire(prim); // This *must* match the VulkanVertexBufferInfo that was bound in bindPipeline(). But we want // to allow to call this before bindPipeline(), so the validation can only happen in draw() - VulkanVertexBufferInfo const* const vbi = - mResourceAllocator.handle_cast(prim.vertexBuffer->vbih); + auto vbi = prim->vertexBuffer->vbi; uint32_t const bufferCount = vbi->getAttributeCount(); VkDeviceSize const* offsets = vbi->getOffsets(); - VkBuffer const* buffers = prim.vertexBuffer->getVkBuffers(); + VkBuffer const* buffers = prim->vertexBuffer->getVkBuffers(); // Next bind the vertex buffers and index buffer. One potential performance improvement is to // avoid rebinding these if they are already bound, but since we do not (yet) support subranges // it would be rare for a client to make consecutive draw calls with the same render primitive. vkCmdBindVertexBuffers(cmdbuffer, 0, bufferCount, buffers, offsets); - vkCmdBindIndexBuffer(cmdbuffer, prim.indexBuffer->buffer.getGpuBuffer(), 0, - prim.indexBuffer->indexType); + vkCmdBindIndexBuffer(cmdbuffer, prim->indexBuffer->buffer.getGpuBuffer(), 0, + prim->indexBuffer->indexType); } void VulkanDriver::bindDescriptorSet( @@ -1735,7 +1731,7 @@ void VulkanDriver::bindDescriptorSet( backend::descriptor_set_t setIndex, backend::DescriptorSetOffsetArray&& offsets) { if (dsh) { - VulkanDescriptorSet* set = mResourceAllocator.handle_cast(dsh); + auto set = resource_ptr::cast(&mResourceManager, dsh); mDescriptorSetManager.bind(setIndex, set, std::move(offsets)); } else { mDescriptorSetManager.unbind(setIndex); @@ -1761,9 +1757,9 @@ void VulkanDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t ins void VulkanDriver::draw(PipelineState state, Handle rph, uint32_t const indexOffset, uint32_t const indexCount, uint32_t const instanceCount) { - VulkanRenderPrimitive* const rp = mResourceAllocator.handle_cast(rph); + auto rp = resource_ptr::cast(&mResourceManager, rph); state.primitiveType = rp->type; - state.vertexBufferInfo = rp->vertexBuffer->vbih; + state.vertexBufferInfo = Handle(rp->vertexBuffer->vbi.id()); bindPipeline(state); bindRenderPrimitive(rph); draw2(indexOffset, indexCount, instanceCount); @@ -1798,19 +1794,19 @@ void VulkanDriver::scissor(Viewport scissorBox) { .extent = { uint32_t(r - l), uint32_t(t - b) } }; - VulkanRenderTarget const* rt = mCurrentRenderPass.renderTarget; + auto rt = mCurrentRenderPass.renderTarget; rt->transformClientRectToPlatform(&scissor); vkCmdSetScissor(cmdbuffer, 0, 1, &scissor); } void VulkanDriver::beginTimerQuery(Handle tqh) { - VulkanTimerQuery* vtq = mResourceAllocator.handle_cast(tqh); + auto vtq = resource_ptr::cast(&mResourceManager, tqh); mTimestamps->beginQuery(&(mCommands.get()), vtq); } void VulkanDriver::endTimerQuery(Handle tqh) { - VulkanTimerQuery* vtq = mResourceAllocator.handle_cast(tqh); - mTimestamps->endQuery(&(mCommands.get()), vtq); + auto vtq = resource_ptr::cast(&mResourceManager, tqh); + mTimestamps->endQuery(&(mCommands.get()), vtq); } void VulkanDriver::debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept { @@ -1842,7 +1838,7 @@ void VulkanDriver::resetState(int) { } void VulkanDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) { - mResourceAllocator.associateHandle(handleId, std::move(tag)); + mResourceManager.associateHandle(handleId, std::move(tag)); } // explicit instantiation of the Dispatcher diff --git a/filament/backend/src/vulkan/VulkanDriver.h b/filament/backend/src/vulkan/VulkanDriver.h index 7dd95209342..e304b8df4a6 100644 --- a/filament/backend/src/vulkan/VulkanDriver.h +++ b/filament/backend/src/vulkan/VulkanDriver.h @@ -24,13 +24,14 @@ #include "VulkanHandles.h" #include "VulkanPipelineCache.h" #include "VulkanReadPixels.h" -#include "VulkanResourceAllocator.h" #include "VulkanSamplerCache.h" #include "VulkanStagePool.h" #include "VulkanUtility.h" #include "backend/DriverEnums.h" #include "caching/VulkanDescriptorSetManager.h" #include "caching/VulkanPipelineLayoutCache.h" +#include "memory/ResourceManager.h" +#include "memory/ResourcePointer.h" #include "DriverBase.h" #include "private/backend/Driver.h" @@ -77,6 +78,9 @@ class VulkanDriver final : public DriverBase { #endif // FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS) private: + template + using resource_ptr = fvkmemory::resource_ptr; + static constexpr uint8_t MAX_SAMPLER_BINDING_COUNT = Program::SAMPLER_BINDING_COUNT; void debugCommandBegin(CommandStream* cmds, bool synchronous, @@ -113,21 +117,16 @@ class VulkanDriver final : public DriverBase { void collectGarbage(); VulkanPlatform* mPlatform = nullptr; + fvkmemory::ResourceManager mResourceManager; std::unique_ptr mTimestamps; - VulkanSwapChain* mCurrentSwapChain = nullptr; - VulkanRenderTarget* mDefaultRenderTarget = nullptr; + resource_ptr mCurrentSwapChain; + resource_ptr mDefaultRenderTarget; VulkanRenderPass mCurrentRenderPass = {}; VmaAllocator mAllocator = VK_NULL_HANDLE; VkDebugReportCallbackEXT mDebugCallback = VK_NULL_HANDLE; VulkanContext mContext = {}; - VulkanResourceAllocator mResourceAllocator; - VulkanResourceManager mResourceManager; - - // Used for resources that are created synchronously and used and destroyed on the backend - // thread. - VulkanThreadSafeResourceManager mThreadSafeResourceManager; VulkanCommands mCommands; VulkanPipelineLayoutCache mPipelineLayoutCache; @@ -142,7 +141,7 @@ class VulkanDriver final : public DriverBase { // This is necessary for us to write to push constants after binding a pipeline. struct { - VulkanProgram* program; + resource_ptr program; VkPipelineLayout pipelineLayout; DescriptorSetMask descriptorSetMask; } mBoundPipeline = {}; diff --git a/filament/backend/src/vulkan/VulkanHandles.cpp b/filament/backend/src/vulkan/VulkanHandles.cpp index 9fda018943b..61e50ffd705 100644 --- a/filament/backend/src/vulkan/VulkanHandles.cpp +++ b/filament/backend/src/vulkan/VulkanHandles.cpp @@ -22,8 +22,8 @@ #include "VulkanDriver.h" #include "VulkanMemory.h" -#include "VulkanResourceAllocator.h" #include "VulkanUtility.h" +#include "vulkan/memory/ResourcePointer.h" #include "spirv/VulkanSpirvUtils.h" #include @@ -105,9 +105,10 @@ BitmaskGroup fromBackendLayout(DescriptorSetLayout const& layout) { return mask; } -VulkanTexture* initMsaaTexture(VulkanTexture* texture, VkDevice device, +fvkmemory::resource_ptr initMsaaTexture( + fvkmemory::resource_ptr texture, VkDevice device, VkPhysicalDevice physicalDevice, VulkanContext const& context, VmaAllocator allocator, - VulkanCommands* commands, VulkanResourceAllocator* handleAllocator, uint8_t levels, + VulkanCommands* commands, fvkmemory::ResourceManager* resManager, uint8_t levels, uint8_t samples, VulkanStagePool& stagePool) { assert_invariant(texture); auto msTexture = texture->getSidecar(); @@ -117,10 +118,9 @@ VulkanTexture* initMsaaTexture(VulkanTexture* texture, VkDevice device, const TextureUsage usage = texture->usage & TextureUsage::ALL_ATTACHMENTS; assert_invariant(static_cast(usage) != 0U); - msTexture = new VulkanTexture(device, physicalDevice, context, allocator, commands, - handleAllocator, texture->target, levels, - texture->format, samples, texture->width, texture->height, texture->depth, usage, - stagePool, true /* heap allocated */); + msTexture = resource_ptr::construct(resManager, device, physicalDevice, + context, allocator, resManager, commands, texture->target, levels, texture->format, + samples, texture->width, texture->height, texture->depth, usage, stagePool); texture->setSidecar(msTexture); } return msTexture; @@ -128,19 +128,18 @@ VulkanTexture* initMsaaTexture(VulkanTexture* texture, VkDevice device, } // anonymous namespace -VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(DescriptorSetLayout const& layout) - : VulkanResource(VulkanResourceType::DESCRIPTOR_SET_LAYOUT), - bitmask(fromBackendLayout(layout)), - count(Count::fromLayoutBitmask(bitmask)) {} - -void VulkanDescriptorSet::acquire(VulkanTexture* texture) { - mResources.acquire(texture); +void VulkanDescriptorSet::acquire(fvkmemory::resource_ptr texture) { + mResources.push_back(texture); } -void VulkanDescriptorSet::acquire(VulkanBufferObject* bufferObject) { - mResources.acquire(bufferObject); +void VulkanDescriptorSet::acquire(fvkmemory::resource_ptr obj) { + mResources.push_back(obj); } +VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(DescriptorSetLayout const& layout) + : bitmask(fromBackendLayout(layout)), + count(Count::fromLayoutBitmask(bitmask)) {} + PushConstantDescription::PushConstantDescription(backend::Program const& program) noexcept { mRangeCount = 0; for (auto stage : { ShaderStage::VERTEX, ShaderStage::FRAGMENT, ShaderStage::COMPUTE }) { @@ -188,7 +187,6 @@ void PushConstantDescription::write(VulkanCommands* commands, VkPipelineLayout l VulkanProgram::VulkanProgram(VkDevice device, Program const& builder) noexcept : HwProgram(builder.getName()), - VulkanResource(VulkanResourceType::PROGRAM), mInfo(new(std::nothrow) PipelineInfo(builder)), mDevice(device) { @@ -256,23 +254,24 @@ VulkanProgram::~VulkanProgram() { // Creates a special "default" render target (i.e. associated with the swap chain) VulkanRenderTarget::VulkanRenderTarget() : HwRenderTarget(0, 0), - VulkanResource(VulkanResourceType::RENDER_TARGET), mOffscreen(false), mProtected(false), - mResources(nullptr), mInfo(std::make_unique()) { mInfo->rpkey.samples = mInfo->fbkey.samples = 1; } -void VulkanRenderTarget::bindToSwapChain(VulkanSwapChain& swapChain) { +VulkanRenderTarget::~VulkanRenderTarget() = default; + +void VulkanRenderTarget::bindToSwapChain(fvkmemory::resource_ptr swapchain) { assert_invariant(!mOffscreen); - VkExtent2D const extent = swapChain.getExtent(); + VkExtent2D const extent = swapchain->getExtent(); width = extent.width; height = extent.height; - mProtected = swapChain.isProtected(); + mProtected = swapchain->isProtected(); - VulkanAttachment color = {.texture = swapChain.getCurrentColor()}; + VulkanAttachment color = {}; + color.texture = swapchain->getCurrentColor(); mInfo->attachments = {color}; auto& fbkey = mInfo->fbkey; @@ -284,33 +283,30 @@ void VulkanRenderTarget::bindToSwapChain(VulkanSwapChain& swapChain) { fbkey.color[0] = color.getImageView(); fbkey.resolve[0] = VK_NULL_HANDLE; - VulkanAttachment depth = {}; - rpkey.depthFormat = depth.getFormat(); - fbkey.depth = VK_NULL_HANDLE; - - if (swapChain.getDepth()) { - depth = {.texture = swapChain.getDepth()}; + if (swapchain->getDepth()) { + VulkanAttachment depth = {}; + depth.texture = swapchain->getDepth(); mInfo->attachments.push_back(depth); mInfo->depthIndex = 1; rpkey.depthFormat = depth.getFormat(); fbkey.depth = depth.getImageView(); + } else { + rpkey.depthFormat = VK_FORMAT_UNDEFINED; + fbkey.depth = VK_NULL_HANDLE; } mInfo->colors.set(0); } VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physicalDevice, - VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, uint32_t width, uint32_t height, uint8_t samples, - VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT], + VulkanContext const& context, fvkmemory::ResourceManager* resourceManager, + VmaAllocator allocator, VulkanCommands* commands, uint32_t width, uint32_t height, + uint8_t samples, VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT], VulkanAttachment depthStencil[2], VulkanStagePool& stagePool, uint8_t layerCount) : HwRenderTarget(width, height), - VulkanResource(VulkanResourceType::RENDER_TARGET), mOffscreen(true), mProtected(false), - mResources(handleAllocator), mInfo(std::make_unique()) { - auto& depth = depthStencil[0]; // Constrain the sample count according to both kinds of sample count masks obtained from @@ -347,14 +343,11 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica fbkey.color[index] = attachment.getImageView(); fbkey.resolve[index] = VK_NULL_HANDLE; - mResources.acquire(attachment.texture); - if (samples > 1) { VulkanAttachment msaaAttachment = {}; if (texture->samples == 1) { auto msaaTexture = initMsaaTexture(texture, device, physicalDevice, context, - allocator, commands, handleAllocator, - ((VulkanTexture const*) texture)->levels, samples, stagePool); + allocator, commands, resourceManager, texture->levels, samples, stagePool); if (msaaTexture && msaaTexture->isTransientAttachment()) { rpkey.usesLazilyAllocatedMemory |= (1 << index); } @@ -375,7 +368,6 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica } fbkey.color[index] = msaaAttachment.getImageView(); msaa.push_back(msaaAttachment); - mResources.acquire(msaaAttachment.texture); } } @@ -388,19 +380,18 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica auto depthTexture = depth.texture; mInfo->depthIndex = (uint8_t) attachments.size(); attachments.push_back(depth); - mResources.acquire(depthTexture); fbkey.depth = depth.getImageView(); if (samples > 1) { mInfo->msaaDepthIndex = mInfo->depthIndex; if (depthTexture->samples == 1) { // MSAA depth texture must have the mipmap count of 1 uint8_t const msLevel = 1; - // Create sidecar MSAA texture for the depth attachment if it does not already exist. - auto msaa = initMsaaTexture(depthTexture, device, physicalDevice, context, allocator, - commands, handleAllocator, msLevel, samples, stagePool); + // Create sidecar MSAA texture for the depth attachment if it does not already + // exist. + auto msaa = initMsaaTexture(depthTexture, device, physicalDevice, context, + allocator, commands, resourceManager, msLevel, samples, stagePool); mInfo->msaaDepthIndex = (uint8_t) attachments.size(); attachments.push_back({ .texture = msaa, .layerCount = layerCount }); - mResources.acquire(msaa); } } } @@ -491,9 +482,7 @@ void VulkanRenderTarget::emitBarriersEndRenderPass(VulkanCommandBuffer& commands VulkanVertexBufferInfo::VulkanVertexBufferInfo( uint8_t bufferCount, uint8_t attributeCount, AttributeArray const& attributes) : HwVertexBufferInfo(bufferCount, attributeCount), - VulkanResource(VulkanResourceType::VERTEX_BUFFER_INFO), mInfo(attributes.size()) { - auto attribDesc = mInfo.mSoa.data(); auto bufferDesc = mInfo.mSoa.data(); auto offsets = mInfo.mSoa.data(); @@ -531,19 +520,15 @@ VulkanVertexBufferInfo::VulkanVertexBufferInfo( } VulkanVertexBuffer::VulkanVertexBuffer(VulkanContext& context, VulkanStagePool& stagePool, - VulkanResourceAllocator* allocator, - uint32_t vertexCount, Handle vbih) + uint32_t vertexCount, fvkmemory::resource_ptr vbi) : HwVertexBuffer(vertexCount), - VulkanResource(VulkanResourceType::VERTEX_BUFFER), - vbih(vbih), - mBuffers(MAX_VERTEX_BUFFER_COUNT), // TODO: can we do better here? - mResources(allocator) { + vbi(vbi), + // TODO: Seems a bit wasteful. can we do better here? + mBuffers(MAX_VERTEX_BUFFER_COUNT) { } -void VulkanVertexBuffer::setBuffer(VulkanResourceAllocator const& allocator, - VulkanBufferObject* bufferObject, uint32_t index) { - VulkanVertexBufferInfo const* const vbi = - const_cast(allocator).handle_cast(vbih); +void VulkanVertexBuffer::setBuffer(fvkmemory::resource_ptr bufferObject, + uint32_t index) { size_t const count = vbi->getAttributeCount(); VkBuffer* const vkbuffers = getVkBuffers(); int8_t const* const attribToBuffer = vbi->getAttributeToBuffer(); @@ -552,25 +537,20 @@ void VulkanVertexBuffer::setBuffer(VulkanResourceAllocator const& allocator, vkbuffers[attribIndex] = bufferObject->buffer.getGpuBuffer(); } } - mResources.acquire(bufferObject); + mResources.push_back(bufferObject); } VulkanBufferObject::VulkanBufferObject(VmaAllocator allocator, VulkanStagePool& stagePool, uint32_t byteCount, BufferObjectBinding bindingType) : HwBufferObject(byteCount), - VulkanResource(VulkanResourceType::BUFFER_OBJECT), buffer(allocator, stagePool, getBufferObjectUsage(bindingType), byteCount), bindingType(bindingType) {} -VulkanRenderPrimitive::VulkanRenderPrimitive(VulkanResourceAllocator* resourceAllocator, - PrimitiveType pt, Handle vbh, Handle ibh) - : VulkanResource(VulkanResourceType::RENDER_PRIMITIVE), - mResources(resourceAllocator) { - type = pt; - vertexBuffer = resourceAllocator->handle_cast(vbh); - indexBuffer = resourceAllocator->handle_cast(ibh); - mResources.acquire(vertexBuffer); - mResources.acquire(indexBuffer); -} +VulkanRenderPrimitive::VulkanRenderPrimitive(PrimitiveType pt, + fvkmemory::resource_ptr vb, + fvkmemory::resource_ptr ib) + : HwRenderPrimitive{.type = pt}, + vertexBuffer(vb), + indexBuffer(ib) {} } // namespace filament::backend diff --git a/filament/backend/src/vulkan/VulkanHandles.h b/filament/backend/src/vulkan/VulkanHandles.h index 1dc3141fd5a..1e3c854a62f 100644 --- a/filament/backend/src/vulkan/VulkanHandles.h +++ b/filament/backend/src/vulkan/VulkanHandles.h @@ -20,14 +20,14 @@ // This needs to be at the top #include "DriverBase.h" +#include "VulkanAsyncHandles.h" #include "VulkanBuffer.h" #include "VulkanFboCache.h" -#include "VulkanResources.h" #include "VulkanSwapChain.h" #include "VulkanTexture.h" #include "VulkanUtility.h" +#include "vulkan/memory/Resource.h" -#include #include #include @@ -35,6 +35,8 @@ #include #include +#include + namespace filament::backend { namespace { @@ -55,7 +57,7 @@ inline uint8_t collapsedCount(Bitmask const& mask) { class VulkanTimestamps; struct VulkanBufferObject; -struct VulkanDescriptorSetLayout : public VulkanResource, HwDescriptorSetLayout { +struct VulkanDescriptorSetLayout : public HwDescriptorSetLayout, fvkmemory::Resource { static constexpr uint8_t UNIQUE_DESCRIPTOR_SET_COUNT = 4; static constexpr uint8_t MAX_BINDINGS = 25; @@ -129,21 +131,19 @@ struct VulkanDescriptorSetLayout : public VulkanResource, HwDescriptorSetLayout VkDescriptorSetLayout mVkLayout = VK_NULL_HANDLE; }; -struct VulkanDescriptorSet : public VulkanResource, HwDescriptorSet { +struct VulkanDescriptorSet : public HwDescriptorSet, fvkmemory::Resource { public: // Because we need to recycle descriptor sets not used, we allow for a callback that the "Pool" // can use to repackage the vk handle. using OnRecycle = std::function; - VulkanDescriptorSet(VulkanResourceAllocator* allocator, VkDescriptorSet rawSet, + VulkanDescriptorSet(VkDescriptorSet rawSet, UniformBufferBitmask const& dynamicUboMask, uint8_t uniqueDynamicUboCount, OnRecycle&& onRecycleFn) - : VulkanResource(VulkanResourceType::DESCRIPTOR_SET), - vkSet(rawSet), + : vkSet(rawSet), dynamicUboMask(dynamicUboMask), uniqueDynamicUboCount(uniqueDynamicUboCount), - mResources(allocator), mOnRecycleFn(std::move(onRecycleFn)) {} ~VulkanDescriptorSet() { @@ -160,9 +160,8 @@ struct VulkanDescriptorSet : public VulkanResource, HwDescriptorSet { return &mOffsets; } - void acquire(VulkanTexture* texture); - - void acquire(VulkanBufferObject* texture); + void acquire(fvkmemory::resource_ptr texture); + void acquire(fvkmemory::resource_ptr buffer); VkDescriptorSet const vkSet; UniformBufferBitmask const dynamicUboMask; @@ -170,7 +169,7 @@ struct VulkanDescriptorSet : public VulkanResource, HwDescriptorSet { private: backend::DescriptorSetOffsetArray mOffsets; - VulkanAcquireOnlyResourceManager mResources; + std::vector> mResources; OnRecycle mOnRecycleFn; }; @@ -178,13 +177,10 @@ using PushConstantNameArray = utils::FixedCapacityVector; using PushConstantNameByStage = std::array; struct PushConstantDescription { - explicit PushConstantDescription(backend::Program const& program) noexcept; VkPushConstantRange const* getVkRanges() const noexcept { return mRanges; } - uint32_t getVkRangeCount() const noexcept { return mRangeCount; } - void write(VulkanCommands* commands, VkPipelineLayout layout, backend::ShaderStage stage, uint8_t index, backend::PushConstantVariant const& value); @@ -196,12 +192,10 @@ struct PushConstantDescription { uint32_t mRangeCount; }; -struct VulkanProgram : public HwProgram, VulkanResource { - +struct VulkanProgram : public HwProgram, fvkmemory::Resource { using BindingList = CappedArray; VulkanProgram(VkDevice device, Program const& builder) noexcept; - ~VulkanProgram(); inline VkShaderModule getVertexShader() const { @@ -255,16 +249,16 @@ struct VulkanProgram : public HwProgram, VulkanResource { // // We use private inheritance to shield clients from the width / height fields in HwRenderTarget, // which are not representative when this is the default render target. -struct VulkanRenderTarget : private HwRenderTarget, VulkanResource { +struct VulkanRenderTarget : private HwRenderTarget, fvkmemory::Resource { // Creates an offscreen render target. VulkanRenderTarget(VkDevice device, VkPhysicalDevice physicalDevice, - VulkanContext const& context, VmaAllocator allocator, - VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, - uint32_t width, uint32_t height, + VulkanContext const& context, fvkmemory::ResourceManager* resourceManager, + VmaAllocator allocator, VulkanCommands* commands, uint32_t width, uint32_t height, uint8_t samples, VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT], VulkanAttachment depthStencil[2], VulkanStagePool& stagePool, uint8_t layerCount); + ~VulkanRenderTarget(); + // Creates a special "default" render target (i.e. associated with the swap chain) explicit VulkanRenderTarget(); @@ -276,12 +270,12 @@ struct VulkanRenderTarget : private HwRenderTarget, VulkanResource { return {width, height}; } - inline VulkanAttachment const& getColor0() const { + inline VulkanAttachment& getColor0() const { assert_invariant(mInfo->colors[0]); return mInfo->attachments[0]; } - inline VulkanAttachment const& getDepth() const { + inline VulkanAttachment& getDepth() const { assert_invariant(hasDepth()); if (mInfo->fbkey.samples == 1) { return mInfo->attachments[mInfo->depthIndex]; @@ -308,7 +302,7 @@ struct VulkanRenderTarget : private HwRenderTarget, VulkanResource { inline bool isSwapChain() const { return !mOffscreen; } inline bool isProtected() const { return mProtected; } - void bindToSwapChain(VulkanSwapChain& surf); + void bindToSwapChain(fvkmemory::resource_ptr swapchain); void emitBarriersBeginRenderPass(VulkanCommandBuffer& commands); @@ -331,13 +325,12 @@ struct VulkanRenderTarget : private HwRenderTarget, VulkanResource { bool const mOffscreen; bool mProtected; - VulkanAcquireOnlyResourceManager mResources; std::unique_ptr mInfo; }; struct VulkanBufferObject; -struct VulkanVertexBufferInfo : public HwVertexBufferInfo, VulkanResource { +struct VulkanVertexBufferInfo : public HwVertexBufferInfo, fvkmemory::Resource { VulkanVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount, AttributeArray const& attributes); @@ -384,33 +377,24 @@ struct VulkanVertexBufferInfo : public HwVertexBufferInfo, VulkanResource { PipelineInfo mInfo; }; -struct VulkanVertexBuffer : public HwVertexBuffer, VulkanResource { - VulkanVertexBuffer(VulkanContext& context, VulkanStagePool& stagePool, - VulkanResourceAllocator* allocator, - uint32_t vertexCount, Handle vbih); - - void setBuffer(VulkanResourceAllocator const& allocator, - VulkanBufferObject* bufferObject, uint32_t index); +struct VulkanVertexBuffer : public HwVertexBuffer, fvkmemory::Resource { + VulkanVertexBuffer(VulkanContext& context, VulkanStagePool& stagePool, uint32_t vertexCount, + fvkmemory::resource_ptr vbi); + void setBuffer(fvkmemory::resource_ptr bufferObject, uint32_t index); - inline VkBuffer const* getVkBuffers() const { - return mBuffers.data(); - } - - inline VkBuffer* getVkBuffers() { - return mBuffers.data(); - } + inline VkBuffer const* getVkBuffers() const { return mBuffers.data(); } + inline VkBuffer* getVkBuffers() { return mBuffers.data(); } + fvkmemory::resource_ptr vbi; - Handle vbih; private: utils::FixedCapacityVector mBuffers; - FixedSizeVulkanResourceManager mResources; + std::vector> mResources; }; -struct VulkanIndexBuffer : public HwIndexBuffer, VulkanResource { +struct VulkanIndexBuffer : public HwIndexBuffer, fvkmemory::Resource { VulkanIndexBuffer(VmaAllocator allocator, VulkanStagePool& stagePool, uint8_t elementSize, uint32_t indexCount) : HwIndexBuffer(elementSize, indexCount), - VulkanResource(VulkanResourceType::INDEX_BUFFER), buffer(allocator, stagePool, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, elementSize * indexCount), indexType(elementSize == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32) {} @@ -418,7 +402,7 @@ struct VulkanIndexBuffer : public HwIndexBuffer, VulkanResource { const VkIndexType indexType; }; -struct VulkanBufferObject : public HwBufferObject, VulkanResource { +struct VulkanBufferObject : public HwBufferObject, fvkmemory::Resource { VulkanBufferObject(VmaAllocator allocator, VulkanStagePool& stagePool, uint32_t byteCount, BufferObjectBinding bindingType); @@ -426,28 +410,13 @@ struct VulkanBufferObject : public HwBufferObject, VulkanResource { const BufferObjectBinding bindingType; }; -struct VulkanSamplerGroup : public HwSamplerGroup, VulkanResource { - // NOTE: we have to use out-of-line allocation here because the size of a Handle<> is limited - std::unique_ptr sb;// FIXME: this shouldn't depend on filament::SamplerGroup - explicit VulkanSamplerGroup(size_t size) noexcept - : VulkanResource(VulkanResourceType::SAMPLER_GROUP), - sb(new SamplerGroup(size)) {} -}; - -struct VulkanRenderPrimitive : public HwRenderPrimitive, VulkanResource { - VulkanRenderPrimitive(VulkanResourceAllocator* resourceAllocator, - PrimitiveType pt, Handle vbh, Handle ibh); +struct VulkanRenderPrimitive : public HwRenderPrimitive, fvkmemory::Resource { + VulkanRenderPrimitive(PrimitiveType pt, fvkmemory::resource_ptr vb, + fvkmemory::resource_ptr ib); + ~VulkanRenderPrimitive() = default; - ~VulkanRenderPrimitive() { - mResources.clear(); - } - - VulkanVertexBuffer* vertexBuffer = nullptr; - VulkanIndexBuffer* indexBuffer = nullptr; - -private: - // Keep references to the vertex buffer and the index buffer. - FixedSizeVulkanResourceManager<2> mResources; + fvkmemory::resource_ptr vertexBuffer; + fvkmemory::resource_ptr indexBuffer; }; inline constexpr VkBufferUsageFlagBits getBufferObjectUsage( diff --git a/filament/backend/src/vulkan/VulkanPipelineCache.cpp b/filament/backend/src/vulkan/VulkanPipelineCache.cpp index dd730fdab73..4cf98cef15a 100644 --- a/filament/backend/src/vulkan/VulkanPipelineCache.cpp +++ b/filament/backend/src/vulkan/VulkanPipelineCache.cpp @@ -241,7 +241,7 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n return &mPipelines.emplace(mPipelineRequirements, cacheEntry).first.value(); } -void VulkanPipelineCache::bindProgram(VulkanProgram* program) noexcept { +void VulkanPipelineCache::bindProgram(fvkmemory::resource_ptr program) noexcept { mPipelineRequirements.shaders[0] = program->getVertexShader(); mPipelineRequirements.shaders[1] = program->getFragmentShader(); diff --git a/filament/backend/src/vulkan/VulkanPipelineCache.h b/filament/backend/src/vulkan/VulkanPipelineCache.h index 702d27f245f..c0500fbb8be 100644 --- a/filament/backend/src/vulkan/VulkanPipelineCache.h +++ b/filament/backend/src/vulkan/VulkanPipelineCache.h @@ -19,7 +19,6 @@ #include "VulkanCommands.h" #include "VulkanMemory.h" -#include "VulkanResources.h" #include "VulkanUtility.h" #include @@ -44,7 +43,6 @@ namespace filament::backend { struct VulkanProgram; struct VulkanBufferObject; struct VulkanTexture; -class VulkanResourceAllocator; // VulkanPipelineCache manages a cache of descriptor sets and pipelines. // @@ -122,7 +120,7 @@ class VulkanPipelineCache { void bindPipeline(VulkanCommandBuffer* commands); // Each of the following methods are fast and do not make Vulkan calls. - void bindProgram(VulkanProgram* program) noexcept; + void bindProgram(fvkmemory::resource_ptr program) noexcept; void bindRasterState(const RasterState& rasterState) noexcept; void bindRenderPass(VkRenderPass renderPass, int subpassIndex) noexcept; void bindPrimitiveTopology(VkPrimitiveTopology topology) noexcept; diff --git a/filament/backend/src/vulkan/VulkanReadPixels.cpp b/filament/backend/src/vulkan/VulkanReadPixels.cpp index c7d95d96bec..48df6c72227 100644 --- a/filament/backend/src/vulkan/VulkanReadPixels.cpp +++ b/filament/backend/src/vulkan/VulkanReadPixels.cpp @@ -117,9 +117,10 @@ void VulkanReadPixels::terminate() noexcept { VulkanReadPixels::VulkanReadPixels(VkDevice device) : mDevice(device) {} -void VulkanReadPixels::run(VulkanRenderTarget* srcTarget, uint32_t const x, uint32_t const y, - uint32_t const width, uint32_t const height, uint32_t const graphicsQueueFamilyIndex, - PixelBufferDescriptor&& pbd, SelecteMemoryFunction const& selectMemoryFunc, +void VulkanReadPixels::run(fvkmemory::resource_ptr srcTarget, uint32_t const x, + uint32_t const y, uint32_t const width, uint32_t const height, + uint32_t const graphicsQueueFamilyIndex, PixelBufferDescriptor&& pbd, + SelecteMemoryFunction const& selectMemoryFunc, OnReadCompleteFunction const& readCompleteFunc) { assert_invariant(mDevice != VK_NULL_HANDLE); @@ -143,7 +144,7 @@ void VulkanReadPixels::run(VulkanRenderTarget* srcTarget, uint32_t const x, uint VkCommandPool& cmdpool = mCommandPool; - VulkanTexture* srcTexture = srcTarget->getColor0().texture; + fvkmemory::resource_ptr srcTexture = srcTarget->getColor0().texture; assert_invariant(srcTexture); VkFormat const srcFormat = srcTexture->getVkFormat(); bool const swizzle diff --git a/filament/backend/src/vulkan/VulkanReadPixels.h b/filament/backend/src/vulkan/VulkanReadPixels.h index e5dd2a31bb9..23699537d31 100644 --- a/filament/backend/src/vulkan/VulkanReadPixels.h +++ b/filament/backend/src/vulkan/VulkanReadPixels.h @@ -17,6 +17,7 @@ #ifndef TNT_FILAMENT_BACKEND_VULKANREADPIXELS_H #define TNT_FILAMENT_BACKEND_VULKANREADPIXELS_H +#include "vulkan/memory/ResourcePointer.h" #include "private/backend/Driver.h" #include @@ -72,9 +73,9 @@ class VulkanReadPixels { void terminate() noexcept; - void run(VulkanRenderTarget* srcTarget, uint32_t x, uint32_t y, uint32_t width, uint32_t height, - uint32_t graphicsQueueFamilyIndex, PixelBufferDescriptor&& pbd, - SelecteMemoryFunction const& selectMemoryFunc, + void run(fvkmemory::resource_ptr srcTarget, uint32_t x, uint32_t y, + uint32_t width, uint32_t height, uint32_t graphicsQueueFamilyIndex, + PixelBufferDescriptor&& pbd, SelecteMemoryFunction const& selectMemoryFunc, OnReadCompleteFunction const& readCompleteFunc); // This method will block until all of the in-flight requests are complete. diff --git a/filament/backend/src/vulkan/VulkanResourceAllocator.h b/filament/backend/src/vulkan/VulkanResourceAllocator.h deleted file mode 100644 index 572aeed4f78..00000000000 --- a/filament/backend/src/vulkan/VulkanResourceAllocator.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TNT_FILAMENT_BACKEND_VULKANRESOURCEALLOCATOR_H -#define TNT_FILAMENT_BACKEND_VULKANRESOURCEALLOCATOR_H - -#include "VulkanConstants.h" -#include "VulkanHandles.h" - -#include - -#include -#include - -#include -#include - -namespace filament::backend { - -#define RESOURCE_TYPE_COUNT (static_cast(VulkanResourceType::END_TYPE)) -#define DEBUG_RESOURCE_LEAKS FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK) - -#if DEBUG_RESOURCE_LEAKS - #define TRACK_INCREMENT() \ - if (!IS_HEAP_ALLOC_TYPE(obj->getType())) { \ - mDebugOnlyResourceCount[static_cast(obj->getType())]++; \ - } - #define TRACK_DECREMENT() \ - if (!IS_HEAP_ALLOC_TYPE(obj->getType())) { \ - mDebugOnlyResourceCount[static_cast(obj->getType())]--; \ - } -#else - // No-op - #define TRACK_INCREMENT() - #define TRACK_DECREMENT() -#endif - -class VulkanResourceAllocator { -public: - using AllocatorImpl = HandleAllocatorVK; - VulkanResourceAllocator(size_t arenaSize, bool disableUseAfterFreeCheck) - : mHandleAllocatorImpl("Handles", arenaSize, disableUseAfterFreeCheck) -#if DEBUG_RESOURCE_LEAKS - , mDebugOnlyResourceCount(RESOURCE_TYPE_COUNT) { - std::memset(mDebugOnlyResourceCount.data(), 0, sizeof(size_t) * RESOURCE_TYPE_COUNT); - } -#else - {} -#endif - - template - inline Handle initHandle(ARGS&&... args) noexcept { - auto handle = mHandleAllocatorImpl.allocateAndConstruct(std::forward(args)...); - auto obj = handle_cast(handle); - obj->initResource(handle.getId()); - TRACK_INCREMENT(); - return handle; - } - - template - inline Handle allocHandle() noexcept { - return mHandleAllocatorImpl.allocate(); - } - - template - inline typename std::enable_if::value, D>::type* construct( - Handle const& handle, ARGS&&... args) noexcept { - auto obj = mHandleAllocatorImpl.construct(handle, std::forward(args)...); - obj->initResource(handle.getId()); - TRACK_INCREMENT(); - return obj; - } - - template - inline typename std::enable_if_t< - std::is_pointer_v && std::is_base_of_v>, Dp> - handle_cast(Handle& handle) noexcept { - return mHandleAllocatorImpl.handle_cast(handle); - } - - template - inline typename std::enable_if_t< - std::is_pointer_v && std::is_base_of_v>, Dp> - handle_cast(Handle const& handle) noexcept { - return mHandleAllocatorImpl.handle_cast(handle); - } - - template - inline void destruct(Handle handle) noexcept { - auto obj = handle_cast(handle); - TRACK_DECREMENT(); - mHandleAllocatorImpl.deallocate(handle, obj); - } - - inline void associateHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept { - mHandleAllocatorImpl.associateTagToHandle(id, std::move(tag)); - } - -private: - AllocatorImpl mHandleAllocatorImpl; - -#if DEBUG_RESOURCE_LEAKS -public: - void print() { - FVK_LOGD << "Resource Allocator state (debug only)" << utils::io::endl; - for (size_t i = 0; i < RESOURCE_TYPE_COUNT; i++) { - FVK_LOGD << "[" << i << "]=" << mDebugOnlyResourceCount[i] << utils::io::endl; - } - FVK_LOGD << "+++++++++++++++++++++++++++++++++++++" << utils::io::endl; - } -private: - utils::FixedCapacityVector mDebugOnlyResourceCount; -#endif - -}; - -#undef TRACK_INCREMENT -#undef TRACK_DECREMENT -#undef DEBUG_RESOURCE_LEAKS - -} // namespace filament::backend - -#endif // TNT_FILAMENT_BACKEND_VULKANRESOURCEALLOCATOR_H diff --git a/filament/backend/src/vulkan/VulkanResources.cpp b/filament/backend/src/vulkan/VulkanResources.cpp deleted file mode 100644 index deb3a3168e6..00000000000 --- a/filament/backend/src/vulkan/VulkanResources.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "VulkanResources.h" -#include "VulkanHandles.h" -#include "VulkanResourceAllocator.h" -#include "VulkanPipelineCache.h" - -namespace filament::backend { - -void deallocateResource(VulkanResourceAllocator* allocator, VulkanResourceType type, - HandleBase::HandleId id) { - - if (IS_HEAP_ALLOC_TYPE(type)) { - return; - } - - switch (type) { - case VulkanResourceType::BUFFER_OBJECT: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::INDEX_BUFFER: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::PROGRAM: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::RENDER_TARGET: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::SAMPLER_GROUP: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::SWAP_CHAIN: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::TEXTURE: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::TIMER_QUERY: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::VERTEX_BUFFER_INFO: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::VERTEX_BUFFER: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::RENDER_PRIMITIVE: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::DESCRIPTOR_SET_LAYOUT: - allocator->destruct(Handle(id)); - break; - case VulkanResourceType::DESCRIPTOR_SET: - allocator->destruct(Handle(id)); - break; - - // If the resource is heap allocated, then the resource manager just skip refcounted - // destruction. - case VulkanResourceType::FENCE: - case VulkanResourceType::HEAP_ALLOCATED: - case VulkanResourceType::END_TYPE: - break; - } -} - -} // namespace filament::backend diff --git a/filament/backend/src/vulkan/VulkanResources.h b/filament/backend/src/vulkan/VulkanResources.h deleted file mode 100644 index cbfb70ab608..00000000000 --- a/filament/backend/src/vulkan/VulkanResources.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TNT_FILAMENT_BACKEND_VULKANRESOURCES_H -#define TNT_FILAMENT_BACKEND_VULKANRESOURCES_H - -#include "VulkanUtility.h" - -#include - -#include -#include -#include - -#include -#include - -namespace filament::backend { - -class VulkanResourceAllocator; -struct VulkanThreadSafeResource; - -// Subclasses of VulkanResource must provide this enum in their construction. -enum class VulkanResourceType : uint8_t { - BUFFER_OBJECT = 0, - INDEX_BUFFER = 1, - PROGRAM = 2, - RENDER_TARGET = 3, - SAMPLER_GROUP = 4, - SWAP_CHAIN = 5, - RENDER_PRIMITIVE = 6, - TEXTURE = 7, - TIMER_QUERY = 8, - VERTEX_BUFFER = 9, - VERTEX_BUFFER_INFO = 10, - DESCRIPTOR_SET_LAYOUT = 11, - DESCRIPTOR_SET = 12, - - // Below are resources that are managed manually (i.e. not ref counted). - FENCE = 13, - HEAP_ALLOCATED = 14, - - END_TYPE = 15, // A placeholder -}; - -#define IS_HEAP_ALLOC_TYPE(f) \ - (f == VulkanResourceType::FENCE || f == VulkanResourceType::HEAP_ALLOCATED) - - -// This is a ref-counting base class that tracks how many references of this resource exist. This -// class is paired with VulkanResourceManagerImpl which is responsible for incrementing or -// decrementing the count. Once mRefCount == 0, VulkanResourceManagerImpl will also call the -// appropriate destructor. VulkanCommandBuffer, VulkanDriver, and composite structure like -// VulkanRenderPrimitive are owners of VulkanResourceManagerImpl instances. -struct VulkanResourceBase { -protected: - explicit VulkanResourceBase(VulkanResourceType type) - : mRefCount(IS_HEAP_ALLOC_TYPE(type) ? 1 : 0), - mType(uint32_t(type)), - mHandleId(0) { - } - -private: - inline VulkanResourceType getType() const noexcept { - return VulkanResourceType(mType); - } - - inline HandleBase::HandleId getId() const noexcept { - return mHandleId; - } - - inline void initResource(HandleBase::HandleId id) noexcept { - mHandleId = id; - } - - inline void ref() noexcept { - if (IS_HEAP_ALLOC_TYPE(getType())) { - return; - } - assert_invariant(mRefCount < ((1<<24) - 1)); - ++mRefCount; - } - - inline void deref() noexcept { - if (IS_HEAP_ALLOC_TYPE(getType())) { - return; - } - assert_invariant(mRefCount > 0); - --mRefCount; - } - - inline size_t refcount() const noexcept { - return mRefCount; - } - - uint32_t mRefCount : 24; // 16M is enough for the refcount - uint32_t mType : 8; // must be uint32_t or MSVC doesn't pack it. no codegen impact w/ clang. - HandleBase::HandleId mHandleId; - - friend struct VulkanThreadSafeResource; - friend class VulkanResourceAllocator; - - template - friend class VulkanResourceManagerImpl; -}; - -static_assert(sizeof(VulkanResourceBase) == 8, "VulkanResourceBase should be 8 bytes"); - -struct VulkanThreadSafeResource { -protected: - explicit VulkanThreadSafeResource(VulkanResourceType type) - : mImpl(type) {} - -private: - inline VulkanResourceType getType() { - return mImpl.getType(); - } - - inline HandleBase::HandleId getId() { - return mImpl.getId(); - } - - inline void initResource(HandleBase::HandleId id) noexcept { - std::unique_lock lock(mMutex); - mImpl.initResource(id); - } - - inline void ref() noexcept { - std::unique_lock lock(mMutex); - mImpl.ref(); - } - - inline void deref() noexcept { - std::unique_lock lock(mMutex); - mImpl.deref(); - } - - inline size_t refcount() noexcept { - std::unique_lock lock(mMutex); - return mImpl.refcount(); - } - - utils::Mutex mMutex; - VulkanResourceBase mImpl; - - friend class VulkanResourceAllocator; - template - friend class VulkanResourceManagerImpl; -}; - -using VulkanResource = VulkanResourceBase; - -namespace { - -// When the size of the resource set is known to be small, (for example for VulkanRenderPrimitive), -// we just use a std::array to back the set. -template -using FixedCapacityResourceSet = CappedArray; - -// robin_set/map are useful for sets that are acquire only and the set will be iterated when the set -// is cleared. -using FastIterationResourceSet = tsl::robin_set; - -// unoredered_set is used in the general case where insert/erase can occur at will. This is useful -// for the basic object ownership count - i.e. VulkanDriver. -using ResourceSet = std::unordered_set; - -using ThreadSafeResourceSet = std::unordered_set; - -} // anonymous namespace - -class VulkanResourceAllocator; - -#define LOCK_IF_NEEDED() \ - if constexpr (std::is_base_of_v) { \ - mMutex->lock(); \ - } - -#define UNLOCK_IF_NEEDED() \ - if constexpr (std::is_base_of_v) { \ - mMutex->unlock(); \ - } - -void deallocateResource(VulkanResourceAllocator* allocator, VulkanResourceType type, - HandleBase::HandleId id); - -template -class VulkanResourceManagerImpl { -public: - explicit VulkanResourceManagerImpl(VulkanResourceAllocator* allocator) - : mAllocator(allocator) { - if constexpr (std::is_base_of_v) { - mMutex = std::make_unique(); - } - } - - VulkanResourceManagerImpl(const VulkanResourceManagerImpl& other) = delete; - void operator=(const VulkanResourceManagerImpl& other) = delete; - VulkanResourceManagerImpl(const VulkanResourceManagerImpl&& other) = delete; - void operator=(const VulkanResourceManagerImpl&& other) = delete; - - ~VulkanResourceManagerImpl() { - clear(); - } - - inline void acquire(ResourceType* resource) { - if (IS_HEAP_ALLOC_TYPE(resource->getType())) { - return; - } - - LOCK_IF_NEEDED(); - if (mResources.find(resource) != mResources.end()) { - UNLOCK_IF_NEEDED(); - return; - } - mResources.insert(resource); - UNLOCK_IF_NEEDED(); - resource->ref(); - } - - // Transfers ownership from one resource set to another - template - inline void acquireAll(VulkanResourceManagerImpl* srcResources) { - copyAll(srcResources); - srcResources->clear(); - } - - // Transfers ownership from one resource set to another - template - inline void copyAll(VulkanResourceManagerImpl* srcResources) { - LOCK_IF_NEEDED(); - for (auto iter = srcResources->mResources.begin(); iter != srcResources->mResources.end(); - iter++) { - acquire(*iter); - } - UNLOCK_IF_NEEDED(); - } - - inline void release(ResourceType* resource) { - if (IS_HEAP_ALLOC_TYPE(resource->getType())) { - return; - } - - LOCK_IF_NEEDED(); - auto resItr = mResources.find(resource); - if (resItr == mResources.end()) { - UNLOCK_IF_NEEDED(); - return; - } - mResources.erase(resItr); - UNLOCK_IF_NEEDED(); - derefImpl(resource); - } - - inline void clear() { - LOCK_IF_NEEDED(); - for (auto iter = mResources.begin(); iter != mResources.end(); iter++) { - derefImpl(*iter); - } - mResources.clear(); - UNLOCK_IF_NEEDED(); - } - - inline size_t size() { - return mResources.size(); - } - -private: - inline void derefImpl(ResourceType* resource) { - resource->deref(); - if (resource->refcount() != 0) { - return; - } - deallocateResource(mAllocator, resource->getType(), resource->getId()); - } - - VulkanResourceAllocator* mAllocator; - SetType mResources; - std::unique_ptr mMutex; - - template friend class VulkanResourceManagerImpl; -}; - -using VulkanAcquireOnlyResourceManager - = VulkanResourceManagerImpl; -using VulkanResourceManager = VulkanResourceManagerImpl; - -template -using FixedSizeVulkanResourceManager = - VulkanResourceManagerImpl>; - -using VulkanThreadSafeResourceManager - = VulkanResourceManagerImpl; - -#undef LOCK_IF_NEEDED -#undef UNLOCK_IF_NEEDED - -} // namespace filament::backend - -#endif // TNT_FILAMENT_BACKEND_VULKANRESOURCES_H diff --git a/filament/backend/src/vulkan/VulkanStagePool.cpp b/filament/backend/src/vulkan/VulkanStagePool.cpp index 067b16afd84..a3964225bd2 100644 --- a/filament/backend/src/vulkan/VulkanStagePool.cpp +++ b/filament/backend/src/vulkan/VulkanStagePool.cpp @@ -16,6 +16,7 @@ #include "VulkanStagePool.h" +#include "VulkanCommands.h" #include "VulkanConstants.h" #include "VulkanImageUtility.h" #include "VulkanMemory.h" @@ -59,7 +60,7 @@ VulkanStage const* VulkanStagePool::acquireStage(uint32_t numBytes) { UTILS_UNUSED_IN_RELEASE VkResult result = vmaCreateBuffer(mAllocator, &bufferInfo, &allocInfo, &stage->buffer, &stage->memory, nullptr); -#if FVK_ENABLED(FVK_DEBUG_ALLOCATION) +#if FVK_ENABLED(FVK_DEBUG_STAGING_ALLOCATION) if (result != VK_SUCCESS) { FVK_LOGE << "Allocation error: " << result << utils::io::endl; } diff --git a/filament/backend/src/vulkan/VulkanStagePool.h b/filament/backend/src/vulkan/VulkanStagePool.h index d2aacae5013..6c8e307ff3f 100644 --- a/filament/backend/src/vulkan/VulkanStagePool.h +++ b/filament/backend/src/vulkan/VulkanStagePool.h @@ -17,8 +17,7 @@ #ifndef TNT_FILAMENT_BACKEND_VULKANSTAGEPOOL_H #define TNT_FILAMENT_BACKEND_VULKANSTAGEPOOL_H -#include "VulkanCommands.h" -#include "VulkanContext.h" +#include "backend/DriverEnums.h" #include "VulkanMemory.h" #include @@ -26,6 +25,8 @@ namespace filament::backend { +class VulkanCommands; + // Immutable POD representing a shared CPU-GPU staging area. struct VulkanStage { VmaAllocation memory; diff --git a/filament/backend/src/vulkan/VulkanSwapChain.cpp b/filament/backend/src/vulkan/VulkanSwapChain.cpp index bf9fd353cd8..c1df76e76db 100644 --- a/filament/backend/src/vulkan/VulkanSwapChain.cpp +++ b/filament/backend/src/vulkan/VulkanSwapChain.cpp @@ -15,6 +15,8 @@ */ #include "VulkanSwapChain.h" + +#include "VulkanCommands.h" #include "VulkanTexture.h" #include @@ -26,19 +28,18 @@ using namespace utils; namespace filament::backend { VulkanSwapChain::VulkanSwapChain(VulkanPlatform* platform, VulkanContext const& context, - VmaAllocator allocator, VulkanCommands* commands, VulkanResourceAllocator* handleAllocator, - VulkanStagePool& stagePool, - void* nativeWindow, uint64_t flags, VkExtent2D extent) - : VulkanResource(VulkanResourceType::SWAP_CHAIN), - mPlatform(platform), + fvkmemory::ResourceManager* resourceManager, VmaAllocator allocator, + VulkanCommands* commands, VulkanStagePool& stagePool, void* nativeWindow, uint64_t flags, + VkExtent2D extent) + : mPlatform(platform), + mResourceManager(resourceManager), mCommands(commands), mAllocator(allocator), - mHandleAllocator(handleAllocator), mStagePool(stagePool), mHeadless(extent.width != 0 && extent.height != 0 && !nativeWindow), mFlushAndWaitOnResize(platform->getCustomization().flushAndWaitOnWindowResize), mTransitionSwapChainImageLayoutForPresent( - platform->getCustomization().transitionSwapChainImageLayoutForPresent), + platform->getCustomization().transitionSwapChainImageLayoutForPresent), mAcquired(false), mIsFirstRenderPass(true) { swapChain = mPlatform->createSwapChain(nativeWindow, flags, extent); @@ -53,6 +54,9 @@ VulkanSwapChain::~VulkanSwapChain() { mCommands->flush(); mCommands->wait(); + mColors = {}; + mDepth = {}; + mPlatform->destroy(swapChain); } @@ -70,13 +74,16 @@ void VulkanSwapChain::update() { colorUsage |= TextureUsage::PROTECTED; } for (auto const color: bundle.colors) { - mColors.push_back(std::make_unique(device, mAllocator, mCommands, mHandleAllocator, - color, bundle.colorFormat, 1, bundle.extent.width, bundle.extent.height, - colorUsage, mStagePool, true /* heap allocated */)); + auto colorTexture = fvkmemory::resource_ptr::construct(mResourceManager, + device, mAllocator, mResourceManager, mCommands, color, bundle.colorFormat, 1, + bundle.extent.width, bundle.extent.height, TextureUsage::COLOR_ATTACHMENT, + mStagePool); + mColors.push_back(colorTexture); } - mDepth = std::make_unique(device, mAllocator, mCommands, mHandleAllocator, - bundle.depth, bundle.depthFormat, 1, bundle.extent.width, bundle.extent.height, - depthUsage, mStagePool, true /* heap allocated */); + + mDepth = fvkmemory::resource_ptr::construct(mResourceManager, device, mAllocator, + mResourceManager, mCommands, bundle.depth, bundle.depthFormat, 1, bundle.extent.width, + bundle.extent.height, TextureUsage::DEPTH_ATTACHMENT, mStagePool); mExtent = bundle.extent; } @@ -95,7 +102,7 @@ void VulkanSwapChain::present() { } mCommands->flush(); - + // call the image ready wait function if (mExplicitImageReadyWait != nullptr) { mExplicitImageReadyWait(swapChain); @@ -135,7 +142,7 @@ void VulkanSwapChain::acquire(bool& resized) { VkResult const result = mPlatform->acquire(swapChain, &imageSyncData); mCurrentSwapIndex = imageSyncData.imageIndex; mExplicitImageReadyWait = imageSyncData.explicitImageReadyWait; - FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) + FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) << "Cannot acquire in swapchain."; if (imageSyncData.imageReadySemaphore != VK_NULL_HANDLE) { mCommands->injectDependency(imageSyncData.imageReadySemaphore); diff --git a/filament/backend/src/vulkan/VulkanSwapChain.h b/filament/backend/src/vulkan/VulkanSwapChain.h index acb88c56b95..bf1c26945bb 100644 --- a/filament/backend/src/vulkan/VulkanSwapChain.h +++ b/filament/backend/src/vulkan/VulkanSwapChain.h @@ -19,9 +19,9 @@ #include "DriverBase.h" -#include "VulkanCommands.h" #include "VulkanContext.h" -#include "VulkanResources.h" +#include "VulkanTexture.h" +#include "vulkan/memory/Resource.h" #include @@ -36,14 +36,14 @@ namespace filament::backend { struct VulkanHeadlessSwapChain; struct VulkanSurfaceSwapChain; -class VulkanResourceAllocator; +class VulkanCommands; // A wrapper around the platform implementation of swapchain. -struct VulkanSwapChain : public HwSwapChain, VulkanResource { - VulkanSwapChain(VulkanPlatform* platform, VulkanContext const& context, VmaAllocator allocator, - VulkanCommands* commands, VulkanResourceAllocator* handleAllocator, - VulkanStagePool& stagePool, - void* nativeWindow, uint64_t flags, VkExtent2D extent = {0, 0}); +struct VulkanSwapChain : public HwSwapChain, fvkmemory::Resource { + VulkanSwapChain(VulkanPlatform* platform, VulkanContext const& context, + fvkmemory::ResourceManager* resourceManager, VmaAllocator allocator, + VulkanCommands* commands, VulkanStagePool& stagePool, void* nativeWindow, + uint64_t flags, VkExtent2D extent = {0, 0}); ~VulkanSwapChain(); @@ -51,15 +51,15 @@ struct VulkanSwapChain : public HwSwapChain, VulkanResource { void acquire(bool& reized); - inline VulkanTexture* getCurrentColor() const noexcept { + fvkmemory::resource_ptr getCurrentColor() const noexcept { uint32_t const imageIndex = mCurrentSwapIndex; FILAMENT_CHECK_PRECONDITION( imageIndex != VulkanPlatform::ImageSyncData::INVALID_IMAGE_INDEX); - return mColors[imageIndex].get(); + return mColors[imageIndex]; } - inline VulkanTexture* getDepth() const noexcept { - return mDepth.get(); + inline fvkmemory::resource_ptr getDepth() const noexcept { + return mDepth; } inline bool isFirstRenderPass() const noexcept { @@ -83,9 +83,9 @@ struct VulkanSwapChain : public HwSwapChain, VulkanResource { void update(); VulkanPlatform* mPlatform; + fvkmemory::ResourceManager* mResourceManager; VulkanCommands* mCommands; VmaAllocator mAllocator; - VulkanResourceAllocator* const mHandleAllocator; VulkanStagePool& mStagePool; bool const mHeadless; bool const mFlushAndWaitOnResize; @@ -93,8 +93,8 @@ struct VulkanSwapChain : public HwSwapChain, VulkanResource { // We create VulkanTextures based on VkImages. VulkanTexture has facilities for doing layout // transitions, which are useful here. - utils::FixedCapacityVector> mColors; - std::unique_ptr mDepth; + utils::FixedCapacityVector> mColors; + fvkmemory::resource_ptr mDepth; VkExtent2D mExtent; uint32_t mCurrentSwapIndex; std::function mExplicitImageReadyWait = nullptr; diff --git a/filament/backend/src/vulkan/VulkanTexture.cpp b/filament/backend/src/vulkan/VulkanTexture.cpp index a526310118e..105ae8072d4 100644 --- a/filament/backend/src/vulkan/VulkanTexture.cpp +++ b/filament/backend/src/vulkan/VulkanTexture.cpp @@ -14,10 +14,11 @@ * limitations under the License. */ +#include "VulkanCommands.h" #include "VulkanMemory.h" -#include "VulkanResourceAllocator.h" #include "VulkanTexture.h" #include "VulkanUtility.h" +#include "vulkan/memory/ResourcePointer.h" #include #include @@ -149,8 +150,7 @@ VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator, VulkanCommands* commands, VulkanStagePool& stagePool, VkFormat format, VkImageViewType viewType, uint8_t levels, uint8_t layerCount, VulkanLayout defaultLayout, bool isProtected) - : VulkanResource(VulkanResourceType::HEAP_ALLOCATED), - mVkFormat(format), + : mVkFormat(format), mViewType(viewType), mFullViewRange{filament::backend::getImageAspect(format), 0, levels, 0, layerCount}, mDefaultLayout(defaultLayout), @@ -161,61 +161,42 @@ VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator, mCommands(commands), mIsTransientAttachment(false) {} -VulkanTextureState* VulkanTexture::getSharedState() { - VulkanTextureState* state = mAllocator->handle_cast(mState); - return state; -} - -VulkanTextureState const* VulkanTexture::getSharedState() const { - VulkanTextureState const* state = mAllocator->handle_cast(mState); - return state; -} - // Constructor for internally passed VkImage -VulkanTexture::VulkanTexture( - VkDevice device, VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, - VkImage image, VkFormat format, uint8_t samples, uint32_t width, uint32_t height, - TextureUsage tusage, VulkanStagePool& stagePool, bool heapAllocated) - : HwTexture(SamplerType::SAMPLER_2D, 1, samples, width, height, 1, TextureFormat::UNUSED, - tusage), - VulkanResource( - heapAllocated ? VulkanResourceType::HEAP_ALLOCATED : VulkanResourceType::TEXTURE), - mAllocator(handleAllocator), - mState(handleAllocator->initHandle( - device, allocator, commands, stagePool, - format, imgutil::getViewType(SamplerType::SAMPLER_2D), 1, 1, - getDefaultLayoutImpl(tusage), - any(usage& TextureUsage::PROTECTED))) { - auto* const state = getSharedState(); - state->mTextureImage = image; - mPrimaryViewRange = state->mFullViewRange; +VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator, + fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image, + VkFormat format, uint8_t samples, uint32_t width, uint32_t height, TextureUsage tusage, + VulkanStagePool& stagePool) + : HwTexture(SamplerType::SAMPLER_2D, 1, samples, width, height, 1, TextureFormat::UNUSED, + tusage), + mState(fvkmemory::resource_ptr::construct(resourceManager, device, + allocator, commands, stagePool, format, imgutil::getViewType(SamplerType::SAMPLER_2D), + 1, 1, getDefaultLayoutImpl(tusage), any(usage & TextureUsage::PROTECTED))) { + mState->mTextureImage = image; + mPrimaryViewRange = mState->mFullViewRange; } // Constructor for user facing texture VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, - VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, SamplerType target, uint8_t levels, - TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth, - TextureUsage tusage, VulkanStagePool& stagePool, bool heapAllocated) + VulkanContext const& context, VmaAllocator allocator, + fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, SamplerType target, + uint8_t levels, TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h, + uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool) : HwTexture(target, levels, samples, w, h, depth, tformat, tusage), - VulkanResource( - heapAllocated ? VulkanResourceType::HEAP_ALLOCATED : VulkanResourceType::TEXTURE), - mAllocator(handleAllocator), - mState(handleAllocator->initHandle(device, allocator, commands, stagePool, - backend::getVkFormat(tformat), imgutil::getViewType(target), levels, - getLayerCount(target, depth), VulkanLayout::UNDEFINED, any(usage& TextureUsage::PROTECTED))) { - auto* const state = getSharedState(); - + mState(fvkmemory::resource_ptr::construct(resourceManager, device, + allocator, commands, stagePool, backend::getVkFormat(tformat), + imgutil::getViewType(target), levels, getLayerCount(target, depth), + VulkanLayout::UNDEFINED, any(usage & TextureUsage::PROTECTED))) { // Create an appropriately-sized device-only VkImage, but do not fill it yet. - VkImageCreateInfo imageInfo{.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .imageType = target == SamplerType::SAMPLER_3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D, - .format = state->mVkFormat, - .extent = {w, h, depth}, - .mipLevels = levels, - .arrayLayers = 1, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = 0}; + VkImageCreateInfo imageInfo{ + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = target == SamplerType::SAMPLER_3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D, + .format = mState->mVkFormat, + .extent = {w, h, depth}, + .mipLevels = levels, + .arrayLayers = 1, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = 0, + }; if (target == SamplerType::SAMPLER_CUBEMAP) { imageInfo.arrayLayers = 6; imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; @@ -254,7 +235,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, none(tusage & ~TextureUsage::ALL_ATTACHMENTS) && // Usage contains at least one attachment flag. any(tusage & TextureUsage::ALL_ATTACHMENTS); - state->mIsTransientAttachment = useTransientAttachment; + mState->mIsTransientAttachment = useTransientAttachment; const VkImageUsageFlags transientFlag = useTransientAttachment ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : 0U; @@ -299,7 +280,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, // any kind of attachment (color or depth). const auto& limits = context.getPhysicalDeviceLimits(); if (imageInfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) { - samples = reduceSampleCount(samples, isVkDepthFormat(state->mVkFormat) + samples = reduceSampleCount(samples, isVkDepthFormat(mState->mVkFormat) ? limits.sampledImageDepthSampleCounts : limits.sampledImageColorSampleCounts); } @@ -313,12 +294,12 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, this->samples = samples; imageInfo.samples = (VkSampleCountFlagBits) samples; - VkResult error = vkCreateImage(state->mDevice, &imageInfo, VKALLOC, &state->mTextureImage); + VkResult error = vkCreateImage(mState->mDevice, &imageInfo, VKALLOC, &mState->mTextureImage); if (error || FVK_ENABLED(FVK_DEBUG_TEXTURE)) { FVK_LOGD << "vkCreateImage: " - << "image = " << state->mTextureImage << ", " + << "image = " << mState->mTextureImage << ", " << "result = " << error << ", " - << "handle = " << utils::io::hex << state->mTextureImage << utils::io::dec << ", " + << "handle = " << utils::io::hex << mState->mTextureImage << utils::io::dec << ", " << "extent = " << w << "x" << h << "x"<< depth << ", " << "mipLevels = " << int(levels) << ", " << "TextureUsage = " << static_cast(usage) << ", " @@ -327,18 +308,18 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, << "type = " << imageInfo.imageType << ", " << "flags = " << imageInfo.flags << ", " << "target = " << static_cast(target) <<", " - << "format = " << state->mVkFormat << utils::io::endl; + << "format = " << mState->mVkFormat << utils::io::endl; } FILAMENT_CHECK_POSTCONDITION(!error) << "Unable to create image."; // Allocate memory for the VkImage and bind it. VkMemoryRequirements memReqs = {}; - vkGetImageMemoryRequirements(state->mDevice, state->mTextureImage, &memReqs); + vkGetImageMemoryRequirements(mState->mDevice, mState->mTextureImage, &memReqs); const VkFlags requiredMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | (useTransientAttachment ? VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT : 0U) | - (state->mIsProtected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0U); + (mState->mIsProtected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0U); uint32_t memoryTypeIndex = context.selectMemoryType(memReqs.memoryTypeBits, requiredMemoryFlags); @@ -350,37 +331,29 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, .allocationSize = memReqs.size, .memoryTypeIndex = memoryTypeIndex, }; - error = vkAllocateMemory(state->mDevice, &allocInfo, nullptr, &state->mTextureImageMemory); + error = vkAllocateMemory(mState->mDevice, &allocInfo, nullptr, &mState->mTextureImageMemory); FILAMENT_CHECK_POSTCONDITION(!error) << "Unable to allocate image memory."; - error = vkBindImageMemory(state->mDevice, state->mTextureImage, state->mTextureImageMemory, 0); + error = vkBindImageMemory(mState->mDevice, mState->mTextureImage, mState->mTextureImageMemory, + 0); FILAMENT_CHECK_POSTCONDITION(!error) << "Unable to bind image."; // Spec out the "primary" VkImageView that shaders use to sample from the image. - mPrimaryViewRange = state->mFullViewRange; + mPrimaryViewRange = mState->mFullViewRange; // Go ahead and create the primary image view. - getImageView(mPrimaryViewRange, state->mViewType, mSwizzle); + getImageView(mPrimaryViewRange, mState->mViewType, mSwizzle); - VulkanCommandBuffer& commandsBuf = state->mCommands->get(); - commandsBuf.acquire(this); - - auto const defaultLayout = state->mDefaultLayout = getDefaultLayoutImpl(imageInfo.usage); - transitionLayout(&commandsBuf, mPrimaryViewRange, defaultLayout); + mState->mDefaultLayout = getDefaultLayoutImpl(imageInfo.usage); } // Constructor for creating a texture view VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, VulkanTexture const* src, uint8_t baseLevel, + fvkmemory::resource_ptr src, uint8_t baseLevel, uint8_t levelCount) : HwTexture(src->target, src->levels, src->samples, src->width, src->height, src->depth, - src->format, src->usage), - VulkanResource(VulkanResourceType::TEXTURE), - mAllocator(handleAllocator) { + src->format, src->usage) { mState = src->mState; - auto* state = getSharedState(); - - state->refs++; mPrimaryViewRange = src->mPrimaryViewRange; mPrimaryViewRange.baseMipLevel = src->mPrimaryViewRange.baseMipLevel + baseLevel; mPrimaryViewRange.levelCount = levelCount; @@ -389,31 +362,21 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, // Constructor for creating a texture view with swizzle VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, VulkanTexture const* src, - VkComponentMapping swizzle) + fvkmemory::resource_ptr src, VkComponentMapping swizzle) : HwTexture(src->target, src->levels, src->samples, src->width, src->height, src->depth, - src->format, src->usage), - VulkanResource(VulkanResourceType::TEXTURE), - mAllocator(handleAllocator) { + src->format, src->usage) { mState = src->mState; - auto* state = getSharedState(); - state->refs++; mPrimaryViewRange = src->mPrimaryViewRange; mSwizzle = composeSwizzle(src->mSwizzle, swizzle); } -VulkanTexture::~VulkanTexture() { - auto* const state = getSharedState(); - state->refs--; - if (state->refs == 0) { - if (state->mTextureImageMemory != VK_NULL_HANDLE) { - vkDestroyImage(state->mDevice, state->mTextureImage, VKALLOC); - vkFreeMemory(state->mDevice, state->mTextureImageMemory, VKALLOC); - } - for (auto entry: state->mCachedImageViews) { - vkDestroyImageView(state->mDevice, entry.second, VKALLOC); - } - mAllocator->destruct(mState); +VulkanTextureState::~VulkanTextureState() { + if (mTextureImageMemory != VK_NULL_HANDLE) { + vkDestroyImage(mDevice, mTextureImage, VKALLOC); + vkFreeMemory(mDevice, mTextureImageMemory, VKALLOC); + } + for (auto entry: mCachedImageViews) { + vkDestroyImageView(mDevice, entry.second, VKALLOC); } } @@ -422,8 +385,7 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt assert_invariant(width <= this->width && height <= this->height); assert_invariant(depth <= this->depth * ((target == SamplerType::SAMPLER_CUBEMAP || target == SamplerType::SAMPLER_CUBEMAP_ARRAY) ? 6 : 1)); - auto* const state = getSharedState(); - assert_invariant(state->mIsProtected == false); + assert_invariant(!mState->mIsProtected); const PixelBufferDescriptor* hostData = &data; PixelBufferDescriptor reshapedData; @@ -436,7 +398,7 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt // If format conversion is both required and supported, use vkCmdBlitImage. const VkFormat hostFormat = backend::getVkFormat(hostData->format, hostData->type); - const VkFormat deviceFormat = getVkFormatLinear(state->mVkFormat); + const VkFormat deviceFormat = getVkFormatLinear(mState->mVkFormat); if (hostFormat != deviceFormat && hostFormat != VK_FORMAT_UNDEFINED) { assert_invariant(xoffset == 0 && yoffset == 0 && zoffset == 0 && "Offsets not yet supported when format conversion is required."); @@ -448,16 +410,16 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt // Otherwise, use vkCmdCopyBufferToImage. void* mapped = nullptr; - VulkanStage const* stage = state->mStagePool.acquireStage(hostData->size); + VulkanStage const* stage = mState->mStagePool.acquireStage(hostData->size); assert_invariant(stage->memory); - vmaMapMemory(state->mAllocator, stage->memory, &mapped); + vmaMapMemory(mState->mAllocator, stage->memory, &mapped); memcpy(mapped, hostData->buffer, hostData->size); - vmaUnmapMemory(state->mAllocator, stage->memory); - vmaFlushAllocation(state->mAllocator, stage->memory, 0, hostData->size); + vmaUnmapMemory(mState->mAllocator, stage->memory); + vmaFlushAllocation(mState->mAllocator, stage->memory, 0, hostData->size); - VulkanCommandBuffer& commands = state->mCommands->get(); + VulkanCommandBuffer& commands = mState->mCommands->get(); VkCommandBuffer const cmdbuf = commands.buffer(); - commands.acquire(this); + commands.acquire(fvkmemory::resource_ptr::cast(this)); VkBufferImageCopy copyRegion = { .bufferOffset = {}, @@ -503,25 +465,24 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt transitionLayout(&commands, transitionRange, newLayout); - vkCmdCopyBufferToImage(cmdbuf, stage->buffer, state->mTextureImage, newVkLayout, 1, ©Region); + vkCmdCopyBufferToImage(cmdbuf, stage->buffer, mState->mTextureImage, newVkLayout, 1, ©Region); transitionLayout(&commands, transitionRange, nextLayout); } void VulkanTexture::updateImageWithBlit(const PixelBufferDescriptor& hostData, uint32_t width, uint32_t height, uint32_t depth, uint32_t miplevel) { - auto* const state = getSharedState(); void* mapped = nullptr; VulkanStageImage const* stage - = state->mStagePool.acquireImage(hostData.format, hostData.type, width, height); - vmaMapMemory(state->mAllocator, stage->memory, &mapped); + = mState->mStagePool.acquireImage(hostData.format, hostData.type, width, height); + vmaMapMemory(mState->mAllocator, stage->memory, &mapped); memcpy(mapped, hostData.buffer, hostData.size); - vmaUnmapMemory(state->mAllocator, stage->memory); - vmaFlushAllocation(state->mAllocator, stage->memory, 0, hostData.size); + vmaUnmapMemory(mState->mAllocator, stage->memory); + vmaFlushAllocation(mState->mAllocator, stage->memory, 0, hostData.size); - VulkanCommandBuffer& commands = state->mCommands->get(); + VulkanCommandBuffer& commands = mState->mCommands->get(); VkCommandBuffer const cmdbuf = commands.buffer(); - commands.acquire(this); + commands.acquire(fvkmemory::resource_ptr::cast(this)); // TODO: support blit-based format conversion for 3D images and cubemaps. const int layer = 0; @@ -544,14 +505,13 @@ void VulkanTexture::updateImageWithBlit(const PixelBufferDescriptor& hostData, u transitionLayout(&commands, range, newLayout); vkCmdBlitImage(cmdbuf, stage->image, imgutil::getVkLayout(VulkanLayout::TRANSFER_SRC), - state->mTextureImage, imgutil::getVkLayout(newLayout), 1, blitRegions, VK_FILTER_NEAREST); + mState->mTextureImage, imgutil::getVkLayout(newLayout), 1, blitRegions, VK_FILTER_NEAREST); transitionLayout(&commands, range, oldLayout); } VulkanLayout VulkanTexture::getDefaultLayout() const { - auto* const state = getSharedState(); - return state->mDefaultLayout; + return mState->mDefaultLayout; } VkImageView VulkanTexture::getAttachmentView(VkImageSubresourceRange range) { @@ -570,42 +530,43 @@ VkImageView VulkanTexture::getViewForType(VkImageSubresourceRange const& range, VkImageView VulkanTexture::getImageView(VkImageSubresourceRange range, VkImageViewType viewType, VkComponentMapping swizzle) { - auto* const state = getSharedState(); VulkanTextureState::ImageViewKey const key{ range, viewType, swizzle }; - auto iter = state->mCachedImageViews.find(key); - if (iter != state->mCachedImageViews.end()) { + auto iter = mState->mCachedImageViews.find(key); + if (iter != mState->mCachedImageViews.end()) { return iter->second; } VkImageViewCreateInfo viewInfo = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .pNext = nullptr, .flags = 0, - .image = state->mTextureImage, + .image = mState->mTextureImage, .viewType = viewType, - .format = state->mVkFormat, + .format = mState->mVkFormat, .components = swizzle, .subresourceRange = range, }; VkImageView imageView; - vkCreateImageView(state->mDevice, &viewInfo, VKALLOC, &imageView); - state->mCachedImageViews.emplace(key, imageView); + vkCreateImageView(mState->mDevice, &viewInfo, VKALLOC, &imageView); + mState->mCachedImageViews.emplace(key, imageView); return imageView; } VkImageAspectFlags VulkanTexture::getImageAspect() const { // Helper function in VulkanUtility - auto* const state = getSharedState(); - return filament::backend::getImageAspect(state->mVkFormat); + return filament::backend::getImageAspect(mState->mVkFormat); } bool VulkanTexture::transitionLayout(VulkanCommandBuffer* commands, VkImageSubresourceRange const& range, VulkanLayout newLayout) { - return transitionLayout(commands->buffer(), range, newLayout); + if (transitionLayout(commands->buffer(), range, newLayout)) { + commands->acquire(fvkmemory::resource_ptr::cast(this)); + return true; + } + return false; } bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceRange const& range, VulkanLayout newLayout) { - auto* const state = getSharedState(); VulkanLayout const oldLayout = getLayout(range.baseArrayLayer, range.baseMipLevel); uint32_t const firstLayer = range.baseArrayLayer; @@ -636,7 +597,7 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR continue; } hasTransitions = hasTransitions || imgutil::transitionLayout(cmdbuf, { - .image = state->mTextureImage, + .image = mState->mTextureImage, .oldLayout = layout, .newLayout = newLayout, .subresources = { @@ -651,7 +612,7 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR } } else if (newLayout != oldLayout) { hasTransitions = imgutil::transitionLayout(cmdbuf, { - .image = state->mTextureImage, + .image = mState->mTextureImage, .oldLayout = oldLayout, .newLayout = newLayout, .subresources = range, @@ -684,7 +645,6 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR void VulkanTexture::samplerToAttachmentBarrier(VulkanCommandBuffer* commands, VkImageSubresourceRange const& range) { VkCommandBuffer const cmdbuf = commands->buffer(); - auto* const state = getSharedState(); VkImageLayout const layout = imgutil::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel)); VkImageMemoryBarrier barrier = { @@ -696,7 +656,7 @@ void VulkanTexture::samplerToAttachmentBarrier(VulkanCommandBuffer* commands, .newLayout = layout, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = state->mTextureImage, + .image = mState->mTextureImage, .subresourceRange = range, }; vkCmdPipelineBarrier(cmdbuf, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, @@ -708,7 +668,6 @@ void VulkanTexture::samplerToAttachmentBarrier(VulkanCommandBuffer* commands, void VulkanTexture::attachmentToSamplerBarrier(VulkanCommandBuffer* commands, VkImageSubresourceRange const& range) { VkCommandBuffer const cmdbuf = commands->buffer(); - auto* const state = getSharedState(); VkImageLayout const layout = imgutil::getVkLayout(getLayout(range.baseArrayLayer, range.baseMipLevel)); VkImageMemoryBarrier barrier = { @@ -719,7 +678,7 @@ void VulkanTexture::attachmentToSamplerBarrier(VulkanCommandBuffer* commands, .newLayout = layout, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = state->mTextureImage, + .image = mState->mTextureImage, .subresourceRange = range, }; vkCmdPipelineBarrier(cmdbuf, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, @@ -727,7 +686,6 @@ void VulkanTexture::attachmentToSamplerBarrier(VulkanCommandBuffer* commands, } void VulkanTexture::setLayout(VkImageSubresourceRange const& range, VulkanLayout newLayout) { - auto* const state = getSharedState(); uint32_t const firstLayer = range.baseArrayLayer; uint32_t const lastLayer = firstLayer + range.layerCount; uint32_t const firstLevel = range.baseMipLevel; @@ -740,34 +698,32 @@ void VulkanTexture::setLayout(VkImageSubresourceRange const& range, VulkanLayout for (uint32_t layer = firstLayer; layer < lastLayer; ++layer) { uint32_t const first = (layer << 16) | firstLevel; uint32_t const last = (layer << 16) | lastLevel; - state->mSubresourceLayouts.clear(first, last); + mState->mSubresourceLayouts.clear(first, last); } } else { for (uint32_t layer = firstLayer; layer < lastLayer; ++layer) { uint32_t const first = (layer << 16) | firstLevel; uint32_t const last = (layer << 16) | lastLevel; - state->mSubresourceLayouts.add(first, last, newLayout); + mState->mSubresourceLayouts.add(first, last, newLayout); } } } VulkanLayout VulkanTexture::getLayout(uint32_t layer, uint32_t level) const { assert_invariant(level <= 0xffff && layer <= 0xffff); - auto* const state = getSharedState(); const uint32_t key = (layer << 16) | level; - if (!state->mSubresourceLayouts.has(key)) { + if (!mState->mSubresourceLayouts.has(key)) { return VulkanLayout::UNDEFINED; } - return state->mSubresourceLayouts.get(key); + return mState->mSubresourceLayouts.get(key); } #if FVK_ENABLED(FVK_DEBUG_TEXTURE) void VulkanTexture::print() const { - auto* const state = getSharedState(); uint32_t const firstLayer = 0; - uint32_t const lastLayer = firstLayer + state->mFullViewRange.layerCount; + uint32_t const lastLayer = firstLayer + mState->mFullViewRange.layerCount; uint32_t const firstLevel = 0; - uint32_t const lastLevel = firstLevel + state->mFullViewRange.levelCount; + uint32_t const lastLevel = firstLevel + mState->mFullViewRange.levelCount; for (uint32_t layer = firstLayer; layer < lastLayer; ++layer) { for (uint32_t level = firstLevel; level < lastLevel; ++level) { @@ -776,16 +732,16 @@ void VulkanTexture::print() const { layer < (mPrimaryViewRange.baseArrayLayer + mPrimaryViewRange.layerCount) && level >= mPrimaryViewRange.baseMipLevel && level < (mPrimaryViewRange.baseMipLevel + mPrimaryViewRange.levelCount); - FVK_LOGD << "[" << state->mTextureImage << "]: (" << layer << "," << level + FVK_LOGD << "[" << mState->mTextureImage << "]: (" << layer << "," << level << ")=" << getLayout(layer, level) << " primary=" << primary << utils::io::endl; } } - for (auto view: state->mCachedImageViews) { + for (auto view: mState->mCachedImageViews) { auto& range = view.first.range; - FVK_LOGD << "[" << state->mTextureImage << ", imageView=" << view.second << "]=>" + FVK_LOGD << "[" << mState->mTextureImage << ", imageView=" << view.second << "]=>" << " (" << range.baseArrayLayer << "," << range.baseMipLevel << ")" << " count=(" << range.layerCount << "," << range.levelCount << ")" << " aspect=" << range.aspectMask << " viewType=" << view.first.type diff --git a/filament/backend/src/vulkan/VulkanTexture.h b/filament/backend/src/vulkan/VulkanTexture.h index 5165b1cec78..e6f9e38ad40 100644 --- a/filament/backend/src/vulkan/VulkanTexture.h +++ b/filament/backend/src/vulkan/VulkanTexture.h @@ -20,8 +20,9 @@ #include "DriverBase.h" #include "VulkanBuffer.h" -#include "VulkanResources.h" #include "VulkanImageUtility.h" +#include "vulkan/memory/Resource.h" +#include "vulkan/memory/ResourcePointer.h" #include #include @@ -30,13 +31,13 @@ namespace filament::backend { -class VulkanResourceAllocator; - -struct VulkanTextureState : public VulkanResource { +struct VulkanTextureState : public fvkmemory::Resource { VulkanTextureState(VkDevice device, VmaAllocator allocator, VulkanCommands* commands, VulkanStagePool& stagePool, VkFormat format, VkImageViewType viewType, uint8_t levels, uint8_t layerCount, VulkanLayout defaultLayout, bool isProtected); + ~VulkanTextureState(); + struct ImageViewKey { VkImageSubresourceRange range; // 4 * 5 bytes VkImageViewType type; // 4 bytes @@ -58,10 +59,8 @@ struct VulkanTextureState : public VulkanResource { using ImageViewHash = utils::hash::MurmurHashFn; - uint32_t refs = 1; - // The texture with the sidecar owns the sidecar. - std::unique_ptr mSidecarMSAA; + fvkmemory::resource_ptr mSidecarMSAA; VkDeviceMemory mTextureImageMemory = VK_NULL_HANDLE; VkFormat const mVkFormat; @@ -83,37 +82,32 @@ struct VulkanTextureState : public VulkanResource { bool mIsTransientAttachment; }; - -struct VulkanTexture : public HwTexture, VulkanResource { +struct VulkanTexture : public HwTexture, fvkmemory::Resource { // Standard constructor for user-facing textures. VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, VulkanContext const& context, - VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, - SamplerType target, uint8_t levels, - TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth, - TextureUsage tusage, VulkanStagePool& stagePool, bool heapAllocated = false); + VmaAllocator allocator, fvkmemory::ResourceManager* resourceManager, + VulkanCommands* commands, SamplerType target, uint8_t levels, TextureFormat tformat, + uint8_t samples, uint32_t w, uint32_t h, uint32_t depth, TextureUsage tusage, + VulkanStagePool& stagePool); // Specialized constructor for internally created textures (e.g. from a swap chain) // The texture will never destroy the given VkImage, but it does manages its subresources. - VulkanTexture(VkDevice device, VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, - VkImage image, + VulkanTexture(VkDevice device, VmaAllocator allocator, + fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image, VkFormat format, uint8_t samples, uint32_t width, uint32_t height, TextureUsage tusage, - VulkanStagePool& stagePool, bool heapAllocated = false); + VulkanStagePool& stagePool); // Constructor for creating a texture view for wrt specific mip range VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, - VulkanTexture const* src, uint8_t baseLevel, uint8_t levelCount); + fvkmemory::resource_ptr src, uint8_t baseLevel, uint8_t levelCount); // Constructor for creating a texture view for swizzle. VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands, - VulkanResourceAllocator* handleAllocator, - VulkanTexture const* src, VkComponentMapping swizzle); + fvkmemory::resource_ptr src, VkComponentMapping swizzle); - ~VulkanTexture(); + ~VulkanTexture() = default; // Uploads data into a subregion of a 2D or 3D texture. void updateImage(const PixelBufferDescriptor& data, uint32_t width, uint32_t height, @@ -121,16 +115,14 @@ struct VulkanTexture : public HwTexture, VulkanResource { // Returns the primary image view, which is used for shader sampling. VkImageView getPrimaryImageView() { - VulkanTextureState* state = getSharedState(); - return getImageView(mPrimaryViewRange, state->mViewType, mSwizzle); + return getImageView(mPrimaryViewRange, mState->mViewType, mSwizzle); } VkImageViewType getViewType() const { - VulkanTextureState const* state = getSharedState(); - return state->mViewType; + return mState->mViewType; } - VkImageSubresourceRange getPrimaryViewRange() const { return mPrimaryViewRange; } + VkImageSubresourceRange const& getPrimaryViewRange() const { return mPrimaryViewRange; } VulkanLayout getPrimaryImageLayout() const { return getLayout(mPrimaryViewRange.baseArrayLayer, mPrimaryViewRange.baseMipLevel); @@ -156,34 +148,28 @@ struct VulkanTexture : public HwTexture, VulkanResource { VkImageView getViewForType(VkImageSubresourceRange const& range, VkImageViewType type); VkFormat getVkFormat() const { - VulkanTextureState const* state = getSharedState(); - return state->mVkFormat; + return mState->mVkFormat; } VkImage getVkImage() const { - VulkanTextureState const* state = getSharedState(); - return state->mTextureImage; + return mState->mTextureImage; } VulkanLayout getLayout(uint32_t layer, uint32_t level) const; - void setSidecar(VulkanTexture* sidecar) { - VulkanTextureState* state = getSharedState(); - state->mSidecarMSAA.reset(sidecar); + void setSidecar(fvkmemory::resource_ptr sidecar) { + mState->mSidecarMSAA = sidecar; } - VulkanTexture* getSidecar() const { - VulkanTextureState const* state = getSharedState(); - return state->mSidecarMSAA.get(); + fvkmemory::resource_ptr getSidecar() const { + return mState->mSidecarMSAA; } bool isTransientAttachment() const { - VulkanTextureState const* state = getSharedState(); - return state->mIsTransientAttachment; + return mState->mIsTransientAttachment; } bool getIsProtected() const { - VulkanTextureState const* state = getSharedState(); - return state->mIsProtected; + return mState->mIsProtected; } bool transitionLayout(VulkanCommandBuffer* commands, VkImageSubresourceRange const& range, @@ -211,9 +197,6 @@ struct VulkanTexture : public HwTexture, VulkanResource { #endif private: - VulkanTextureState* getSharedState(); - VulkanTextureState const* getSharedState() const; - // Gets or creates a cached VkImageView for a range of miplevels, array layers, viewType, and // swizzle (or not). VkImageView getImageView(VkImageSubresourceRange range, VkImageViewType viewType, @@ -222,9 +205,7 @@ struct VulkanTexture : public HwTexture, VulkanResource { void updateImageWithBlit(const PixelBufferDescriptor& hostData, uint32_t width, uint32_t height, uint32_t depth, uint32_t miplevel); - VulkanResourceAllocator* const mAllocator; - - Handle mState; + fvkmemory::resource_ptr mState; // Track the range of subresources that define the "primary" image view, which is the special // image view that gets bound to an actual texture sampler. diff --git a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp b/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp index 0533b58e0f4..19aa989b8c0 100644 --- a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp +++ b/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.cpp @@ -16,11 +16,11 @@ #include "VulkanDescriptorSetManager.h" +#include #include #include #include #include -#include #include #include @@ -274,7 +274,7 @@ class VulkanDescriptorSetManager::DescriptorInfinitePool { DescriptorInfinitePool(VkDevice device) : mDevice(device) {} - VkDescriptorSet obtainSet(VulkanDescriptorSetLayout* layout) { + VkDescriptorSet obtainSet(fvkmemory::resource_ptr layout) { auto const vklayout = layout->getVkLayout(); DescriptorPool* sameTypePool = nullptr; for (auto& pool: mPools) { @@ -325,13 +325,12 @@ class VulkanDescriptorSetManager::DescriptorSetLayoutManager { DescriptorSetLayoutManager(VkDevice device) : mDevice(device) {} - VkDescriptorSetLayout getVkLayout(VulkanDescriptorSetLayout* layout) { - auto const& bitmasks = layout->bitmask; + VkDescriptorSetLayout getVkLayout(VulkanDescriptorSetLayout::Bitmask const& bitmasks) { if (auto itr = mVkLayouts.find(bitmasks); itr != mVkLayouts.end()) { return itr->second; } - auto vklayout = createLayout(mDevice, layout->bitmask); - mVkLayouts[layout->bitmask] = vklayout; + auto vklayout = createLayout(mDevice, bitmasks); + mVkLayouts[bitmasks] = vklayout; return vklayout; } @@ -347,10 +346,11 @@ class VulkanDescriptorSetManager::DescriptorSetLayoutManager { mVkLayouts; }; + VulkanDescriptorSetManager::VulkanDescriptorSetManager(VkDevice device, - VulkanResourceAllocator* resourceAllocator) + fvkmemory::ResourceManager* resourceManager) : mDevice(device), - mResourceAllocator(resourceAllocator), + mResourceManager(resourceManager), mLayoutManager(std::make_unique(device)), mDescriptorPool(std::make_unique(device)) {} @@ -359,18 +359,20 @@ VulkanDescriptorSetManager::~VulkanDescriptorSetManager() = default; void VulkanDescriptorSetManager::terminate() noexcept{ mLayoutManager.reset(); mDescriptorPool.reset(); + clearHistory(); } // bind() is not really binding the set but just stashing until we have all the info // (pipelinelayout). -void VulkanDescriptorSetManager::bind(uint8_t setIndex, VulkanDescriptorSet* set, +void VulkanDescriptorSetManager::bind(uint8_t setIndex, + fvkmemory::resource_ptr set, backend::DescriptorSetOffsetArray&& offsets) { set->setOffsets(std::move(offsets)); mStashedSets[setIndex] = set; } void VulkanDescriptorSetManager::unbind(uint8_t setIndex) { - mStashedSets[setIndex] = nullptr; + mStashedSets[setIndex] = {}; } void VulkanDescriptorSetManager::commit(VulkanCommandBuffer* commands, @@ -412,14 +414,14 @@ void VulkanDescriptorSetManager::commit(VulkanCommandBuffer* commands, }; } -void VulkanDescriptorSetManager::updateBuffer(VulkanDescriptorSet* set, uint8_t binding, - VulkanBufferObject* bufferObject, VkDeviceSize offset, VkDeviceSize size) noexcept { +void VulkanDescriptorSetManager::updateBuffer(fvkmemory::resource_ptr set, + uint8_t binding, fvkmemory::resource_ptr bufferObject, + VkDeviceSize offset, VkDeviceSize size) noexcept { VkDescriptorBufferInfo const info = { .buffer = bufferObject->buffer.getGpuBuffer(), .offset = offset, .range = size, }; - VkDescriptorType type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; if (set->dynamicUboMask.test(binding)) { @@ -438,8 +440,9 @@ void VulkanDescriptorSetManager::updateBuffer(VulkanDescriptorSet* set, uint8_t set->acquire(bufferObject); } -void VulkanDescriptorSetManager::updateSampler(VulkanDescriptorSet* set, uint8_t binding, - VulkanTexture* texture, VkSampler sampler) noexcept { +void VulkanDescriptorSetManager::updateSampler(fvkmemory::resource_ptr set, + uint8_t binding, fvkmemory::resource_ptr texture, + VkSampler sampler) noexcept { VkDescriptorImageInfo info{ .sampler = sampler, }; @@ -469,38 +472,35 @@ void VulkanDescriptorSetManager::updateSampler(VulkanDescriptorSet* set, uint8_t set->acquire(texture); } -void VulkanDescriptorSetManager::updateInputAttachment(VulkanDescriptorSet* set, - VulkanAttachment attachment) noexcept { +void VulkanDescriptorSetManager::updateInputAttachment( + fvkmemory::resource_ptr set, + VulkanAttachment const& attachment) noexcept { // TOOD: fill-in this region } -void VulkanDescriptorSetManager::createSet(Handle handle, - VulkanDescriptorSetLayout* layout) { +fvkmemory::resource_ptr VulkanDescriptorSetManager::createSet( + Handle handle, fvkmemory::resource_ptr layout) { auto const vkSet = mDescriptorPool->obtainSet(layout); auto const& count = layout->count; auto const vklayout = layout->getVkLayout(); - mResourceAllocator->construct(handle, mResourceAllocator, vkSet, + return fvkmemory::resource_ptr::make(mResourceManager, handle, vkSet, layout->bitmask.dynamicUbo, layout->count.dynamicUbo, - [vkSet, count, vklayout, this](VulkanDescriptorSet* set) { - eraseSetFromHistory(set); - mDescriptorPool->recycle(count, vklayout, vkSet); + [vkSet, count, vklayout, this](VulkanDescriptorSet*) { + // Note that mDescriptorPool could be gone due to terminate (when the backend shuts + // down). + if (mDescriptorPool) { + mDescriptorPool->recycle(count, vklayout, vkSet); + } }); } -void VulkanDescriptorSetManager::destroySet(Handle handle) { -} - -void VulkanDescriptorSetManager::initVkLayout(VulkanDescriptorSetLayout* layout) { - layout->setVkLayout(mLayoutManager->getVkLayout(layout)); +void VulkanDescriptorSetManager::initVkLayout( + fvkmemory::resource_ptr layout) { + layout->setVkLayout(mLayoutManager->getVkLayout(layout->bitmask)); } -void VulkanDescriptorSetManager::eraseSetFromHistory(VulkanDescriptorSet* set) { - for (uint8_t i = 0; i < mStashedSets.size(); ++i) { - if (mStashedSets[i] == set) { - mStashedSets[i] = nullptr; - } - } +void VulkanDescriptorSetManager::clearHistory() { + mStashedSets = {}; } - } // namespace filament::backend diff --git a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.h b/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.h index 2735e5062b1..db3c612de02 100644 --- a/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.h +++ b/filament/backend/src/vulkan/caching/VulkanDescriptorSetManager.h @@ -17,9 +17,10 @@ #ifndef TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETMANAGER_H #define TNT_FILAMENT_BACKEND_CACHING_VULKANDESCRIPTORSETMANAGER_H -#include -#include -#include +#include "vulkan/VulkanHandles.h" +#include "vulkan/VulkanTexture.h" +#include "vulkan/VulkanUtility.h" +#include "vulkan/memory/ResourcePointer.h" #include #include @@ -46,46 +47,45 @@ class VulkanDescriptorSetManager { using DescriptorSetLayoutArray = VulkanDescriptorSetLayout::DescriptorSetLayoutArray; - VulkanDescriptorSetManager(VkDevice device, VulkanResourceAllocator* resourceAllocator); + VulkanDescriptorSetManager(VkDevice device, fvkmemory::ResourceManager* resourceManager); ~VulkanDescriptorSetManager(); void terminate() noexcept; - void updateBuffer(VulkanDescriptorSet* set, uint8_t binding, - VulkanBufferObject* bufferObject, VkDeviceSize offset, VkDeviceSize size) noexcept; + void updateBuffer(fvkmemory::resource_ptr set, uint8_t binding, + fvkmemory::resource_ptr bufferObject, VkDeviceSize offset, + VkDeviceSize size) noexcept; - void updateSampler(VulkanDescriptorSet* set, uint8_t binding, - VulkanTexture* texture, VkSampler sampler) noexcept; + void updateSampler(fvkmemory::resource_ptr set, uint8_t binding, + fvkmemory::resource_ptr texture, VkSampler sampler) noexcept; - void updateInputAttachment(VulkanDescriptorSet* set, VulkanAttachment attachment) noexcept; + void updateInputAttachment(fvkmemory::resource_ptr set, + VulkanAttachment const& attachment) noexcept; - void bind(uint8_t setIndex, VulkanDescriptorSet* set, backend::DescriptorSetOffsetArray&& offsets); + void bind(uint8_t setIndex, fvkmemory::resource_ptr set, + backend::DescriptorSetOffsetArray&& offsets); void unbind(uint8_t setIndex); void commit(VulkanCommandBuffer* commands, VkPipelineLayout pipelineLayout, DescriptorSetMask const& setMask); - void setPlaceHolders(VkSampler sampler, VulkanTexture* texture, - VulkanBufferObject* bufferObject) noexcept; + fvkmemory::resource_ptr createSet(Handle handle, + fvkmemory::resource_ptr layout); - void createSet(Handle handle, VulkanDescriptorSetLayout* layout); + void initVkLayout(fvkmemory::resource_ptr layout); - void destroySet(Handle handle); - - void initVkLayout(VulkanDescriptorSetLayout* layout); + void clearHistory(); private: class DescriptorSetLayoutManager; class DescriptorInfinitePool; - void eraseSetFromHistory(VulkanDescriptorSet* set); - using DescriptorSetArray = - std::array; - + std::array, UNIQUE_DESCRIPTOR_SET_COUNT>; + VkDevice mDevice; - VulkanResourceAllocator* mResourceAllocator; + fvkmemory::ResourceManager* mResourceManager; std::unique_ptr mLayoutManager; std::unique_ptr mDescriptorPool; std::pair mInputAttachment; diff --git a/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.cpp b/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.cpp index 09a84d33993..256a616aa2e 100644 --- a/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.cpp +++ b/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.cpp @@ -16,12 +16,11 @@ #include "VulkanPipelineLayoutCache.h" -#include - namespace filament::backend { VkPipelineLayout VulkanPipelineLayoutCache::getLayout( - DescriptorSetLayoutArray const& descriptorSetLayouts, VulkanProgram* program) { + DescriptorSetLayoutArray const& descriptorSetLayouts, + fvkmemory::resource_ptr program) { PipelineLayoutKey key = {}; uint8_t descSetLayoutCount = 0; key.descSetLayouts = descriptorSetLayouts; @@ -40,13 +39,13 @@ VkPipelineLayout VulkanPipelineLayoutCache::getLayout( for (uint8_t i = 0; i < pushConstantRangeCount; ++i) { auto const& range = pushConstantRanges[i]; auto& pushConstant = key.pushConstant[i]; - if (range.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) { + if (range.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) { pushConstant.stage = static_cast(ShaderStage::VERTEX); } - if (range.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) { + if (range.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) { pushConstant.stage = static_cast(ShaderStage::FRAGMENT); } - if (range.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) { + if (range.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) { pushConstant.stage = static_cast(ShaderStage::COMPUTE); } pushConstant.size = range.size; diff --git a/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.h b/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.h index 01d7122e201..212ad60b0cf 100644 --- a/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.h +++ b/filament/backend/src/vulkan/caching/VulkanPipelineLayoutCache.h @@ -30,7 +30,7 @@ class VulkanPipelineLayoutCache { public: using DescriptorSetLayoutArray = VulkanDescriptorSetLayout::DescriptorSetLayoutArray; - VulkanPipelineLayoutCache(VkDevice device, VulkanResourceAllocator* allocator) + VulkanPipelineLayoutCache(VkDevice device) : mDevice(device), mTimestamp(0) {} @@ -56,7 +56,7 @@ class VulkanPipelineLayoutCache { // A pipeline layout depends on the descriptor set layout and the push constant ranges, which // are described in the program. VkPipelineLayout getLayout(DescriptorSetLayoutArray const& descriptorSetLayouts, - VulkanProgram* program); + fvkmemory::resource_ptr program); private: using Timestamp = uint64_t; diff --git a/filament/backend/src/vulkan/memory/ResourceManager.cpp b/filament/backend/src/vulkan/memory/ResourceManager.cpp index db938d61b9f..c29b959bd65 100644 --- a/filament/backend/src/vulkan/memory/ResourceManager.cpp +++ b/filament/backend/src/vulkan/memory/ResourceManager.cpp @@ -22,7 +22,7 @@ namespace filament::backend::fvkmemory { namespace { -#if FVK_ENABLED(FVK_DEBUG_ALLOCATION) +#if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK) uint32_t COUNTER[(size_t) ResourceType::UNDEFINED_TYPE] = {}; #endif } @@ -105,20 +105,20 @@ void ResourceManager::destroyWithType(ResourceType type, HandleId id) { case ResourceType::UNDEFINED_TYPE: break; } -#if FVK_ENABLED(FVK_DEBUG_ALLOCATION) +#if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK) COUNTER[(size_t) type]--; #endif } void ResourceManager::traceConstruction(ResourceType type, HandleId id) { -#if FVK_ENABLED(FVK_DEBUG_ALLOCATION) +#if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK) assert_invariant(type != ResourceType::UNDEFINED_TYPE); COUNTER[(size_t) type]++; #endif } void ResourceManager::print() const noexcept { -#if FVK_ENABLED(FVK_DEBUG_ALLOCATION) +#if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK) utils::slog.e << "-------------------" << utils::io::endl; for (size_t i = 0; i < (size_t) ResourceType::UNDEFINED_TYPE; ++i) { utils::slog.e <<" " << getTypeStr((ResourceType) i) << "=" << COUNTER[i] << utils::io::endl; diff --git a/filament/backend/src/vulkan/memory/ResourceManager.h b/filament/backend/src/vulkan/memory/ResourceManager.h index fa2b62da260..fd2fef054bb 100644 --- a/filament/backend/src/vulkan/memory/ResourceManager.h +++ b/filament/backend/src/vulkan/memory/ResourceManager.h @@ -95,7 +95,6 @@ class ResourceManager { AllocatorImpl mHandleAllocatorImpl; using GcList = std::vector>; - utils::Mutex mThreadSafeGcListMutex; GcList mThreadSafeGcList; GcList mGcList;