[Tizen] Ensure to destroy eglSyncObject at the same context of creation 92/316092/1 accepted/tizen/9.0/unified/20241211.021251
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 4 Dec 2024 07:22:08 +0000 (16:22 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Tue, 10 Dec 2024 06:05:33 +0000 (15:05 +0900)
To make ensure the eglSyncObject destroy at the same context of write,
let we collect discarded objects per each GLES::Context, and release them
when the context be current, after PostRender().

Furthermore, Let we destroy the sync objects before
content be destroyed.

And also, let we make TextureDependency use SyncObjectId
instead of AgingSyncObject* directly.
So, we don't need to notify context invalidated to
TextureDependency class. If some sync object deleted due to
context destruction, SyncObjectId will return nullptr from
SyncPool. So we only need to notify pool only.

Change-Id: I8fed7d3fecad7f9e11d4db686ae2271106f588d3
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
dali/internal/graphics/gles-impl/egl-graphics-controller.cpp
dali/internal/graphics/gles-impl/egl-graphics-controller.h
dali/internal/graphics/gles-impl/gles-context.cpp
dali/internal/graphics/gles-impl/gles-context.h
dali/internal/graphics/gles-impl/gles-sync-pool.cpp
dali/internal/graphics/gles-impl/gles-sync-pool.h
dali/internal/graphics/gles-impl/gles-texture-dependency-checker.cpp
dali/internal/graphics/gles-impl/gles-texture-dependency-checker.h

index 6faf8b1e024dafe0d41264368b359725e3bbb9c8..049ba86fe9a76534829c7520740d2341671b24d6 100644 (file)
@@ -304,6 +304,11 @@ void EglGraphicsController::ResolvePresentRenderTarget(GLES::RenderTarget* rende
     auto* surfaceInterface = reinterpret_cast<Dali::Integration::RenderSurfaceInterface*>(rt->GetCreateInfo().surface);
     surfaceInterface->MakeContextCurrent();
     surfaceInterface->PostRender();
+
+    // Delete discarded surface context sync objects.
+    // NOTE : We can assume that surface context is become current now.
+    //        And also can asusme that ResolvePresentRenderTarget() will be called at most 1 times per each frame.
+    mSyncPool.ProcessDiscardSyncObjects(GetSurfaceContext(surfaceInterface));
   }
 }
 
@@ -311,6 +316,10 @@ void EglGraphicsController::PostRender()
 {
   mTextureDependencyChecker.Reset();
   mSyncPool.AgeSyncObjects();
+
+  // Delete discarded resource context sync objects.
+  // NOTE : We can assume that current context is resource context now.
+  mSyncPool.ProcessDiscardSyncObjects(mCurrentContext);
 }
 
 Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
