Fixing swapchain buffer count and cmd buffer allocs 15/321415/5
authorDavid Steele <david.steele@samsung.com>
Thu, 20 Mar 2025 19:32:59 +0000 (19:32 +0000)
committerDavid Steele <david.steele@samsung.com>
Fri, 21 Mar 2025 14:55:01 +0000 (14:55 +0000)
Number of swapchain buffers should be based on minImageCount
from surfaceCapabilities, rather than the current number of
images that getSwapchainImagesKHR returns.

Currently, it is possible for the swapchain to get invalidated,
and the new swapchain can be generated with more images than
min. We only need to sync the min number; so we double or triple
buffer based on this count.

(number of CommandBuffers / SwapchainBuffers is based on this min count,
not total image count)

Changed this to only reallocate command buffers in Reset(), rather than
breaking any outstanding sequence.

Change-Id: I5348dcc1762426e5370a35cd7f48d4612a3b5114

dali/internal/graphics/vulkan-impl/vulkan-command-buffer.cpp
dali/internal/graphics/vulkan-impl/vulkan-command-buffer.h
dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.h
dali/internal/graphics/vulkan/vulkan-device.cpp

index a149fbed66e2fa52ae80f7bf384f4d3d1039cb47..329a5e132812382594e748a82f6ea6c1d3d810dd 100644 (file)
 #include <dali/internal/window-system/common/window-render-surface.h>
 
 #if defined(DEBUG_ENABLED)
