> The Vulkan::Graphics class manages all command pools.
> Creation of command pools is no longer exposed.
> Command pools are lazily created when command buffer creation is required and are stored in a map using the calling thread's ID as the key.
> All the command pools allocated by the Vulkan::Graphics class are using the eResetCommanBuffer flag to allow for explicit command buffer resetting.
Change-Id: I92a275cf591b3a85c98d596f977b9ec4ef4211c6
//apiCommand->PreparePipeline();
- if( !mCommandPool )
- {
- mCommandPool = Vulkan::CommandPool::New( mGraphics );
- }
// start new command buffer
- auto cmdbuf = mCommandPool->NewCommandBuffer( false );
+ auto cmdbuf = mGraphics.CreateCommandBuffer( false );//mCommandPool->NewCommandBuffer( false );
cmdbuf->Reset();
cmdbuf->Begin( vk::CommandBufferUsageFlagBits::eRenderPassContinue );
cmdbuf->BindGraphicsPipeline( apiCommand->GetPipeline() );
class CommandPool : public VkManaged
{
-public:
-
- /**
- *
- * @param graphics
- * @param createInfo
- * @return
- */
- static RefCountedCommandPool New( Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo );
+ friend class Graphics;
- /**
- *
- * @param graphics
- * @return
- */
- static RefCountedCommandPool New( Graphics& graphics );
+public:
~CommandPool() override;
CommandPool( Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo );
+ /**
+ *
+ * @param graphics
+ * @param createInfo
+ * @return
+ */
+ static RefCountedCommandPool New( Graphics& graphics, const vk::CommandPoolCreateInfo& createInfo );
+
+ /**
+ *
+ * @param graphics
+ * @return
+ */
+ static RefCountedCommandPool New( Graphics& graphics );
+
struct Impl;
std::unique_ptr<Impl> mImpl;
uint32_t GetAttachmentCount( AttachmentType type ) const
{
- std::vector<RefCountedImageView> retval{};
switch( type )
{
case AttachmentType::COLOR:
.setLayerCount( 1 )
.setBaseArrayLayer( 0 ) );
- if(!mCommandPool)
- {
- mCommandPool = CommandPool::New(mGraphics);
- mCommandBuffer = mCommandPool->NewCommandBuffer(true);
- }
- else
- {
- mCommandBuffer->Reset();
- }
-
- mCommandBuffer->Begin(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
+ auto commandBuffer = mGraphics.CreateCommandBuffer( true );
+
+ commandBuffer->Begin(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
// change layout
- auto barrier = std::vector<vk::ImageMemoryBarrier>{mCommandBuffer->ImageLayoutTransitionBarrier(
+ auto barrier = std::vector<vk::ImageMemoryBarrier>{commandBuffer->ImageLayoutTransitionBarrier(
mImage, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eTransferDstOptimal, vk::ImageAspectFlagBits::eColor )};
// change layout to prepare image to transfer data
- mCommandBuffer->PipelineBarrier(
+ commandBuffer->PipelineBarrier(
vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, {barrier} );
// copy image
- mCommandBuffer->CopyBufferToImage( buffer, mImage, vk::ImageLayout::eTransferDstOptimal, {copy} );
+ commandBuffer->CopyBufferToImage( buffer, mImage, vk::ImageLayout::eTransferDstOptimal, {copy} );
// change layout to shader read-only optimal
- mCommandBuffer->PipelineBarrier(
+ commandBuffer->PipelineBarrier(
vk::PipelineStageFlagBits::eVertexShader,
vk::PipelineStageFlagBits::eVertexShader,
{},
{},
{},
- {mCommandBuffer->ImageLayoutTransitionBarrier(
+ {commandBuffer->ImageLayoutTransitionBarrier(
mImage, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageAspectFlagBits::eColor )} );
- mCommandBuffer->End();
+ commandBuffer->End();
// submit and wait till image is uploaded so temporary buffer can be destroyed safely
auto fence = mGraphics.CreateFence({});
- VkAssert(mGraphics.Submit( mGraphics.GetGraphicsQueue( 0u ), { SubmissionData{}.SetCommandBuffers( { mCommandBuffer } ) }, fence ));
+ VkAssert(mGraphics.Submit( mGraphics.GetGraphicsQueue( 0u ), { SubmissionData{}.SetCommandBuffers( { commandBuffer } ) }, fence ));
VkAssert(mGraphics.WaitForFence(fence, std::numeric_limits<uint32_t>::max()));
return true;
}
RefCountedImageView mImageView;
RefCountedSampler mSampler;
- // command pools should be 'per-thread' so they can be safely
- // used withing one single thread before submitting them
- RefCountedCommandPool mCommandPool;
- RefCountedCommandBuffer mCommandBuffer; // primary buffer, executed independent
-
// layouts
vk::ImageLayout mOldLayout;
vk::ImageLayout mNewLayout;
//"VK_LAYER_LUNARG_monitor", // monitor
"VK_LAYER_LUNARG_swapchain", // swapchain
"VK_LAYER_GOOGLE_threading", // threading
- "VK_LAYER_LUNARG_api_dump", // api
+ //"VK_LAYER_LUNARG_api_dump", // api
"VK_LAYER_LUNARG_object_tracker", // objects
"VK_LAYER_LUNARG_core_validation", // core
"VK_LAYER_GOOGLE_unique_objects", // unique objects
NotImplemented()
}
-RefCountedCommandPool Graphics::CreateCommandPool( const vk::CommandPoolCreateInfo& info )
-{
- //TODO: move the logic of creation here
- //TODO: add the object to the cache
- return CommandPool::New( *this,
- vk::CommandPoolCreateInfo{}.setQueueFamilyIndex( 0u )
- .setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer ));
-}
-
-RefCountedCommandBuffer Graphics::CreateCommandBuffer()
-{
- NotImplemented()
-}
-
-std::vector< RefCountedCommandBuffer > Graphics::CreateCommandBuffers()
-{
- NotImplemented()
-}
-
RefCountedGpuMemoryBlock Graphics::CreateGpuMemoryBlock()
{
NotImplemented()
return refCountedSampler;
}
+
+RefCountedCommandBuffer Graphics::CreateCommandBuffer( bool primary )
+{
+ auto commandPool = FindCommandPool( std::this_thread::get_id() );
+
+ return commandPool->NewCommandBuffer( primary );
+}
// --------------------------------------------------------------------------------------------------------------
// Actions ------------------------------------------------------------------------------------------------------
void Graphics::AddCommandPool( Handle< CommandPool > pool )
{
std::lock_guard< std::mutex > lock{ mMutex };
- mResourceCache->AddCommandPool( std::move( pool ));
+ mResourceCache->AddCommandPool( std::this_thread::get_id(), std::move( pool ));
}
void Graphics::AddDescriptorPool( Handle< DescriptorPool > pool )
.setPpEnabledLayerNames(validationLayers.data());
#if defined(DEBUG_ENABLED)
- if( ! getenv("LOG_VULKAN") )
- {
- info.setEnabledLayerCount(0);
- }
+// if( ! getenv("LOG_VULKAN") )
+// {
+// info.setEnabledLayerCount(0);
+// }
#endif
mInstance = VkAssert(vk::createInstance(info, *mAllocator));
return retval;
}
+RefCountedCommandPool Graphics::FindCommandPool( std::thread::id )
+{
+ RefCountedCommandPool commandPool;
+ {
+ std::lock_guard< std::mutex > lock{ mMutex };
+ commandPool = mResourceCache->FindCommandPool( std::this_thread::get_id() );
+ }
+
+ if( !commandPool )
+ {
+ auto&& createInfo = vk::CommandPoolCreateInfo{}.setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer );
+ commandPool = CommandPool::New( *this, createInfo);
+ }
+
+ return commandPool;
+}
+
} // namespace Vulkan
} // namespace Graphics
} // namespace Dali
RefCountedDescriptorPool CreateDescriptorPool();
- RefCountedCommandPool CreateCommandPool( const vk::CommandPoolCreateInfo& info );
-
- RefCountedCommandBuffer CreateCommandBuffer();
-
- std::vector< RefCountedCommandBuffer > CreateCommandBuffers();
-
RefCountedGpuMemoryBlock CreateGpuMemoryBlock();
RefCountedDescriptorSet CreateDescriptorSet();
RefCountedSampler CreateSampler( const vk::SamplerCreateInfo& samplerCreateInfo );
+ RefCountedCommandBuffer CreateCommandBuffer( bool primary );
+
public: // Actions
vk::Result WaitForFence( RefCountedFence fence, uint32_t timeout = std::numeric_limits< uint32_t >::max() );
std::vector< const char* > PrepareDefaultInstanceExtensions();
+ RefCountedCommandPool FindCommandPool( std::thread::id );
+
private: // Members
std::unique_ptr< GpuMemoryManager > mDeviceMemoryManager;
return *this;
}
-ResourceCache& ResourceCache::AddCommandPool( RefCountedCommandPool pool )
+ResourceCache& ResourceCache::AddCommandPool( std::thread::id currentThreadId, RefCountedCommandPool pool )
{
- mCommandPools.push_back( pool );
+ mCommandPools[currentThreadId] = pool;
return *this;
}
return iterator == mShaders.end() ? RefCountedShader() : RefCountedShader(&**iterator);
}
-RefCountedCommandPool ResourceCache::FindCommandPool( vk::CommandPool commandPool )
+RefCountedCommandPool ResourceCache::FindCommandPool( std::thread::id currentThreadId )
{
- auto iterator = std::find_if(mCommandPools.begin(),
- mCommandPools.end(),
- [&](const RefCountedCommandPool entry) { return entry->GetVkHandle() == commandPool; });
-
- return iterator == mCommandPools.end() ? RefCountedCommandPool() : RefCountedCommandPool(&**iterator);
+ return mCommandPools.find( currentThreadId ) == mCommandPools.end() ? RefCountedCommandPool() : mCommandPools[ currentThreadId ];
}
RefCountedDescriptorPool ResourceCache::FindDescriptorPool( vk::DescriptorPool descriptorPool )
{
if( !mCommandPools.empty() )
{
+ using EntryPair = std::pair< std::thread::id, RefCountedCommandPool >;
auto iterator = std::find_if(mCommandPools.begin(),
mCommandPools.end(),
- [&](const RefCountedCommandPool entry) { return &*entry == &commandPool; });
+ [&](const EntryPair& entry) { return &*(entry.second) == &commandPool; });
- std::iter_swap(iterator, std::prev(mCommandPools.end()));
- mCommandPools.back().Reset();
- mCommandPools.pop_back();
+ mCommandPools.erase( iterator );
}
return *this;
}
// INTERNAL INCLUDES
#include <dali/graphics/vulkan/vulkan-types.h>
#include <functional>
+#include <thread>
namespace Dali
{
namespace Vulkan
{
+using CommandPoolMap = std::unordered_map< std::thread::id, RefCountedCommandPool >;
+using DiscardQueue = std::vector< std::function< void() > >;
+
/**
* Stores and manages Vulkan resources
*/
* @param pool The command pool object to be added to the cache
* @return A reference to the ResourceCache
*/
- ResourceCache& AddCommandPool( RefCountedCommandPool pool );
+ ResourceCache& AddCommandPool( std::thread::id currentThreadId, RefCountedCommandPool pool );
/**
* Adds the provided descriptor pool object to the descriptor pool cache
/**
* Finds the CommandPool object using the specified Vulkan handle
- * @param commandPool The Vulkan handle of the CommandPool object to be found
+ * @param currentThreadId The Vulkan handle of the CommandPool object to be found
* @return A Handle to the CommandPool object if found. An empty Handle otherwise
*/
- RefCountedCommandPool FindCommandPool( vk::CommandPool commandPool );
+ RefCountedCommandPool FindCommandPool( std::thread::id currentThreadId );
/**
* Finds the DescriptorPool object using the specified Vulkan handle
std::vector< RefCountedImage > mImages;
std::vector< RefCountedImageView > mImageViews;
std::vector< RefCountedShader > mShaders;
- std::vector< RefCountedCommandPool > mCommandPools;
std::vector< RefCountedDescriptorPool > mDescriptorPools;
std::vector< RefCountedFramebuffer > mFramebuffers;
std::vector< RefCountedSampler > mSamplers;
std::vector< RefCountedFence > mFences;
- std::vector< std::function< void() > > mDiscardQueue;
+
+ // Command pool map using thread IDs as keys
+ CommandPoolMap mCommandPools;
+
+ DiscardQueue mDiscardQueue;
};
} //namespace Vulkan
RefCountedCommandBuffer masterCmdBuffer;
/*
- * Each buffer has a command pool to allocate from
- */
- RefCountedCommandPool masterCommandPool;
-
- /*
* Framebuffer object associated with the buffer
*/
RefCountedFramebuffer framebuffer;
mSwapchainBuffer.clear();
for( auto&& fb : mFramebuffers )
{
- auto cmdPool = CommandPool::New( mGraphics, vk::CommandPoolCreateInfo{}.setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer ) );
- auto masterCmd = cmdPool->NewCommandBuffer( true );
+ auto masterCmd = mGraphics.CreateCommandBuffer( true );
auto swapBuffer = SwapchainBuffer{};
swapBuffer.framebuffer = fb;
swapBuffer.index = 0;
swapBuffer.masterCmdBuffer = masterCmd;
- swapBuffer.masterCommandPool = cmdPool;
swapBuffer.endOfFrameFence = mGraphics.CreateFence({});
swapBuffer.firstUse = true;
mSwapchainBuffer.emplace_back( swapBuffer );
/*
* Create temporary command pool
*/
- auto commandPool = CommandPool::New( mGraphics );
- auto cmdBuffer = commandPool->NewCommandBuffer();
+ auto cmdBuffer = mGraphics.CreateCommandBuffer( true );
std::vector<vk::ImageMemoryBarrier> barriers;
RefCountedImageView depthStencilImage{};