Ignore glTexImage2D if we know given texture is already discarded 32/306032/1
authorEunki, Hong <eunkiki.hong@samsung.com>
Thu, 15 Feb 2024 08:32:10 +0000 (17:32 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 15 Feb 2024 08:32:10 +0000 (17:32 +0900)
Since glTexImage2D is heavy operation, and if we know that we don't use it,
we can ignore the texture upload operations.

Change-Id: If474919945d39d19f8870b06850db4e843d7ba11
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/gl-implementation.h

index abe4c47..3d7979a 100644 (file)
@@ -438,7 +438,7 @@ void EglGraphicsController::ProcessDiscardQueues()
   DALI_TRACE_SCOPE(gTraceFilter, "DALI_EGL_CONTROLLER_DISCARD_QUEUE");
 
   // Process textures
-  ProcessDiscardQueue<GLES::Texture>(mDiscardTextureQueue);
+  ProcessDiscardSet<GLES::Texture>(mDiscardTextureSet);
 
   // Process buffers
   ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
@@ -777,89 +777,93 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
           sourceBufferReleaseRequired = Dali::Integration::IsPixelDataReleaseAfterUpload(source.pixelDataSource.pixelData) && info.srcOffset == 0u;
         }
 
-        auto                 sourceStride = info.srcStride;
-        std::vector<uint8_t> tempBuffer;
-
-        if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
+        // Skip texture upload if given texture is already discarded for this render loop.
+        if(mDiscardTextureSet.find(texture) == mDiscardTextureSet.end())
         {
-          // Convert RGB to RGBA if necessary.
-          if(texture->TryConvertPixelData(sourceBuffer, info.srcFormat, createInfo.format, info.srcSize, info.srcStride, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer))
+          auto                 sourceStride = info.srcStride;
+          std::vector<uint8_t> tempBuffer;
+
+          if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
           {
-            sourceBuffer = &tempBuffer[0];
-            sourceStride = 0u; // Converted buffer compacted. make stride as 0.
-            srcFormat    = destFormat;
-            srcType      = GLES::GLTextureFormatType(createInfo.format).type;
+            // Convert RGB to RGBA if necessary.
+            if(texture->TryConvertPixelData(sourceBuffer, info.srcFormat, createInfo.format, info.srcSize, info.srcStride, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer))
+            {
+              sourceBuffer = &tempBuffer[0];
+              sourceStride = 0u; // Converted buffer compacted. make stride as 0.
+              srcFormat    = destFormat;
+              srcType      = GLES::GLTextureFormatType(createInfo.format).type;
+            }
           }
-        }
 
-        // Calculate the maximum mipmap level for the texture
-        texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
+          // Calculate the maximum mipmap level for the texture
+          texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
 
-        GLenum bindTarget{GL_TEXTURE_2D};
-        GLenum target{GL_TEXTURE_2D};
+          GLenum bindTarget{GL_TEXTURE_2D};
+          GLenum target{GL_TEXTURE_2D};
 
-        if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
-        {
-          bindTarget = GL_TEXTURE_CUBE_MAP;
-          target     = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
-        }
+          if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
+          {
+            bindTarget = GL_TEXTURE_CUBE_MAP;
+            target     = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
+          }
 
-        mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
-        mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
+          mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+          mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
 
-        mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
+          mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
 
-        if(!isSubImage)
-        {
-          if(!texture->IsCompressed())
-          {
-            mGlAbstraction->TexImage2D(target,
-                                       info.level,
-                                       destInternalFormat,
-                                       info.srcExtent2D.width,
-                                       info.srcExtent2D.height,
-                                       0,
-                                       srcFormat,
-                                       srcType,
-                                       sourceBuffer);
-          }
-          else
-          {
-            mGlAbstraction->CompressedTexImage2D(target,
-                                                 info.level,
-                                                 destInternalFormat,
-                                                 info.srcExtent2D.width,
-                                                 info.srcExtent2D.height,
-                                                 0,
-                                                 info.srcSize,
-                                                 sourceBuffer);
-          }
-        }
-        else
-        {
-          if(!texture->IsCompressed())
+          if(!isSubImage)
           {
-            mGlAbstraction->TexSubImage2D(target,
-                                          info.level,
-                                          info.dstOffset2D.x,
-                                          info.dstOffset2D.y,
-                                          info.srcExtent2D.width,
-                                          info.srcExtent2D.height,
-                                          srcFormat,
-                                          srcType,
-                                          sourceBuffer);
+            if(!texture->IsCompressed())
+            {
+              mGlAbstraction->TexImage2D(target,
+                                         info.level,
+                                         destInternalFormat,
+                                         info.srcExtent2D.width,
+                                         info.srcExtent2D.height,
+                                         0,
+                                         srcFormat,
+                                         srcType,
+                                         sourceBuffer);
+            }
+            else
+            {
+              mGlAbstraction->CompressedTexImage2D(target,
+                                                   info.level,
+                                                   destInternalFormat,
+                                                   info.srcExtent2D.width,
+                                                   info.srcExtent2D.height,
+                                                   0,
+                                                   info.srcSize,
+                                                   sourceBuffer);
+            }
           }
           else
           {
-            mGlAbstraction->CompressedTexSubImage2D(target,
-                                                    info.level,
-                                                    info.dstOffset2D.x,
-                                                    info.dstOffset2D.y,
-                                                    info.srcExtent2D.width,
-                                                    info.srcExtent2D.height,
-                                                    srcFormat,
-                                                    info.srcSize,
-                                                    sourceBuffer);
+            if(!texture->IsCompressed())
+            {
+              mGlAbstraction->TexSubImage2D(target,
+                                            info.level,
+                                            info.dstOffset2D.x,
+                                            info.dstOffset2D.y,
+                                            info.srcExtent2D.width,
+                                            info.srcExtent2D.height,
+                                            srcFormat,
+                                            srcType,
+                                            sourceBuffer);
+            }
+            else
+            {
+              mGlAbstraction->CompressedTexSubImage2D(target,
+                                                      info.level,
+                                                      info.dstOffset2D.x,
+                                                      info.dstOffset2D.y,
+                                                      info.srcExtent2D.width,
+                                                      info.srcExtent2D.height,
+                                                      srcFormat,
+                                                      info.srcSize,
+                                                      sourceBuffer);
+            }
           }
         }
 