-Debug::Filter* gLogCmdBufferFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VK_COMMAND_BUFFER");
+Debug::Filter*        gLogCmdBufferFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VK_COMMAND_BUFFER");
+extern Debug::Filter* gVulkanFilter;
 #endif
 
 namespace Dali::Graphics::Vulkan
 {
+const uint32_t EXCESS_BUFFER_COUNT = 4;
+
 template<typename VT, typename GT>
 VT* ConstGraphicsCast(const GT* object)
 {
@@ -47,17 +50,7 @@ CommandBuffer::CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo
 : CommandBufferResource(createInfo, controller),
   mDynamicStateMask(CommandBuffer::INITIAL_DYNAMIC_MASK_VALUE)
 {
-  auto& device    = controller.GetGraphicsDevice();
-  bool  isPrimary = true;
-  if(createInfo.level == Graphics::CommandBufferLevel::SECONDARY)
-  {
-    isPrimary = false;
-  }
-  auto commandPool = device.GetCommandPool(std::this_thread::get_id());
-  for(uint32_t i = 0; i < device.GetBufferCount(); ++i)
-  {
-    mCommandBufferImpl.emplace_back(commandPool->NewCommandBuffer(isPrimary));
-  }
+  AllocateCommandBuffers();
 }
 
 CommandBuffer::~CommandBuffer() = default;
@@ -81,14 +74,14 @@ void CommandBuffer::DiscardResource()
 
 void CommandBuffer::Begin(const Graphics::CommandBufferBeginInfo& info)
 {
-  mDynamicStateMask    = CommandBuffer::INITIAL_DYNAMIC_MASK_VALUE;
-  mRenderTarget        = ConstGraphicsCast<Vulkan::RenderTarget, Graphics::RenderTarget>(info.renderTarget);
-  uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size());
-  DALI_LOG_INFO(gLogCmdBufferFilter, Debug::Verbose, "CommandBuffer::Begin: ptr:%p bufferIndex=%d\n", GetImpl(), bufferIndex);
+  mDynamicStateMask = CommandBuffer::INITIAL_DYNAMIC_MASK_VALUE;
+  mRenderTarget     = ConstGraphicsCast<Vulkan::RenderTarget, Graphics::RenderTarget>(info.renderTarget);
+
+  auto commandBufferImpl = GetImpl();
+  DALI_LOG_INFO(gLogCmdBufferFilter, Debug::Verbose, "CommandBuffer::Begin: ptr:%p bufferIndex=%d\n", GetImpl(), mController.GetGraphicsDevice().GetCurrentBufferIndex());
   mCmdCount++; // Debug info
 
-  if(mCommandBufferImpl[bufferIndex])
+  if(commandBufferImpl)
   {
     vk::CommandBufferInheritanceInfo inheritanceInfo{};
     if(info.renderPass)
@@ -99,7 +92,7 @@ void CommandBuffer::Begin(const Graphics::CommandBufferBeginInfo& info)
       inheritanceInfo.queryFlags         = static_cast<vk::QueryControlFlags>(0);
       inheritanceInfo.pipelineStatistics = static_cast<vk::QueryPipelineStatisticFlags>(0);
     }
-    mCommandBufferImpl[bufferIndex]->Begin(static_cast<vk::CommandBufferUsageFlags>(info.usage), &inheritanceInfo);
+    commandBufferImpl->Begin(static_cast<vk::CommandBufferUsageFlags>(info.usage), &inheritanceInfo);
 
     // Default depth/stencil should be off:
     SetDepthTestEnable(false);
@@ -111,19 +104,30 @@ void CommandBuffer::Begin(const Graphics::CommandBufferBeginInfo& info)
 
 void CommandBuffer::End()
 {
-  uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-  DALI_LOG_INFO(gLogCmdBufferFilter, Debug::Verbose, "CommandBuffer::End: ptr:%p bufferIndex=%d\n", GetImpl(), bufferIndex);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  DALI_LOG_INFO(gLogCmdBufferFilter, Debug::Verbose, "CommandBuffer::End: ptr:%p bufferIndex=%d\n", commandBufferImpl, mController.GetGraphicsDevice().GetCurrentBufferIndex());
+
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->End();
+  commandBufferImpl->End();
 }
 
 void CommandBuffer::Reset()
 {
-  uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_LOG_INFO(gLogCmdBufferFilter, Debug::Verbose, "CommandBuffer::Reset: ptr:%p bufferIndex=%d", GetImpl(), bufferIndex);
+  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
+
+  if(bufferIndex >= EXCESS_BUFFER_COUNT)
+  {
+    DALI_LOG_ERROR("ERROR: bufferIndex %u exceeds EXCESS_BUFFER_COUNT\n", bufferIndex);
+  }
+  DALI_ASSERT_DEBUG(bufferIndex < EXCESS_BUFFER_COUNT);
+
+  if(bufferIndex >= mCommandBufferImpl.size())
+  {
+    // Handle (odd) case where swapchain is re-created with a different number of min images
+    AllocateCommandBuffers();
+  }
 
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
+  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size());
   mCommandBufferImpl[bufferIndex]->Reset();
 
   mDynamicStateMask = CommandBuffer::INITIAL_DYNAMIC_MASK_VALUE;
@@ -135,68 +139,58 @@ void CommandBuffer::BindVertexBuffers(uint32_t
                                       const std::vector<const Graphics::Buffer*>& gfxBuffers,
                                       const std::vector<uint32_t>&                offsets)
 {
-  uint32_t                 bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
+  mCmdCount++; // Debug info
   std::vector<BufferImpl*> buffers;
   buffers.reserve(gfxBuffers.size());
   for(auto& gfxBuffer : gfxBuffers)
   {
     buffers.push_back(ConstGraphicsCast<Buffer, Graphics::Buffer>(gfxBuffer)->GetImpl());
   }
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-  mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->BindVertexBuffers(firstBinding, buffers, offsets);
+
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->BindVertexBuffers(firstBinding, buffers, offsets);
 }
 
 void CommandBuffer::BindIndexBuffer(const Graphics::Buffer& gfxBuffer,
                                     uint32_t                offset,
                                     Format                  format)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
+  mCmdCount++; // Debug info
   auto indexBuffer = ConstGraphicsCast<Buffer, Graphics::Buffer>(&gfxBuffer);
   DALI_ASSERT_DEBUG(indexBuffer && indexBuffer->GetImpl());
 
-  mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->BindIndexBuffer(*indexBuffer->GetImpl(), offset, format);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->BindIndexBuffer(*indexBuffer->GetImpl(), offset, format);
 }
 
 void CommandBuffer::BindUniformBuffers(const std::vector<UniformBufferBinding>& bindings)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
-  mCommandBufferImpl[bufferIndex]->BindUniformBuffers(bindings);
+  mCmdCount++; // Debug info
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->BindUniformBuffers(bindings);
 }
 
 void CommandBuffer::BindPipeline(const Graphics::Pipeline& pipeline)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->BindPipeline(&pipeline);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->BindPipeline(&pipeline);
 }
 
 void CommandBuffer::BindTextures(const std::vector<TextureBinding>& textureBindings)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
