Merge "Remove old pipeline caches" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / pipeline-cache.cpp
index 3f655f4..92fe22b 100644 (file)
@@ -29,6 +29,8 @@ namespace Dali::Internal::Render
 {
 namespace
 {
+constexpr uint32_t CACHE_CLEAN_FRAME_COUNT = 600; // 60fps * 10sec
+
 // Helper to get the vertex input format
 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
 {
@@ -209,8 +211,14 @@ PipelineCacheL0* PipelineCache::GetPipelineCacheL0(std::size_t hash, Program* pr
     {
       const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
 
+      uint32_t                  divisor         = vertexBuffer->GetDivisor();
+      Graphics::VertexInputRate vertexInputRate = (divisor == 0
+                                                     ? Graphics::VertexInputRate::PER_VERTEX
+                                                     : Graphics::VertexInputRate::PER_INSTANCE);
+
       vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
-                                                   Graphics::VertexInputRate::PER_VERTEX);
+                                                   vertexInputRate);
+      //@todo Add the actual rate to the graphics struct
 
       const uint32_t attributeCount          = vertexBuffer->GetAttributeCount();
       uint32_t       lastBoundAttributeIndex = 0;
@@ -316,6 +324,21 @@ PipelineCacheL1* PipelineCacheL0::GetPipelineCacheL1(Render::Renderer* renderer,
   return retval;
 }
 
+void PipelineCacheL0::ClearUnusedCache()
+{
+  for(auto iter = level1nodes.begin(); iter != level1nodes.end();)
+  {
+    if(iter->ClearUnusedCache())
+    {
+      iter = level1nodes.erase(iter);
+    }
+    else
+    {
+      iter++;
+    }
+  }
+}
+
 PipelineCacheL2* PipelineCacheL1::GetPipelineCacheL2(bool blend, bool premul, BlendingOptions& blendingOptions)
 {
   // early out
@@ -404,6 +427,28 @@ PipelineCacheL2* PipelineCacheL1::GetPipelineCacheL2(bool blend, bool premul, Bl
   return retval;
 }
 
+bool PipelineCacheL1::ClearUnusedCache()
+{
+  if(noBlend.referenceCount > 0)
+  {
+    return false;
+  }
+
+  for(auto iter = level2nodes.begin(); iter != level2nodes.end();)
+  {
+    if(iter->referenceCount == 0)
+    {
+      iter = level2nodes.erase(iter);
+    }
+    else
+    {
+      iter++;
+    }
+  }
+
+  return level2nodes.empty();
+}
+
 void PipelineCacheQueryInfo::GenerateHash()
 {
   // Lightweight hash value generation.
@@ -453,6 +498,7 @@ PipelineResult PipelineCache::GetPipeline(const PipelineCacheQueryInfo& queryInf
   // If we can reuse latest bound pipeline, Fast return.
   if(ReuseLatestBoundPipeline(latestUsedCacheIndex, queryInfo))
   {
+    mLatestResult[latestUsedCacheIndex].level2->referenceCount++;
     return mLatestResult[latestUsedCacheIndex];
   }
 
@@ -482,10 +528,10 @@ PipelineResult PipelineCache::GetPipeline(const PipelineCacheQueryInfo& queryInf
   PipelineResult result{};
 
   result.pipeline = level2->pipeline.get();
-  result.level0   = level0;
-  result.level1   = level1;
   result.level2   = level2;
 
+  level2->referenceCount++;
+
   // Copy query and result
   mLatestQuery[latestUsedCacheIndex]  = queryInfo;
   mLatestResult[latestUsedCacheIndex] = result;
@@ -498,4 +544,41 @@ bool PipelineCache::ReuseLatestBoundPipeline(const int latestUsedCacheIndex, con
   return mLatestResult[latestUsedCacheIndex].pipeline != nullptr && PipelineCacheQueryInfo::Equal(queryInfo, mLatestQuery[latestUsedCacheIndex]);
 }
 
+void PipelineCache::PreRender()
+{
+  CleanLatestUsedCache();
+
+  // We don't need to check this every frame
+  if(++mFrameCount >= CACHE_CLEAN_FRAME_COUNT)
+  {
+    mFrameCount = 0u;
+    ClearUnusedCache();
+  }
+}
+
+void PipelineCache::ClearUnusedCache()
+{
+  for(auto iter = level0nodes.begin(); iter != level0nodes.end();)
+  {
+    iter->ClearUnusedCache();
+
+    if(iter->level1nodes.empty())
+    {
+      iter = level0nodes.erase(iter);
+    }
+    else
+    {
+      iter++;
+    }
+  }
+}
+
+void PipelineCache::ResetPipeline(PipelineCacheL2* pipelineCache)
+{
+  if(pipelineCache)
+  {
+    pipelineCache->referenceCount--;
+  }
+}
+
 } // namespace Dali::Internal::Render