Change render target semaphore handling 72/317772/11
authorDavid Steele <david.steele@samsung.com>
Fri, 20 Dec 2024 17:40:17 +0000 (17:40 +0000)
committerDavid Steele <david.steele@samsung.com>
Thu, 23 Jan 2025 16:45:17 +0000 (16:45 +0000)
Fixed bug with dependency graph adding same dependency more than once to render target

Changed queue submission to handle vector of wait stage masks
(as a render task may depend on more than one offscreen to finish rendering)

Changed render task dependence so that only the "earliest" dependent needs to
wait for offscreen - (2nd dependant Submit can't wait on already signalled sema, apparently!)
Fixes a lot of lockups in demos.

Changed swapchain Submit() to pass in any offscreen dependencies.
  Swapchain submit adds own dependence on acquireNextImageSemaphore.

Test harness:
  Some tests skip initial "SendNotification" call. This means that scene-setup done by the test harness is ignored until the next frame.
  Changed the TestApplication InitilizeCore method to ensure that the messages are processed after setup.
  (So it doesn't matter if the test doesn't first call app.SendNotification()).

Change-Id: I05449137fa14ce1b00d3ecd152f4d0cf2409228d

automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-egl-application.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-vk-application.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-vk-application.h
dali/internal/graphics/vulkan-impl/vulkan-queue-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-queue-impl.h
dali/internal/graphics/vulkan-impl/vulkan-render-target.cpp
dali/internal/graphics/vulkan-impl/vulkan-render-target.h
dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.cpp
dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.h

index 1f17af3133589db22f8ec6aa7ccf8741a1f5c411..9abc90241410ac67b89426163100a914c6adab6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -90,7 +90,7 @@ void TestGraphicsApplication::CreateScene()
   createInfo.SetSurface({nullptr})
     .SetExtent({mSurfaceWidth, mSurfaceHeight})
     .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
-  //mRenderTarget = mGraphicsController.CreateRenderTarget(createInfo, nullptr);
+  // mRenderTarget = mGraphicsController.CreateRenderTarget(createInfo, nullptr);
   mScene.SetSurfaceRenderTarget(createInfo);
 }
 
@@ -98,6 +98,7 @@ void TestGraphicsApplication::InitializeCore()
 {
   mCore->SceneCreated();
   mCore->Initialize();
+  mCore->ProcessEvents();
 }
 
 TestGraphicsApplication::~TestGraphicsApplication()
index 10ae54c0368db55bbfdae91997d3bff1660557c3..1fe4b004366287c698fbfbc440b710c2953af8c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -99,7 +99,7 @@ void TestGraphicsApplication::CreateScene()
   createInfo.SetSurface({nullptr})
     .SetExtent({mSurfaceWidth, mSurfaceHeight})
     .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
-  //mRenderTarget = mGraphicsController.CreateRenderTarget(createInfo, nullptr);
+
   mScene.SetSurfaceRenderTarget(createInfo);
 }
 
@@ -107,6 +107,7 @@ void TestGraphicsApplication::InitializeCore()
 {
   mCore->SceneCreated();
   mCore->Initialize();
+  mCore->ProcessEvents();
 }
 
 TestGraphicsApplication::~TestGraphicsApplication()
index e3d3095649abbe150593252e3fd809048afd844b..f7d51038c0a780ff470c7eba3c62a72cfac60bd0 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -101,12 +101,11 @@ private:
   void DoUpdate(uint32_t intervalMilliseconds, const char* location = NULL);
 
 protected:
-  TestPlatformAbstraction                     mPlatformAbstraction;
-  TestRenderController                        mRenderController;
-  TestVkAbstraction                           mVkAbstraction;
-  Graphics::VulkanGraphics                    mGraphics; // Use real vulkan graphics
-  Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};
-  Dali::DisplayConnection*                    mDisplayConnection{nullptr};
+  TestPlatformAbstraction  mPlatformAbstraction;
+  TestRenderController     mRenderController;
+  TestVkAbstraction        mVkAbstraction;
+  Graphics::VulkanGraphics mGraphics; // Use real vulkan graphics
+  Dali::DisplayConnection* mDisplayConnection{nullptr};
 
   Integration::UpdateStatus mStatus;
   Integration::RenderStatus mRenderStatus;