-  mCommandBufferImpl[bufferIndex]->BindTextures(textureBindings);
-
   mCmdCount++; // Debug info
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->BindTextures(textureBindings);
+
   mController.CheckTextureDependencies(textureBindings, mRenderTarget);
 }
 
 void CommandBuffer::BindSamplers(const std::vector<SamplerBinding>& samplerBindings)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->BindSamplers(samplerBindings);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->BindSamplers(samplerBindings);
 }
 
 void CommandBuffer::BindPushConstants(void*    data,
@@ -210,10 +204,6 @@ void CommandBuffer::BeginRenderPass(Graphics::RenderPass*          gfxRenderPass
                                     Rect2D                         renderArea,
                                     const std::vector<ClearValue>& clearValues)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   auto renderTarget = static_cast<Vulkan::RenderTarget*>(gfxRenderTarget);
   DALI_ASSERT_DEBUG(mRenderTarget == renderTarget && "RenderPass has different render target to cmd buffer Begin");
 
@@ -256,39 +246,32 @@ void CommandBuffer::BeginRenderPass(Graphics::RenderPass*          gfxRenderPass
   }
 
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->BeginRenderPass(vk::RenderPassBeginInfo{}
-                                                     .setFramebuffer(framebuffer->GetVkHandle())
-                                                     .setRenderPass(renderPassImpl->GetVkHandle())
-                                                     .setRenderArea({{0, 0}, {renderArea.width, renderArea.height}})
-                                                     .setPClearValues(vkClearValues.data())
-                                                     .setClearValueCount(uint32_t(vkClearValues.size())),
-                                                   vk::SubpassContents::eSecondaryCommandBuffers);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->BeginRenderPass(vk::RenderPassBeginInfo{}
+                                       .setFramebuffer(framebuffer->GetVkHandle())
+                                       .setRenderPass(renderPassImpl->GetVkHandle())
+                                       .setRenderArea({{0, 0}, {renderArea.width, renderArea.height}})
+                                       .setPClearValues(vkClearValues.data())
+                                       .setClearValueCount(uint32_t(vkClearValues.size())),
+                                     vk::SubpassContents::eSecondaryCommandBuffers);
 }
 
 void CommandBuffer::EndRenderPass(Graphics::SyncObject* syncObject)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->EndRenderPass();
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->EndRenderPass();
 }
 
 void CommandBuffer::ReadPixels(uint8_t* buffer)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->ReadPixels(buffer);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->ReadPixels(buffer);
 }
 
 void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& gfxCommandBuffers)
 {
-  uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   std::vector<vk::CommandBuffer> vkCommandBuffers;
   vkCommandBuffers.reserve(gfxCommandBuffers.size());
   for(auto& gfxCmdBuf : gfxCommandBuffers)
@@ -296,7 +279,8 @@ void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuf
     vkCommandBuffers.push_back(ConstGraphicsCast<CommandBuffer, Graphics::CommandBuffer>(gfxCmdBuf)->GetImpl()->GetVkHandle());
   }
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->ExecuteCommandBuffers(vkCommandBuffers);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->ExecuteCommandBuffers(vkCommandBuffers);
 }
 
 void CommandBuffer::Draw(uint32_t vertexCount,
@@ -304,11 +288,9 @@ void CommandBuffer::Draw(uint32_t vertexCount,
                          uint32_t firstVertex,
                          uint32_t firstInstance)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->Draw(vertexCount, instanceCount, firstVertex, firstInstance);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->Draw(vertexCount, instanceCount, firstVertex, firstInstance);
 }
 
 void CommandBuffer::DrawIndexed(uint32_t indexCount,
@@ -317,11 +299,9 @@ void CommandBuffer::DrawIndexed(uint32_t indexCount,
                                 int32_t  vertexOffset,
                                 uint32_t firstInstance)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->DrawIndexed(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->DrawIndexed(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
 }
 
 void CommandBuffer::DrawIndexedIndirect(Graphics::Buffer& gfxBuffer,
@@ -329,12 +309,10 @@ void CommandBuffer::DrawIndexedIndirect(Graphics::Buffer& gfxBuffer,
                                         uint32_t          drawCount,
                                         uint32_t          stride)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
-  auto buffer = ConstGraphicsCast<Buffer, Graphics::Buffer>(&gfxBuffer)->GetImpl();
   mCmdCount++; // Debug info
-  mCommandBufferImpl[bufferIndex]->DrawIndexedIndirect(*buffer, offset, drawCount, stride);
+  auto               buffer            = ConstGraphicsCast<Buffer, Graphics::Buffer>(&gfxBuffer)->GetImpl();
+  CommandBufferImpl* commandBufferImpl = GetImpl();
+  commandBufferImpl->DrawIndexedIndirect(*buffer, offset, drawCount, stride);
 }
 
 void CommandBuffer::DrawNative(const DrawNativeInfo* drawInfo)
@@ -343,15 +321,14 @@ void CommandBuffer::DrawNative(const DrawNativeInfo* drawInfo)
 
 void CommandBuffer::SetScissor(Rect2D value)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   // @todo Vulkan accepts array of scissors... add to API
 
   if(SetDynamicState(mDynamicState.scissor, value, DynamicStateMaskBits::SCISSOR))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetScissor(value);
+
+    CommandBufferImpl* commandBufferImpl = GetImpl();
+    commandBufferImpl->SetScissor(value);
   }
 }
 