@@ -460,9 +469,30 @@ void EglGraphicsController::CreateSurfaceContext(Dali::Integration::RenderSurfac
 
 void EglGraphicsController::DeleteSurfaceContext(Dali::Integration::RenderSurfaceInterface* surface)
 {
-  mSurfaceContexts.erase(std::remove_if(
-                           mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
-                         mSurfaceContexts.end());
+  auto       iter       = mSurfaceContexts.begin();
+  auto       newEndIter = mSurfaceContexts.begin();
+  const auto endIter    = mSurfaceContexts.end();
+  for(; iter != endIter; ++iter)
+  {
+    if(iter->first != surface)
+    {
+      if(newEndIter != iter)
+      {
+        *newEndIter = std::move(*iter);
+      }
+      newEndIter++;
+      continue;
+    }
+    else
+    {
+      // Mark as given context will be deleted soon.
+      // It will make sync object id that created by given context
+      // become invalidated.
+      mSyncPool.InvalidateContext(iter->second.get());
+    }
+  }
+
+  mSurfaceContexts.erase(newEndIter, endIter);
 }
 
 void EglGraphicsController::ActivateResourceContext()
@@ -483,16 +513,30 @@ void EglGraphicsController::ActivateSurfaceContext(Dali::Integration::RenderSurf
 {
   if(surface && mGraphics->IsResourceContextSupported())
   {
-    auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return (iter.first == surface); });
+    auto* context = GetSurfaceContext(surface);
 
-    if(iter != mSurfaceContexts.end())
+    if(context)
     {
-      mCurrentContext = iter->second.get();
+      mCurrentContext = context;
       mCurrentContext->GlContextCreated();
     }
   }
 }
 
+GLES::Context* EglGraphicsController::GetSurfaceContext(Dali::Integration::RenderSurfaceInterface* surface) const
+{
+  if(DALI_LIKELY(surface))
+  {
+    auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](const SurfaceContextPair& iter) { return (iter.first == surface); });
+
+    if(iter != mSurfaceContexts.end())
+    {
+      return iter->second.get();
+    }
+  }
+  return nullptr;
+}
+
 void EglGraphicsController::AddTexture(GLES::Texture& texture)
 {
   // Assuming we are on the correct context
index 911962784c139eab104179e0f21199ccdd331019..79a676824123e411f6033946549ebad47d64467b 100644 (file)
@@ -20,6 +20,7 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/common/map-wrapper.h>
 #include <dali/graphics-api/graphics-controller.h>
+#include <memory>
 #include <queue>
 #include <unordered_map>
 #include <unordered_set>
@@ -839,6 +840,15 @@ public:
 
   uint32_t GetDeviceLimitation(Dali::Graphics::DeviceCapability capability) override;
 
+private:
+  /**
+   * Get the surface context
+   *
+   * @param[in] surface The surface whose context to want get context.
+   * @return valid context or null if not found.
+   */
+  GLES::Context* GetSurfaceContext(Dali::Integration::RenderSurfaceInterface* surface) const;
+
 private:
   Integration::GlAbstraction*              mGlAbstraction{nullptr};
   Integration::GlContextHelperAbstraction* mGlContextHelperAbstraction{nullptr};
@@ -886,8 +896,9 @@ private:
   void* mSharedContext{nullptr}; ///< Shared EGL context
 
   GLES::TextureDependencyChecker mTextureDependencyChecker; // Checks if FBO textures need syncing
-  GLES::SyncPool                 mSyncPool;
-  std::size_t                    mCapacity{0u}; ///< Memory Usage (of command buffers)
+
+  GLES::SyncPool mSyncPool;
+  std::size_t    mCapacity{0u}; ///< Memory Usage (of command buffers)
 };
 
 } // namespace Graphics
index c6c821f998f04ef9bdfc2f818b1a43bb4507829a..b096617a4a33fdfe1c921a00fdd2bf702d64194a 100644 (file)
@@ -268,7 +268,8 @@ struct Context::Impl
   std::unordered_map<const GLES::ProgramImpl*, std::map<std::size_t, uint32_t>> mProgramVAOMap;              ///< GL program-VAO map
   uint32_t                                                                      mProgramVAOCurrentState{0u}; ///< Currently bound VAO
   GLStateCache                                                                  mGlStateCache{};             ///< GL status cache
-  std::vector<Dali::GLuint>                                                     mDiscardedVAOList{};
+
+  std::vector<Dali::GLuint> mDiscardedVAOList{};
 
   bool mGlContextCreated{false};    ///< True if the OpenGL context has been created
   bool mVertexBuffersChanged{true}; ///< True if BindVertexBuffers changed any buffer bindings
@@ -944,7 +945,6 @@ void Context::ReadPixels(uint8_t* buffer)
   }
 }
 