index c4740bb2ed63ee2ce7dcc02df96859b508da65df..993ac2a1ad722821c761e965318e914b690349e2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 namespace Dali::Graphics::Vulkan
 {
 // submission
-SubmissionData::SubmissionData(const std::vector<vk::Semaphore>&      waitSemaphores_,
-                               vk::PipelineStageFlags                 waitDestinationStageMask_,
-                               const std::vector<CommandBufferImpl*>& commandBuffers_,
-                               const std::vector<vk::Semaphore>&      signalSemaphores_)
+SubmissionData::SubmissionData(const std::vector<vk::Semaphore>&          waitSemaphores_,
+                               const std::vector<vk::PipelineStageFlags>& waitDestinationStageMask_,
+                               const std::vector<CommandBufferImpl*>&     commandBuffers_,
+                               const std::vector<vk::Semaphore>&          signalSemaphores_)
 : waitSemaphores(waitSemaphores_),
   waitDestinationStageMask(waitDestinationStageMask_),
   commandBuffers(commandBuffers_),
@@ -40,7 +40,7 @@ SubmissionData& SubmissionData::SetWaitSemaphores(const std::vector<vk::Semaphor
   return *this;
 }
 
-SubmissionData& SubmissionData::SetWaitDestinationStageMask(vk::PipelineStageFlags dstStageMask)
+SubmissionData& SubmissionData::SetWaitDestinationStageMask(const std::vector<vk::PipelineStageFlags>& dstStageMask)
 {
   waitDestinationStageMask = dstStageMask;
   return *this;
@@ -126,7 +126,7 @@ vk::Result Queue::Submit(const std::vector<SubmissionData>& submissionData, Fenc
     auto submitInfo = vk::SubmitInfo()
                         .setWaitSemaphoreCount(U32(subData.waitSemaphores.size()))
                         .setPWaitSemaphores(subData.waitSemaphores.data())
-                        .setPWaitDstStageMask(&subData.waitDestinationStageMask)
+                        .setPWaitDstStageMask(subData.waitDestinationStageMask.data())
                         .setCommandBufferCount(U32(subData.commandBuffers.size()))
                         .setPCommandBuffers(&commandBufferHandles[currentBufferIndex])
                         .setSignalSemaphoreCount(U32(subData.signalSemaphores.size()))
index f5b1fe52ced7cd4ee81e6dd2e89f192f451822bb..95dc90ba5fb7c61858df0200a32a02caf362d304 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_GRAPHICS_VULKAN_QUEUE_IMPL_H
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,23 +33,23 @@ struct SubmissionData
 {
   SubmissionData() = default;
 
-  explicit SubmissionData(const std::vector<vk::Semaphore>&      waitSemaphores_,
-                          vk::PipelineStageFlags                 waitDestinationStageMask_,
-                          const std::vector<CommandBufferImpl*>& commandBuffers_,
-                          const std::vector<vk::Semaphore>&      signalSemaphores_);
+  explicit SubmissionData(const std::vector<vk::Semaphore>&          waitSemaphores_,
+                          const std::vector<vk::PipelineStageFlags>& waitDestinationStageMask_,
+                          const std::vector<CommandBufferImpl*>&     commandBuffers_,
+                          const std::vector<vk::Semaphore>&          signalSemaphores_);
 
   SubmissionData& SetWaitSemaphores(const std::vector<vk::Semaphore>& semaphores);
 
-  SubmissionData& SetWaitDestinationStageMask(vk::PipelineStageFlags dstStageMask);
+  SubmissionData& SetWaitDestinationStageMask(const std::vector<vk::PipelineStageFlags>& dstStageMask);
 
   SubmissionData& SetCommandBuffers(const std::vector<CommandBufferImpl*>& cmdBuffers);
 
   SubmissionData& SetSignalSemaphores(const std::vector<vk::Semaphore>& semaphores);
 
-  std::vector<vk::Semaphore>      waitSemaphores;
-  vk::PipelineStageFlags          waitDestinationStageMask;
-  std::vector<CommandBufferImpl*> commandBuffers;
-  std::vector<vk::Semaphore>      signalSemaphores;
+  std::vector<vk::Semaphore>          waitSemaphores;
+  std::vector<vk::PipelineStageFlags> waitDestinationStageMask;
+  std::vector<CommandBufferImpl*>     commandBuffers;
+  std::vector<vk::Semaphore>          signalSemaphores;
 };
 
 class Queue
index 2f93915d1f4a9d363f0f7a658fd6478a42224a89..feb68e853b4d017b45d4c1c3d7cd2dcb837f835b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -107,29 +107,37 @@ void RenderTarget::Submit(const CommandBuffer* cmdBuffer)
   auto& graphicsDevice = mController.GetGraphicsDevice();
   auto  surface        = GetSurface();
 
+  std::vector<vk::Semaphore> waitSemaphores;
+  for(auto renderTarget : mDependencies)
+  {
+    // Only use semaphore if dependency render target was submitted
+    // already this frame and not already waited on.
+    if(renderTarget->mSubmitted && !renderTarget->mSemaphoreWaited)
+    {
+      waitSemaphores.push_back(renderTarget->mSubmitSemaphore);
+      renderTarget->mSemaphoreWaited = true;
+    }
+  }
+  std::vector<vk::PipelineStageFlags> waitDstStageMask{waitSemaphores.size(), vk::PipelineStageFlagBits::eColorAttachmentOutput};
+
   if(surface)
   {
     auto surfaceId = static_cast<Internal::Adaptor::WindowRenderSurface*>(surface)->GetSurfaceId();
     auto swapchain = graphicsDevice.GetSwapchainForSurfaceId(surfaceId);
-    swapchain->Submit(cmdBuffer->GetImpl());
+    swapchain->Submit(cmdBuffer->GetImpl(), waitSemaphores);
   }
   else
   {
-    std::vector<vk::Semaphore> waitSemaphores;
-    for(auto renderTarget : mDependencies)
-    {
-      waitSemaphores.push_back(renderTarget->mSubmitSemaphore);
-    }
-
     std::vector<vk::Semaphore> signalSemaphores{mSubmitSemaphore};
     graphicsDevice.GetGraphicsQueue(0).Submit(
       {SubmissionData{
         waitSemaphores,
-        {vk::PipelineStageFlagBits::eFragmentShader},
+        waitDstStageMask,
         {cmdBuffer->GetImpl()},
         signalSemaphores}},
       nullptr);
   }
+  mSubmitted = true;
 }
 
 } // namespace Dali::Graphics::Vulkan
index caca3c881491bf8ab6a329e8892bca2c0ac8ea59..9dc848b0eae7e4b800a2b160a2fcad3ca77eff82 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_GRAPHICS_VULKAN_RENDER_TARGET_H
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -109,11 +109,17 @@ public:
   void ResetDependencies()
   {
     mDependencies.clear();
+    mSubmitted       = false;
+    mSemaphoreWaited = false;
   }
 
   void AddDependency(RenderTarget* dependency)
   {
-    mDependencies.push_back(dependency);
+    auto iter = std::find(mDependencies.begin(), mDependencies.end(), dependency);
+    if(iter == mDependencies.end())
+    {
+      mDependencies.push_back(dependency);
+    }
   }
   void RemoveDependency(RenderTarget* dependency)
   {
@@ -124,9 +130,13 @@ public:
     }
   }
 