@@ -371,13 +348,11 @@ void CommandBuffer::SetViewport(Viewport value)
     correctedValue.y      = value.height;
   }
 
-  uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   if(SetDynamicState(mDynamicState.viewport, correctedValue, DynamicStateMaskBits::VIEWPORT))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetViewport(correctedValue);
+    CommandBufferImpl* commandBufferImpl = GetImpl();
+    commandBufferImpl->SetViewport(correctedValue);
   }
 }
 
@@ -403,25 +378,21 @@ void CommandBuffer::ClearDepthBuffer()
 
 void CommandBuffer::SetStencilTestEnable(bool stencilEnable)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   if(SetDynamicState(mDynamicState.stencilTest, stencilEnable, DynamicStateMaskBits::STENCIL_TEST))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetStencilTestEnable(stencilEnable);
+    CommandBufferImpl* commandBufferImpl = GetImpl();
+    commandBufferImpl->SetStencilTestEnable(stencilEnable);
   }
 }
 
 void CommandBuffer::SetStencilWriteMask(uint32_t writeMask)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
-
   if(SetDynamicState(mDynamicState.stencilWriteMask, writeMask, DynamicStateMaskBits::STENCIL_WRITE_MASK))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack, writeMask);
+    CommandBufferImpl* commandBufferImpl = GetImpl();
+    commandBufferImpl->SetStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack, writeMask);
   }
 }
 
@@ -432,18 +403,17 @@ void CommandBuffer::SetStencilState(Graphics::CompareOp compareOp,
                                     Graphics::StencilOp passOp,
                                     Graphics::StencilOp depthFailOp)
 {
-  uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
+  CommandBufferImpl* commandBufferImpl = GetImpl();
 
   if(SetDynamicState(mDynamicState.stencilCompareMask, compareMask, DynamicStateMaskBits::STENCIL_COMP_MASK))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack, compareMask);
+    commandBufferImpl->SetStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack, compareMask);
   }
   if(SetDynamicState(mDynamicState.stencilReference, reference, DynamicStateMaskBits::STENCIL_REF))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetStencilReference(vk::StencilFaceFlagBits::eFrontAndBack, reference);