index c4a0ba0..cddc538 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/graphics-api/graphics-controller.h>
 #include <queue>
 #include <unordered_map>
+#include <unordered_set>
 
 // INTERNAL INCLUDES
 #include <dali/integration-api/graphics-sync-abstraction.h>
@@ -384,7 +385,7 @@ public:
    */
   void DiscardResource(GLES::Texture* texture)
   {
-    mDiscardTextureQueue.push(texture);
+    mDiscardTextureSet.insert(texture);
   }
 
   /**
@@ -645,6 +646,40 @@ public:
   }
 
   /**
+   * @brief Processes a discard set for type specified
+   *
+   * @param[in,out] set Reference to the discard set
+   */
+  template<class U, class T>
+  void ProcessDiscardSet(T& set)
+  {
+    while(!set.empty())
+    {
+      auto  iter   = set.begin();
+      auto* object = const_cast<U*>(*iter);
+
+      // Destroy
+      object->DestroyResource();
+
+      // Free
+      auto* clbk = object->GetCreateInfo().allocationCallbacks;
+      if(clbk)
+      {
+        // Call destructor
+        object->~U();
+
+        // Free memory
+        clbk->freeCallback(object, clbk->userData);
+      }
+      else
+      {
+        delete object;
+      }
+      set.erase(iter);
+    }
+  }
+
+  /**
    * @brief Processes all resource create queues
    */
   void ProcessCreateQueues();
@@ -820,8 +855,8 @@ private:
   Internal::Adaptor::EglSyncImplementation* mEglSyncImplementation{nullptr};
   Internal::Adaptor::GraphicsInterface*     mGraphics{nullptr}; // Pointer to owning structure via interface.
 
-  std::queue<GLES::Texture*> mCreateTextureQueue;  ///< Create queue for texture resource
-  std::queue<GLES::Texture*> mDiscardTextureQueue; ///< Discard queue for texture resource
+  std::queue<GLES::Texture*>         mCreateTextureQueue; ///< Create queue for texture resource
+  std::unordered_set<GLES::Texture*> mDiscardTextureSet;  ///< Discard queue for texture resource
 
   std::queue<GLES::Buffer*> mCreateBufferQueue;  ///< Create queue for buffer resource
   std::queue<GLES::Buffer*> mDiscardBufferQueue; ///< Discard queue for buffer resource
index bf40d8c..733743b 100644 (file)
@@ -877,7 +877,7 @@ public:
 
     glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
 
-    FINISH_DURATION_CHECK_WITH_FORMAT("glTexImage2D", "size : %u x %u", width, height);
+    FINISH_DURATION_CHECK_WITH_FORMAT("glTexImage2D", "size : %u x %u, format : %d, type : %d", width, height, static_cast<int>(format), static_cast<int>(type));
   }
 
   void TexParameterf(GLenum target, GLenum pname, GLfloat param) override
@@ -906,7 +906,7 @@ public:
 
     glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
 
-    FINISH_DURATION_CHECK_WITH_FORMAT("glTexSubImage2D", "size : %u x %u", width, height);
+    FINISH_DURATION_CHECK_WITH_FORMAT("glTexSubImage2D", "size : %u x %u, format : %d, type : %d", width, height, static_cast<int>(format), static_cast<int>(type));
   }
 
   void Uniform1f(GLint location, GLfloat x) override