-
 void Context::ClearState()
 {
   mImpl->mCurrentTextureBindings.clear();
index d9c2047c87ac0578a3fe40aa7346d39a33ee1f4f..9086769d38ae42c922be62ebcb702a0f6e43e876 100644 (file)
@@ -230,6 +230,7 @@ public:
   void SetDepthWriteEnable(bool depthWriteEnable);
 
   void ResetGLESState();
+
 private:
   /**
    * @brief Clear current state
index 650a5b791ab54ef3f8bc7c57903d4fbb97ff39e6..b3e69635906b90c6a07bb9d552b0ac84c9e2fc55 100644 (file)
@@ -30,7 +30,7 @@ extern Debug::Filter* gLogSyncFilter;
 
 namespace Dali::Graphics::GLES
 {
-AgingSyncObject::AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext, bool _egl)
+SyncPool::AgingSyncObject::AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext, bool _egl)
 : controller(controller),
   writeContext(writeContext),
   egl(_egl)
@@ -50,7 +50,7 @@ AgingSyncObject::AgingSyncObject(Graphics::EglGraphicsController& controller, co
   }
 }
 
-AgingSyncObject::~AgingSyncObject()
+SyncPool::AgingSyncObject::~AgingSyncObject()
 {
   if(DALI_LIKELY(!EglGraphicsController::IsShuttingDown()))
   {
@@ -70,7 +70,7 @@ AgingSyncObject::~AgingSyncObject()
   }
 }
 
-bool AgingSyncObject::IsSynced()
+bool SyncPool::AgingSyncObject::IsSynced()
 {
   bool synced = false;
   if(egl)
@@ -97,7 +97,7 @@ bool AgingSyncObject::IsSynced()
   return synced;
 }
 
-bool AgingSyncObject::ClientWait()
+bool SyncPool::AgingSyncObject::ClientWait()
 {
   bool synced = false;
   if(egl)
@@ -125,7 +125,7 @@ bool AgingSyncObject::ClientWait()
   return synced;
 }
 
-void AgingSyncObject::Wait()
+void SyncPool::AgingSyncObject::Wait()
 {
   if(egl)
   {
@@ -148,17 +148,21 @@ void AgingSyncObject::Wait()
 
 SyncPool::~SyncPool() = default;
 
-AgingSyncObject* SyncPool::AllocateSyncObject(const Context* writeContext, SyncPool::SyncContext syncContext)
+SyncPool::SyncObjectId SyncPool::AllocateSyncObject(const Context* writeContext, SyncPool::SyncContext syncContext)
 {
-  AgingSyncObject* agingSyncObject = new AgingSyncObject(mController, writeContext, (syncContext == SyncContext::EGL));
+  auto agingSyncObject = std::make_unique<AgingSyncObject>(mController, writeContext, (syncContext == SyncContext::EGL));
+
+  auto syncPoolObjectId = mSyncObjectId++;
 
   // Take ownership of sync object
-  mSyncObjects.PushBack(agingSyncObject);
-  return agingSyncObject;
+  mSyncObjects.insert(std::make_pair(syncPoolObjectId, std::move(agingSyncObject)));
+  return syncPoolObjectId;
 }
 
-bool SyncPool::IsSynced(AgingSyncObject* agingSyncObject)
+bool SyncPool::IsSynced(SyncPool::SyncObjectId syncPoolObjectId)
 {
+  AgingSyncObject* agingSyncObject = GetAgingSyncObject(syncPoolObjectId);
+
   if(DALI_LIKELY(agingSyncObject != nullptr))
   {
     return agingSyncObject->IsSynced();
@@ -166,8 +170,10 @@ bool SyncPool::IsSynced(AgingSyncObject* agingSyncObject)
   return false;
 }
 
-void SyncPool::Wait(AgingSyncObject* agingSyncObject)
+void SyncPool::Wait(SyncPool::SyncObjectId syncPoolObjectId)
 {
+  AgingSyncObject* agingSyncObject = GetAgingSyncObject(syncPoolObjectId);
+
   if(DALI_LIKELY(agingSyncObject != nullptr))
   {
     agingSyncObject->syncing = true;
@@ -175,8 +181,10 @@ void SyncPool::Wait(AgingSyncObject* agingSyncObject)
   }
 }
 
-bool SyncPool::ClientWait(AgingSyncObject* agingSyncObject)
+bool SyncPool::ClientWait(SyncPool::SyncObjectId syncPoolObjectId)
 {
+  AgingSyncObject* agingSyncObject = GetAgingSyncObject(syncPoolObjectId);
+
   if(DALI_LIKELY(agingSyncObject != nullptr))
   {
     return agingSyncObject->ClientWait();
@@ -184,12 +192,15 @@ bool SyncPool::ClientWait(AgingSyncObject* agingSyncObject)
   return false;
 }
 
-void SyncPool::FreeSyncObject(AgingSyncObject* agingSyncObject)
+void SyncPool::FreeSyncObject(SyncPool::SyncObjectId syncPoolObjectId)
 {
-  if(DALI_LIKELY(agingSyncObject != nullptr))
+  auto iter = mSyncObjects.find(syncPoolObjectId);
+  if(iter != mSyncObjects.end())
   {
-    // Release memory of sync object
-    mSyncObjects.EraseObject(agingSyncObject);
+    // Move memory of sync object to discard queue
+    DiscardAgingSyncObject(std::move(iter->second));
+
+    mSyncObjects.erase(iter);
   }
 }
 
@@ -199,28 +210,97 @@ void SyncPool::FreeSyncObject(AgingSyncObject* agingSyncObject)
  */
 void SyncPool::AgeSyncObjects()
 {
-  DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgeSyncObjects: count: %d\n", mSyncObjects.Count());
-
-  if(!mSyncObjects.IsEmpty())
+  if(!mSyncObjects.empty())
   {
+    DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgeSyncObjects: count: %d\n", mSyncObjects.size());
+
     // Age the remaining sync objects.
-    for(auto iter = mSyncObjects.Begin(); iter != mSyncObjects.End();)
+    for(auto iter = mSyncObjects.begin(); iter != mSyncObjects.end();)
     {
-      auto* agingSyncObject = (*iter);
-      if(agingSyncObject != nullptr && (agingSyncObject->glSyncObject != 0 || agingSyncObject->eglSyncObject != nullptr) && agingSyncObject->age > 0)
+      auto* agingSyncObject = (iter->second).get();
+      if(agingSyncObject != nullptr &&
+         (agingSyncObject->glSyncObject != 0 ||
+          agingSyncObject->eglSyncObject != nullptr) &&
+         agingSyncObject->age > 0)
       {
         --agingSyncObject->age;
         ++iter;
       }
       else
+      {
+        // Move memory of sync object to discard queue
+        DiscardAgingSyncObject(std::move(iter->second));
+
+        iter = mSyncObjects.erase(iter);
+      }
+    }
+
+    DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgeSyncObjects: count after erase: %d\n", mSyncObjects.size());
+  }
+}
+
+void SyncPool::ProcessDiscardSyncObjects(const Context* currentContext)
+{
+  auto iter = mDiscardSyncObjects.find(currentContext);
+  if(iter != mDiscardSyncObjects.end())
+  {
+#ifdef DEBUG_ENABLED
+    auto& agingSyncObjectsList = iter->second;
+
+    DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "ProcessDiscardSyncObjects: context[%p], count: %zu\n", currentContext, agingSyncObjectsList.size());
+#endif
+
+    mDiscardSyncObjects.erase(iter);
+  }
+}
+
+void SyncPool::InvalidateContext(const Context* invalidatedContext)
+{
+  if(!mSyncObjects.empty())
+  {
+    DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "InvalidateContext: context[%p], count: %d\n", invalidatedContext, mSyncObjects.size());
+
+    // Age the remaining sync objects.
+    for(auto iter = mSyncObjects.begin(); iter != mSyncObjects.end();)
+    {
+      auto* agingSyncObject = (iter->second).get();
+      if(agingSyncObject == nullptr ||
+         agingSyncObject->writeContext == invalidatedContext)
       {
         // Release memory of sync object
-        iter = mSyncObjects.Erase(iter);
+        // Note : We don't need to call DiscardAgingSyncObject here.
+        //        Even if current context is not given context, we should call it
+        //        since some DALI objects should be destroyed.
+        //        Don't worry about EGLSync leak, since it will be destroyed by eglDestroyContext.
+        iter = mSyncObjects.erase(iter);
+      }
+      else
+      {
+        ++iter;
       }
     }
+
+    DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "InvalidateContext: context[%p], count after erase: %d\n", mSyncObjects.size());
   }
 