+    commandBufferImpl->SetStencilReference(vk::StencilFaceFlagBits::eFrontAndBack, reference);
   }
 
   if(SetDynamicState(mDynamicState.stencilFailOp, failOp, DynamicStateMaskBits::STENCIL_OP_FAIL) ||
@@ -452,44 +422,41 @@ void CommandBuffer::SetStencilState(Graphics::CompareOp compareOp,
      SetDynamicState(mDynamicState.stencilCompareOp, compareOp, DynamicStateMaskBits::STENCIL_OP_COMP))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetStencilOp(vk::StencilFaceFlagBits::eFrontAndBack,
-                                                  VkStencilOpType(failOp).op,
-                                                  VkStencilOpType(passOp).op,
-                                                  VkStencilOpType(depthFailOp).op,
-                                                  VkCompareOpType(compareOp).op);
+    commandBufferImpl->SetStencilOp(vk::StencilFaceFlagBits::eFrontAndBack,
+                                    VkStencilOpType(failOp).op,
+                                    VkStencilOpType(passOp).op,
+                                    VkStencilOpType(depthFailOp).op,
+                                    VkCompareOpType(compareOp).op);
   }
 }
 
 void CommandBuffer::SetDepthCompareOp(Graphics::CompareOp compareOp)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
   if(SetDynamicState(mDynamicState.depthCompareOp, compareOp, DynamicStateMaskBits::DEPTH_OP_COMP))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetDepthCompareOp(VkCompareOpType(compareOp).op);
+    CommandBufferImpl* commandBufferImpl = GetImpl();
+    commandBufferImpl->SetDepthCompareOp(VkCompareOpType(compareOp).op);
   }
 }
 
 void CommandBuffer::SetDepthTestEnable(bool depthTestEnable)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
   if(SetDynamicState(mDynamicState.depthTest, depthTestEnable, DynamicStateMaskBits::DEPTH_TEST))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetDepthTestEnable(depthTestEnable);
+    CommandBufferImpl* commandBufferImpl = GetImpl();
+    commandBufferImpl->SetDepthTestEnable(depthTestEnable);
   }
 }
 
 void CommandBuffer::SetDepthWriteEnable(bool depthWriteEnable)
 {
-  const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
   if(SetDynamicState(mDynamicState.depthWrite, depthWriteEnable, DynamicStateMaskBits::DEPTH_WRITE))
   {
     mCmdCount++; // Debug info
-    mCommandBufferImpl[bufferIndex]->SetDepthWriteEnable(depthWriteEnable);
+    CommandBufferImpl* commandBufferImpl = GetImpl();
+    commandBufferImpl->SetDepthWriteEnable(depthWriteEnable);
   }
 }
 
@@ -502,8 +469,27 @@ Vulkan::RenderTarget* CommandBuffer::GetRenderTarget() const
 [[nodiscard]] Vulkan::CommandBufferImpl* CommandBuffer::GetImpl() const
 {
   const uint32_t bufferIndex = mController.GetGraphicsDevice().GetCurrentBufferIndex();
-  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size() && mCommandBufferImpl[bufferIndex]);
+  DALI_ASSERT_ALWAYS(bufferIndex < mCommandBufferImpl.size());
   return mCommandBufferImpl[bufferIndex];
 }
 
+void CommandBuffer::AllocateCommandBuffers()
+{
+  auto& device    = mController.GetGraphicsDevice();
+  bool  isPrimary = true;
+  if(mCreateInfo.level == Graphics::CommandBufferLevel::SECONDARY)
+  {
+    isPrimary = false;
+  }
+  auto commandPool = device.GetCommandPool(std::this_thread::get_id());
+  auto bufferCount = device.GetBufferCount();
+
+  DALI_LOG_INFO(gVulkanFilter, Debug::General, "Allocating %d new cmd buffers\n", bufferCount - mCommandBufferImpl.size());
+
+  for(uint32_t i = mCommandBufferImpl.size(); i < bufferCount; ++i)
+  {
+    mCommandBufferImpl.emplace_back(commandPool->NewCommandBuffer(isPrimary));
+  }
+}
+
 } // namespace Dali::Graphics::Vulkan
index 99a091484905b98a08f3c4beffec52e16b61dd67..eff635721629df58675ebef68bc9677bab463c00 100644 (file)
@@ -384,9 +384,17 @@ public: // API
    */
   RenderTarget* GetRenderTarget() const;
 