+  const std::vector<RenderTarget*>& GetDependencies() const;
+
 private:
-  vk::Semaphore              mSubmitSemaphore; ///< Signaled when the command buffer for this target is processed
-  std::vector<RenderTarget*> mDependencies;    ///< Render targets whose output is used as input to this task.
+  std::vector<RenderTarget*> mDependencies;     ///< Render targets whose output is used as input to this task.
+  vk::Semaphore              mSubmitSemaphore;  ///< Signaled when the command buffer for this target is processed
+  bool                       mSubmitted{false}; ///< Check if this render target was submitted this frame
+  bool                       mSemaphoreWaited{false};
 };
 
 } // namespace Dali::Graphics::Vulkan
index 5d9a41a15678798a564784e70c9b4cb36cb0002e..93c3264b0ea0ddd0bcd87cfe292ed5ccd9045fdd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -371,15 +371,21 @@ FramebufferImpl* Swapchain::AcquireNextFramebuffer(bool shouldCollectGarbageNow)
   return mFramebuffers[mSwapchainImageIndex].get();
 }
 
-void Swapchain::Submit(CommandBufferImpl* commandBuffer)
+void Swapchain::Submit(CommandBufferImpl* commandBuffer, const std::vector<vk::Semaphore>& depends)
 {
   auto& swapchainBuffer = mSwapchainBuffers[mGraphicsDevice.GetCurrentBufferIndex()];
 
   swapchainBuffer->endOfFrameFence->Reset();
 
+  std::vector<vk::Semaphore>          waitSemaphores{depends};
+  std::vector<vk::PipelineStageFlags> waitDstStageMask{waitSemaphores.size(), vk::PipelineStageFlagBits::eColorAttachmentOutput};
+
+  waitSemaphores.push_back(swapchainBuffer->acquireNextImageSemaphore);
+  waitDstStageMask.push_back(vk::PipelineStageFlagBits::eFragmentShader);
+
   mQueue->Submit({Vulkan::SubmissionData{
-                   {swapchainBuffer->acquireNextImageSemaphore},
-                   {vk::PipelineStageFlagBits::eFragmentShader},
+                   waitSemaphores,
+                   waitDstStageMask,
                    {commandBuffer},
                    {swapchainBuffer->submitSemaphore}}},
                  swapchainBuffer->endOfFrameFence.get());
index 6654b7783cbfdd440c132f8c80b38ba98468e278..41c60e5051dfce5ee8d4b584ed3d9764dba0d349 100644 (file)
@@ -92,7 +92,7 @@ public:
   /**
    * Submits the given command buffer to the swapchain queue
    */
-  void Submit(CommandBufferImpl* commandBuffer);
+  void Submit(CommandBufferImpl* commandBuffer, const std::vector<vk::Semaphore>& depends);
 
   /**
    * Presents using default present queue, asynchronously