-  DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "AgeSyncObjects: count after erase: %d\n", mSyncObjects.Count());
+  // Release discarded sync objects.
+  ProcessDiscardSyncObjects(invalidatedContext);
+}
+
+void SyncPool::DiscardAgingSyncObject(std::unique_ptr<AgingSyncObject>&& agingSyncObject)
+{
+  const Context* currentContext = agingSyncObject->writeContext;
+  mDiscardSyncObjects[currentContext].emplace_back(std::move(agingSyncObject));
+}
+
+SyncPool::AgingSyncObject* SyncPool::GetAgingSyncObject(SyncPool::SyncObjectId syncPoolObjectId) const
+{
+  auto iter = mSyncObjects.find(syncPoolObjectId);
+  if(iter != mSyncObjects.end())
+  {
+    return iter->second.get();
+  }
+  return nullptr;
 }
 
 } // namespace Dali::Graphics::GLES
index 7c25d933fecbbfa1278ae328d74a5a272155585b..c826c0df36bbe54c5fcf2c30a25f48139bf8ad37 100644 (file)
@@ -22,6 +22,9 @@
 #include <dali/integration-api/ordered-set.h>
 #include <dali/public-api/common/vector-wrapper.h>
 
+#include <cstdint>
+#include <memory>
+
 namespace Dali
 {
 namespace Internal::Adaptor
@@ -37,37 +40,21 @@ namespace GLES
 {
 class Context;
 
-struct AgingSyncObject
-{
-  AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext, bool egl = false);
-  ~AgingSyncObject();
-
-  EglGraphicsController& controller;
-  const Context*         writeContext;
-  union
-  {
-    GLsync                            glSyncObject;
-    Internal::Adaptor::EglSyncObject* eglSyncObject;
-  };
-  uint8_t age{2};
-  bool    syncing{false};
-  bool    egl{false};
-
-  bool IsSynced();
-  void Wait();
-  bool ClientWait();
-};
-using AgingSyncPtrRef = std::unique_ptr<AgingSyncObject>&;
-
 /**
  * A vector of current fence syncs. They only age if glWaitSync is called on them in the
  * same frame they are created, otherwise they are deleted.
  * They must be created in the writeContext, but can be synced from a readContext.
- * (Pool per context? - probably only ever used in resource context!)
+ *
+ * To match the created context and destroy context, we use discarded sync objects queue per each context.
+ * After when we can assume that eglMakeCurrent called, we can safely discard the sync objects.
+ *
+ * @note Before destroy the context, we should call InvalidateContext(), to ensure release memories.
  */
 class SyncPool
 {
 public:
+  using SyncObjectId = uint32_t;
+
   enum class SyncContext
   {
     EGL, ///< Use EGL sync when syncing between multiple contexts
@@ -84,35 +71,35 @@ public:
   /**
    * Allocate a sync object in the writeContext
    * @param writeContext
-   * @return An owned ptr to a sync object
+   * @return An unique id to a sync object
    */
-  AgingSyncObject* AllocateSyncObject(const Context* writeContext, SyncContext syncContext);
+  SyncObjectId AllocateSyncObject(const Context* writeContext, SyncContext syncContext);
 
   /**
    * Check whether given object is synced in the CPU
-   * @param syncPoolObject The object to check synced.
+   * @param syncPoolObjectId The id of object to check synced.
    * @return true if the sync object was signaled, false if it timed out
    */
-  bool IsSynced(AgingSyncObject* syncPoolObject);
+  bool IsSynced(SyncObjectId syncPoolObjectId);
 
   /**
    * Wait on a sync object in any context in the GPU
-   * @param syncPoolObject The object to wait on.
+   * @param syncPoolObjectId The id of object to wait on.
    */
-  void Wait(AgingSyncObject* syncPoolObject);
+  void Wait(SyncObjectId syncPoolObjectId);
 
   /**
    * Wait on a sync object in any context in the CPU
-   * @param syncPoolObject The object to wait on.
+   * @param syncPoolObjectId The id of object to wait on.
    * @return true if the sync object was signaled, false if it timed out
    */
-  bool ClientWait(AgingSyncObject* syncPoolObject);
+  bool ClientWait(SyncObjectId syncPoolObjectId);
 
   /**
    * Delete the sync object if it's not needed.
-   * @param syncPoolObject The object to delete.
+   * @param syncPoolObjectId The id of object to delete.
    */
-  void FreeSyncObject(AgingSyncObject* syncPoolObject);
+  void FreeSyncObject(SyncObjectId syncPoolObjectId);
 
   /**
    * Age outstanding sync objects. Call at the end of each frame.
@@ -120,9 +107,68 @@ public:
    */
   void AgeSyncObjects();
 
+public: /// Contexts relative API
+  /**
+   * Delete all sync objects that were created by given context.
+   *
+   * @param[in] currentContext The current context which will delete its sync objects.
+   */
+  void ProcessDiscardSyncObjects(const Context* currentContext);
+
+  /**
+   * Notify that given context will be destroyed soon.
+   * Let we remove all sync objects created by given context.
+   * @param invalidatedContext The context which will be called eglDestroyContext soon.
+   */
+  void InvalidateContext(const Context* invalidatedContext);
+
+private:
+  struct AgingSyncObject
+  {
+    AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext, bool egl = false);
+    ~AgingSyncObject();
+
+    EglGraphicsController& controller;
+    const Context*         writeContext;
+    union
+    {
+      GLsync                            glSyncObject;
+      Internal::Adaptor::EglSyncObject* eglSyncObject;
+    };
+    uint8_t age{2};
+    bool    syncing{false};
+    bool    egl{false};
+
+    bool IsSynced();
+    void Wait();
+    bool ClientWait();
+  };
+
 private:
-  Dali::Integration::OrderedSet<AgingSyncObject> mSyncObjects; ///< The list of sync objects in this pool (owned)
-  EglGraphicsController&                         mController;
+  /**
+   * Discard a sync object that was created by given context.
+   * @param currentContext The current context which will delete its sync object.
+   * @param agingSyncObject The sync object to delete.
+   */
+  void DiscardAgingSyncObject(std::unique_ptr<AgingSyncObject>&& agingSyncObject);
+
+  /**
+   * Get aging sync object from the container
+   * @param syncPoolObjectId The id of object to get.
+   * @return pointer to the aging sync object
+   */
+  AgingSyncObject* GetAgingSyncObject(SyncObjectId syncPoolObjectId) const;
+
+private:
+  using SyncObjectContainer = std::unordered_map<SyncObjectId, std::unique_ptr<AgingSyncObject>>;
+  SyncObjectContainer mSyncObjects; ///< The list of sync objects in this pool (owned)
+
+  using DiscardedSyncObjectContainer = std::unordered_map<const Context*, std::vector<std::unique_ptr<AgingSyncObject>>>;
+  DiscardedSyncObjectContainer mDiscardSyncObjects; ///< The list of discarded sync objects per each context
+
+  EglGraphicsController& mController;
+
+  SyncObjectId mSyncObjectId{0u};
 };
 
 } // namespace GLES