+  /**
+   * Get the implementation according to the current buffer index.
+   */
   [[nodiscard]] CommandBufferImpl* GetImpl() const;
 
 private:
+  /**
+   * Ensure that there are enough command buffers allocated.
+   */
+  void AllocateCommandBuffers();
+
   static const DynamicStateMask INITIAL_DYNAMIC_MASK_VALUE{0xFFFFFFFF};
 
   /** Struct that defines the current state */
index 2a4c60c2b3e5b371d6e00b3d41b033924bc1f4a3..7ca576dc7e312a4eff4f4c0eeae638cbc9409375 100644 (file)
@@ -140,11 +140,11 @@ void Swapchain::CreateVkSwapchain(
   }
 
   // Determine the number of images
-  if(surfaceCapabilities.minImageCount > 0 &&
-     bufferCount != surfaceCapabilities.minImageCount)
+  if(surfaceCapabilities.minImageCount > 0)
   {
     bufferCount = surfaceCapabilities.minImageCount;
   }
+  mBufferCount = bufferCount;
 
   // Find the transformation of the surface
   vk::SurfaceTransformFlagBitsKHR preTransform;
@@ -161,8 +161,7 @@ void Swapchain::CreateVkSwapchain(
   auto presentModes = surface->GetSurfacePresentModes();
   auto found        = std::find_if(presentModes.begin(),
                             presentModes.end(),
-                            [&](vk::PresentModeKHR mode)
-                            {
+                            [&](vk::PresentModeKHR mode) {
                               return presentMode == mode;
                             });
 
@@ -201,16 +200,18 @@ void Swapchain::Destroy()
     mDepthStencilBuffer->Destroy();
   }
 
+  mFramebuffers.clear();
+  mSwapchainBuffers.clear();
+  mSwapchainImages.clear();
+
+  DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying SwapChain: %p\n", static_cast<VkSwapchainKHR>(mSwapchainKHR));
+
   if(mSwapchainKHR)
   {
     auto device    = mGraphicsDevice.GetLogicalDevice();
-    auto swapchain = mSwapchainKHR;
     auto allocator = &mGraphicsDevice.GetAllocator();
-    mFramebuffers.clear();
-    mSwapchainBuffers.clear();
 
-    DALI_LOG_INFO(gVulkanFilter, Debug::General, "Destroying SwapChain: %p\n", static_cast<VkSwapchainKHR>(swapchain));
-    device.destroySwapchainKHR(swapchain, allocator);
+    device.destroySwapchainKHR(mSwapchainKHR, allocator);
     mSwapchainKHR = nullptr;
   }
 }
@@ -241,6 +242,8 @@ void Swapchain::CreateFramebuffers(FramebufferAttachmentHandle depthAttachment)
 
   auto clearColor = vk::ClearColorValue{}.setFloat32({1.0f, 0.0f, 1.0f, 1.0f});
 
+  DALI_LOG_INFO(gVulkanFilter, Debug::General, "Num Images: %u\n", images.size());
+
   //
   // CREATE FRAMEBUFFERS
   //
@@ -269,8 +272,7 @@ void Swapchain::CreateFramebuffers(FramebufferAttachmentHandle depthAttachment)
                            depthAttachment,
                            mSwapchainCreateInfoKHR.imageExtent.width,
                            mSwapchainCreateInfoKHR.imageExtent.height),
-      [](FramebufferImpl* framebuffer1)
-      {
+      [](FramebufferImpl* framebuffer1) {
         framebuffer1->Destroy();
         delete framebuffer1;
       });