index dd8df4997ad3df97abc967848ca67b3603a5876c..d4f9bac696d4b8d2fb4fdb7fabafb12749a25130 100644 (file)
@@ -37,7 +37,7 @@ TextureDependencyChecker::~TextureDependencyChecker()
       {
         texture->SetDependencyIndex(0xffffffff);
       }
-      mController.GetSyncPool().FreeSyncObject(textureDependency.agingSyncObject);
+      mController.GetSyncPool().FreeSyncObject(textureDependency.agingSyncObjectId);
     }
     mFramebufferTextureDependencies.clear();
 
@@ -45,10 +45,7 @@ TextureDependencyChecker::~TextureDependencyChecker()
     {
       for(auto& nativeTextureDependency : mNativeTextureDependencies[nativeIndex])
       {
-        if(nativeTextureDependency.agingSyncObject != nullptr)
-        {
-          mController.GetSyncPool().FreeSyncObject(nativeTextureDependency.agingSyncObject);
-        }
+        mController.GetSyncPool().FreeSyncObject(nativeTextureDependency.agingSyncObjectId);
       }
       mNativeTextureDependencies[nativeIndex].clear();
     }
@@ -64,22 +61,19 @@ void TextureDependencyChecker::Reset()
     }
     if(!textureDependency.syncing)
     {
-      mController.GetSyncPool().FreeSyncObject(textureDependency.agingSyncObject);
+      mController.GetSyncPool().FreeSyncObject(textureDependency.agingSyncObjectId);
     }
   }
   mFramebufferTextureDependencies.clear();
 
-  if(mNativeTextureDependencies[0].size() > 0 || mNativeTextureDependencies[1].size())
+  if(!mNativeTextureDependencies[0].empty() || !mNativeTextureDependencies[1].empty())
   {
     DALI_ASSERT_ALWAYS(mIsFirstPreparedNativeTextureDependency && "CreateNativeTextureSync should be called before PostRender!");
 
     // Remove all infomations about previous native textures
     for(auto& nativeTextureDependency : mNativeTextureDependencies[mPreviousNativeTextureDependencyIndex])
     {
-      if(nativeTextureDependency.agingSyncObject != nullptr)
-      {
-        mController.GetSyncPool().FreeSyncObject(nativeTextureDependency.agingSyncObject);
-      }
+      mController.GetSyncPool().FreeSyncObject(nativeTextureDependency.agingSyncObjectId);
     }
     mNativeTextureDependencies[mPreviousNativeTextureDependencyIndex].clear();
 
@@ -125,7 +119,7 @@ void TextureDependencyChecker::AddTextures(const GLES::Context* writeContext, co
   // We have to check on different EGL contexts: The shared resource context is used to write to fbos,
   // but they are usually drawn onto separate scene context.
   DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::AddTextures() Allocating sync object\n");
-  textureDependency.agingSyncObject = mController.GetSyncPool().AllocateSyncObject(writeContext, SyncPool::SyncContext::EGL);
+  textureDependency.agingSyncObjectId = mController.GetSyncPool().AllocateSyncObject(writeContext, SyncPool::SyncContext::EGL);
 }
 
 void TextureDependencyChecker::CheckNeedsSync(const GLES::Context* readContext, const GLES::Texture* texture, bool cpu)
@@ -142,7 +136,7 @@ void TextureDependencyChecker::CheckNeedsSync(const GLES::Context* readContext,
       if(cpu)
       {
         DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CheckNeedsSync Insert CPU WAIT");
-        mController.GetSyncPool().ClientWait(textureDependency.agingSyncObject);
+        mController.GetSyncPool().ClientWait(textureDependency.agingSyncObjectId);
       }
       else
       {
@@ -150,7 +144,7 @@ void TextureDependencyChecker::CheckNeedsSync(const GLES::Context* readContext,
         // to the sync point.
         // However, this may instead timeout, and we can't tell the difference (at least, for glFenceSync)
         DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CheckNeedsSync Insert GPU WAIT");
-        mController.GetSyncPool().Wait(textureDependency.agingSyncObject);
+        mController.GetSyncPool().Wait(textureDependency.agingSyncObjectId);
       }
     }
   }
@@ -170,29 +164,25 @@ void TextureDependencyChecker::CheckNeedsSync(const GLES::Context* readContext,
       auto iter = nativeTextureDependency.textures.find(texture);
       if(iter != nativeTextureDependency.textures.end())
       {
-        if(nativeTextureDependency.agingSyncObject != nullptr)
+        if(cpu)
         {
-          if(cpu)
-          {
-            DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CheckNeedsSync (for native) Insert CPU WAIT");
-            nativeTextureDependency.synced = mController.GetSyncPool().ClientWait(nativeTextureDependency.agingSyncObject);
+          DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CheckNeedsSync (for native) Insert CPU WAIT");
+          nativeTextureDependency.synced = mController.GetSyncPool().ClientWait(nativeTextureDependency.agingSyncObjectId);
 
-            if(DALI_LIKELY(nativeTextureDependency.synced) && readContext == nativeTextureDependency.agingSyncObject->writeContext)
-            {
-              // We can free sync object immediatly if we are using same context.
-              mController.GetSyncPool().FreeSyncObject(nativeTextureDependency.agingSyncObject);
-              nativeTextureDependency.agingSyncObject = nullptr;
-            }
-          }
-          else
+          if(DALI_LIKELY(nativeTextureDependency.synced) && readContext == nativeTextureDependency.writeContext)
           {
-            // Wait on the sync object in GPU. This will ensure that the writeContext completes its tasks prior
-            // to the sync point.
-            // However, this may instead timeout, and we can't tell the difference (at least, for glFenceSync)
-            DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CheckNeedsSync (for native) Insert GPU WAIT");
-            mController.GetSyncPool().Wait(nativeTextureDependency.agingSyncObject);
+            // We can free sync object immediatly if we are using same context.
+            mController.GetSyncPool().FreeSyncObject(nativeTextureDependency.agingSyncObjectId);
           }
         }
+        else
+        {
+          // Wait on the sync object in GPU. This will ensure that the writeContext completes its tasks prior
+          // to the sync point.
+          // However, this may instead timeout, and we can't tell the difference (at least, for glFenceSync)
+          DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CheckNeedsSync (for native) Insert GPU WAIT");
+          mController.GetSyncPool().Wait(nativeTextureDependency.agingSyncObjectId);
+        }
 
         nativeTextureDependency.textures.erase(iter);
       }
@@ -236,7 +226,7 @@ void TextureDependencyChecker::DiscardNativeTexture(const GLES::Texture* texture
           nativeTextureDependency.textures.erase(jter);
           if(nativeTextureDependency.textures.empty())
           {
-            mController.GetSyncPool().FreeSyncObject(nativeTextureDependency.agingSyncObject);
+            mController.GetSyncPool().FreeSyncObject(nativeTextureDependency.agingSyncObjectId);
             iter = mNativeTextureDependencies[nativeIndex].erase(iter);
 
             isErased = true;
@@ -264,10 +254,11 @@ void TextureDependencyChecker::CreateNativeTextureSync(const GLES::Context* writ
 
   if(DALI_LIKELY(!mNativeTextureDependencies[mCurrentNativeTextureDependencyIndex].empty()))
   {
-    auto& nativeTextureDependency = mNativeTextureDependencies[mCurrentNativeTextureDependencyIndex].back();
+    auto& nativeTextureDependency        = mNativeTextureDependencies[mCurrentNativeTextureDependencyIndex].back();
+    nativeTextureDependency.writeContext = writeContext; // Store write context
 
     DALI_LOG_INFO(gLogSyncFilter, Debug::Verbose, "TextureDependencyChecker::CreateNativeTextureSync() Allocating sync object\n");
-    nativeTextureDependency.agingSyncObject = mController.GetSyncPool().AllocateSyncObject(writeContext, SyncPool::SyncContext::EGL);
+    nativeTextureDependency.agingSyncObjectId = mController.GetSyncPool().AllocateSyncObject(writeContext, SyncPool::SyncContext::EGL);
   }
 }
 
index 08afaae66890f3d2697b9708750e4ca88b04cb37..90e8876009eddeca53a757cac45f90fe93a0deee 100644 (file)
@@ -34,7 +34,6 @@ namespace GLES
 class Context;
 class Framebuffer;
 class Texture;
-class AgingSyncObject;
 
 /**
  * Class to handle dependency checks between textures on different
@@ -117,12 +116,14 @@ public: ///< For NativeTexture dependency checker
   void CreateNativeTextureSync(const Context* writeContext);
 
 private:
+  using SyncObjectId = uint32_t; ///< Note : It should be matched with Dali::Graphics::GLES::SyncPool:SyncObjectId.
+
   struct FramebufferTextureDependency
   {
     std::vector<Texture*> textures;
     Context*              writeContext{nullptr};
     Framebuffer*          framebuffer{nullptr};
-    AgingSyncObject*      agingSyncObject{nullptr};
+    SyncObjectId          agingSyncObjectId{0u};
     bool                  syncing{false};
   };
   std::vector<FramebufferTextureDependency> mFramebufferTextureDependencies;
@@ -130,7 +131,8 @@ private:
   struct NativeTextureDependency
   {
     std::unordered_set<const Texture*> textures;
-    AgingSyncObject*                   agingSyncObject{nullptr};
+    const Context*                     writeContext{nullptr};
+    SyncObjectId                       agingSyncObjectId{0u};
     bool                               synced{false};
   };
   std::vector<NativeTextureDependency> mNativeTextureDependencies[2];