@@ -314,7 +316,7 @@ FramebufferImpl* Swapchain::AcquireNextFramebuffer(bool shouldCollectGarbageNow)
   // on swapchain first create sync primitives if not created yet
   if(mSwapchainBuffers.empty())
   {
-    mSwapchainBuffers.resize(mSwapchainImages.size());
+    mSwapchainBuffers.resize(mBufferCount);
     for(auto& buffer : mSwapchainBuffers)
     {
       buffer.reset(new SwapchainBuffer(mGraphicsDevice));
@@ -348,6 +350,8 @@ FramebufferImpl* Swapchain::AcquireNextFramebuffer(bool shouldCollectGarbageNow)
 
   DALI_LOG_INFO(gVulkanFilter, Debug::General, "Swapchain Image Index ( AFTER Acquire ) = %d", int(mSwapchainImageIndex));
 
+  DALI_LOG_INFO(gVulkanFilter, Debug::General, "acquireNextImageKHR result %s\n", vk::to_string(result).c_str());
+
   // swapchain either not optimal or expired, returning nullptr and
   // setting validity to false
   if(result != vk::Result::eSuccess)
@@ -404,7 +408,7 @@ void Swapchain::CreateSubmissionData(
 
 uint32_t Swapchain::GetCurrentBufferIndex() const
 {
-  return mSwapchainBuffers.empty() ? 0 : mFrameCounter % mSwapchainBuffers.size();
+  return mSwapchainBuffers.empty() ? 0 : mFrameCounter % mBufferCount;
 }
 
 bool Swapchain::Present()
@@ -505,9 +509,4 @@ void Swapchain::SetDepthStencil(vk::Format depthStencilFormat)
   CreateFramebuffers(depthAttachment);
 }
 
-uint32_t Swapchain::GetImageCount() const
-{
-  return uint32_t(mFramebuffers.size());
-}
-
 } // namespace Dali::Graphics::Vulkan
index bee9ee9da4bb482bb75a3b2df2fcd072b567c812..30b3de6685e7cfc66b5510a9f2a6aab198129ad5 100644 (file)
@@ -143,12 +143,6 @@ public:
    */
   void SetDepthStencil(vk::Format depthStencilFormat);
 
-  /**
-   * Returns number of allocated swapchain images
-   * @return Number of swapchain images
-   */
-  [[nodiscard]] uint32_t GetImageCount() const;
-
   /**
    * Returns surface associated with swapchain
    * @return Pointer to surface
@@ -160,6 +154,11 @@ public:
 
   [[nodiscard]] uint32_t GetCurrentBufferIndex() const;
 
+  [[nodiscard]] uint32_t GetBufferCount() const
+  {
+    return mBufferCount;
+  }
+
 private:
   void CreateVkSwapchain(
     vk::SwapchainKHR   oldSwapchain,
@@ -188,6 +187,7 @@ private:
    * Array of swapchain buffers
    */
   std::vector<std::unique_ptr<SwapchainBuffer>> mSwapchainBuffers;
+  uint32_t                                      mBufferCount{2u};       ///< Minimum Number of swapchain buffers
   uint32_t                                      mFrameCounter{0u};      ///< Current frame number
   uint32_t                                      mSwapchainImageIndex{}; ///< Swapchain image index returned by vkAcquireNextImageKHR
 
index 50614a70f8d664cc1c02e036ab13e6fdbd59ae7b..885f9a3da3374e96c84750aaeb87f3308b50ac56 100644 (file)
@@ -381,6 +381,8 @@ Swapchain* Device::CreateSwapchain(SurfaceImpl*       surface,
 {
   auto newSwapchain = Swapchain::NewSwapchain(*this, GetPresentQueue(), oldSwapchain ? oldSwapchain->GetVkHandle() : nullptr, surface, requestedFormat, presentMode, mBufferCount);
 
+  DALI_LOG_INFO(gVulkanFilter, Debug::Concise, "Creating new swapchain with buffer count: %u\n", mBufferCount);
+
   if(oldSwapchain)
   {
     for(auto&& i : mSurfaceMap)
@@ -418,6 +420,8 @@ void Device::AcquireNextImage(SurfaceId surfaceId)
   {
     FramebufferImpl* framebuffer = swapchain->AcquireNextFramebuffer(true);
 
+    DALI_LOG_INFO(gVulkanFilter, Debug::Verbose, "  framebuffer::%p  isValid:%s\n", framebuffer, swapchain->IsValid() ? "T" : "F");
+
     // In case something went wrong we will try to replace swapchain once
     // before calling it a day.
     if(!framebuffer || !swapchain->IsValid())