Refactoring node partial update cache 66/285066/3
authorDavid Steele <david.steele@samsung.com>
Mon, 5 Dec 2022 17:48:45 +0000 (17:48 +0000)
committerHeeyong Song <heeyong.song@samsung.com>
Thu, 8 Dec 2022 07:11:42 +0000 (16:11 +0900)
Removing a level of inheritance, moving struct to node
Removed 1 buffer's worth of data, keep only last frame's data.
Instead, compute hash of node data and store that.

Cleaned up other data-provider structs and headers

Change-Id: I7b1033f37d0f22349f9c9cf0488feab28d63036b

dali/internal/event/actors/actor-impl.h
dali/internal/render/data-providers/node-data-provider.h
dali/internal/render/data-providers/uniform-map-data-provider.h
dali/internal/update/manager/render-instruction-processor.cpp
dali/internal/update/nodes/node.h
dali/internal/update/nodes/partial-rendering-data.h [new file with mode: 0644]

index 4557a03..fca059c 100644 (file)
@@ -63,9 +63,6 @@ class RenderTask;
 class Renderer;
 class Scene;
 
-class ActorDepthTreeNode;
-using DepthNodeMemoryPool = Dali::Internal::MemoryPoolObjectAllocator<ActorDepthTreeNode>;
-
 /**
  * Actor is the primary object with which Dali applications interact.
  * UI controls can be built by combining multiple actors.
@@ -1722,8 +1719,8 @@ private:
   };
 
   // Remove default constructor and copy constructor
-  Actor()             = delete;
-  Actor(const Actor&) = delete;
+  Actor()                            = delete;
+  Actor(const Actor&)                = delete;
   Actor& operator=(const Actor& rhs) = delete;
 
   /**
index 0c02dc7..e8c6dbc 100644 (file)
  *
  */
 
-#include <dali/internal/render/data-providers/uniform-map-data-provider.h>
-#include <dali/public-api/math/matrix.h>
-#include <cstring>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/update/common/uniform-map.h>
+#include <dali/public-api/math/vector4.h>
 
 namespace Dali
 {
-struct Vector4;
-class Matrix;
-
 namespace Internal
 {
 namespace SceneGraph
 {
-class Node;
-class Renderer;
-class TextureSet;
-
-/**
- * Structure to store partial rendering cache data
- */
-struct PartialRenderingCacheInfo
-{
-  Node*             node{nullptr};         /// Node associated with the entry
-  const Renderer*   renderer{nullptr};     /// Renderer object
-  const TextureSet* textureSet{nullptr};   /// TextureSet object
-  Matrix            matrix{};              /// Model-view matrix
-  Vector4           color{};               /// Color
-  Vector3           size{};                /// Size
-  Vector4           updatedPositionSize{}; /// Updated position/size (x, y, width, height)
-  bool              isOpaque{};            /// Opacity state
-  uint32_t          depthIndex{0u};        /// Depth index
-};
-
-/**
- * Structure contains partial rendering data used in order to determine
- * whether anything has changed and node has to be updated
- */
-struct PartialRenderingNodeData
-{
-  /**
-   * @brief Retrieves current PartialDataCacheInfo structure
-   * @return Current PartialDataCacheInfo structure
-   */
-  PartialRenderingCacheInfo& GetCurrentCacheInfo()
-  {
-    return mData[mCurrentIndex];
-  }
-
-  /**
-   * @brief Tests whether cache changed since last frame
-   * @return True if changed
-   */
-  bool IsUpdated()
-  {
-    return (0 != memcmp(&mData[0], &mData[1], sizeof(PartialRenderingCacheInfo)) || !mRendered);
-  }
-
-  /**
-   * @brief Swaps cache buffers
-   */
-  void SwapBuffers()
-  {
-    mCurrentIndex = static_cast<uint8_t>((~mCurrentIndex) & 1);
-  }
-
-  PartialRenderingCacheInfo mData[2u];         /// Double-buffered data
-  uint8_t                   mCurrentIndex{0u}; /// Current buffer index
-  bool                      mVisible{true};    /// Visible state
-  bool                      mRendered{false};  /// Rendering state
-};
-
-/**
- * An interface to provide partial rendering data
- */
-class PartialRenderingDataProvider
-{
-public:
-  /**
-   * Constructor
-   */
-  PartialRenderingDataProvider() = default;
-
-  /**
-   * Destructor
-   */
-  virtual ~PartialRenderingDataProvider() = default;
-
-  /**
-   * @brief Returns partial rendering data associated with the node.
-   * @return A valid pointer to the partial rendering data or nullptr
-   */
-  PartialRenderingNodeData& GetPartialRenderingData()
-  {
-    return mPartialRenderingData;
-  }
-
-protected:
-  PartialRenderingNodeData mPartialRenderingData;
-};
-
 /**
  * An interface to provide data for a Renderer
  */
-class NodeDataProvider : public PartialRenderingDataProvider
+class NodeDataProvider
 {
 public:
   /**
@@ -131,12 +41,6 @@ public:
 
   /**
    * @param bufferIndex to use
-   * @return a reference to the model matrix
-   */
-  virtual const Matrix& GetModelMatrix(BufferIndex bufferIndex) const = 0;
-
-  /**
-   * @param bufferIndex to use
    * @return a reference to the color
    */
   virtual const Vector4& GetRenderColor(BufferIndex bufferIndex) const = 0;
@@ -150,7 +54,7 @@ protected:
   /**
    * Virtual destructor, this is an interface, no deletion through this interface
    */
-  ~NodeDataProvider() override = default;
+  ~NodeDataProvider() = default;
 };
 
 } // namespace SceneGraph
index 5c1ec23..4fbac49 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_UNIFORM_MAP_DATA_PROVIDER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -16,9 +16,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <dali/internal/common/buffer-index.h>
+
 #include <dali/internal/update/common/collected-uniform-map.h>
-#include <dali/public-api/common/vector-wrapper.h>
 
 namespace Dali
 {
index aae62bd..3bc7f79 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali/internal/render/renderers/render-renderer.h>
 #include <dali/internal/render/shaders/render-shader.h>
 #include <dali/internal/update/manager/sorted-layers.h>
+#include <dali/internal/update/nodes/partial-rendering-data.h>
 #include <dali/internal/update/nodes/scene-graph-layer.h>
 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
 #include <dali/internal/update/rendering/scene-graph-texture-set.h>
@@ -260,21 +261,19 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
       // Get the next free RenderItem.
       RenderItem& item = renderList.GetNextFreeItem();
 
-      // Get cached values
-      auto& partialRenderingData = node->GetPartialRenderingData();
+      PartialRenderingData partialRenderingData;
 
-      auto& partialRenderingCacheInfo = node->GetPartialRenderingData().GetCurrentCacheInfo();
-
-      partialRenderingCacheInfo.node       = node;
-      partialRenderingCacheInfo.isOpaque   = isOpaque;
-      partialRenderingCacheInfo.renderer   = renderable.mRenderer;
-      partialRenderingCacheInfo.color      = node->GetWorldColor(updateBufferIndex);
-      partialRenderingCacheInfo.depthIndex = node->GetDepthIndex();
+      partialRenderingData.node       = node;
+      partialRenderingData.renderer   = renderable.mRenderer;
+      partialRenderingData.color      = node->GetWorldColor(updateBufferIndex);
+      partialRenderingData.depthIndex = node->GetDepthIndex();
+      partialRenderingData.isOpaque   = isOpaque;
 
+      partialRenderingData.textureSet = nullptr;
       if(DALI_LIKELY(renderable.mRenderer))
       {
-        partialRenderingCacheInfo.color.a *= renderable.mRenderer->GetOpacity(updateBufferIndex);
-        partialRenderingCacheInfo.textureSet = renderable.mRenderer->GetTextureSet();
+        partialRenderingData.color.a *= renderable.mRenderer->GetOpacity(updateBufferIndex);
+        partialRenderingData.textureSet = renderable.mRenderer->GetTextureSet();
       }
 
       item.mNode     = node;
@@ -326,21 +325,20 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
       }
       item.mModelViewMatrix = nodeModelViewMatrix;
 
-      partialRenderingCacheInfo.matrix              = item.mModelViewMatrix;
-      partialRenderingCacheInfo.size                = item.mSize;
-      partialRenderingCacheInfo.updatedPositionSize = item.mUpdateArea;
-
-      item.mIsUpdated = partialRenderingData.IsUpdated() || item.mIsUpdated;
+      partialRenderingData.matrix              = item.mModelViewMatrix;
+      partialRenderingData.updatedPositionSize = item.mUpdateArea;
+      partialRenderingData.size                = item.mSize;
 
-      partialRenderingData.mRendered = true;
+      auto& nodePartialRenderingData = node->GetPartialRenderingData();
+      item.mIsUpdated                = nodePartialRenderingData.IsUpdated(partialRenderingData) || item.mIsUpdated;
 
-      partialRenderingData.SwapBuffers();
+      nodePartialRenderingData.Update(partialRenderingData);
     }
     else
     {
       // Mark as not rendered
-      auto& partialRenderingData     = node->GetPartialRenderingData();
-      partialRenderingData.mRendered = false;
+      auto& nodePartialRenderingData     = node->GetPartialRenderingData();
+      nodePartialRenderingData.mRendered = false;
     }
 
     node->SetCulled(updateBufferIndex, false);
@@ -348,8 +346,8 @@ inline void AddRendererToRenderList(BufferIndex               updateBufferIndex,
   else
   {
     // Mark as not rendered
-    auto& partialRenderingData     = node->GetPartialRenderingData();
-    partialRenderingData.mRendered = false;
+    auto& nodePartialRenderingData     = node->GetPartialRenderingData();
+    nodePartialRenderingData.mRendered = false;
 
     node->SetCulled(updateBufferIndex, true);
   }
@@ -491,8 +489,10 @@ inline void RenderInstructionProcessor::SortRenderItems(BufferIndex bufferIndex,
 
   // List of zValue calculating functions.
   const Dali::Layer::SortFunctionType zValueFunctionFromVector3[] = {
-    [](const Vector3& position) { return position.z; },
-    [](const Vector3& position) { return position.LengthSquared(); },
+    [](const Vector3& position)
+    { return position.z; },
+    [](const Vector3& position)
+    { return position.LengthSquared(); },
     layer.GetSortFunction(),
   };
 
index 2cb97a3..d9acd62 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali/internal/update/manager/transform-manager-property.h>
 #include <dali/internal/update/manager/transform-manager.h>
 #include <dali/internal/update/nodes/node-declarations.h>
+#include <dali/internal/update/nodes/partial-rendering-data.h>
 #include <dali/internal/update/rendering/scene-graph-renderer.h>
 #include <dali/public-api/actors/actor-enumerations.h>
 #include <dali/public-api/actors/draw-mode.h>
@@ -57,6 +58,7 @@ class DiscardQueue;
 class Layer;
 class RenderTask;
 class UpdateManager;
+class Node;
 
 // Flags which require the scene renderable lists to be updated
 static NodePropertyFlags RenderableUpdateFlags = NodePropertyFlags::TRANSFORM | NodePropertyFlags::CHILD_DELETED;
@@ -846,6 +848,15 @@ public:
     return mCulled[bufferIndex];
   }
 
+  /**
+   * @brief Returns partial rendering data associated with the node.
+   * @return The partial rendering data
+   */
+  PartialRenderingData& GetPartialRenderingData()
+  {
+    return mPartialRenderingData;
+  }
+
 public:
   /**
    * @copydoc Dali::Internal::SceneGraph::PropertyOwner::IsAnimationPossible
@@ -886,14 +897,6 @@ protected:
 
 private: // from NodeDataProvider
   /**
-   * @copydoc NodeDataProvider::GetModelMatrix
-   */
-  const Matrix& GetModelMatrix(BufferIndex bufferIndex) const override
-  {
-    return GetWorldMatrix(bufferIndex);
-  }
-
-  /**
    * @copydoc NodeDataProvider::GetRenderColor
    */
   const Vector4& GetRenderColor(BufferIndex bufferIndex) const override
@@ -911,10 +914,10 @@ private: // from NodeDataProvider
 
 private:
   // Delete copy and move
-  Node(const Node&) = delete;
-  Node(Node&&)      = delete;
+  Node(const Node&)                = delete;
+  Node(Node&&)                     = delete;
   Node& operator=(const Node& rhs) = delete;
-  Node& operator=(Node&& rhs) = delete;
+  Node& operator=(Node&& rhs)      = delete;
 
   /**
    * Recursive helper to disconnect a Node and its children.
@@ -958,6 +961,8 @@ public: // Default properties
 protected:
   static uint32_t mNodeCounter; ///< count of total nodes, used for unique ids
 
+  PartialRenderingData mPartialRenderingData; ///< Cache to determine if this should be rendered again
+
   Node*       mParent;              ///< Pointer to parent node (a child is owned by its parent)
   RenderTask* mExclusiveRenderTask; ///< Nodes can be marked as exclusive to a single RenderTask
 
diff --git a/dali/internal/update/nodes/partial-rendering-data.h b/dali/internal/update/nodes/partial-rendering-data.h
new file mode 100644 (file)
index 0000000..d487908
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_PARTIAL_RENDERING_DATA_H
+#define DALI_INTERNAL_SCENE_GRAPH_PARTIAL_RENDERING_DATA_H
+
+/*
+ * Copyright (c) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/update/rendering/scene-graph-renderer.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali::Internal::SceneGraph
+{
+class Node;
+class TextureSet;
+
+/**
+ * Structure contains partial rendering data used in order to determine
+ * whether anything has changed and node has to be updated
+ */
+struct PartialRenderingData
+{
+  Node*             node{nullptr};                  /// Node associated with the entry
+  Renderer*         renderer{nullptr};              /// Renderer object
+  const TextureSet* textureSet{nullptr};            /// TextureSet object
+  Matrix            matrix{};                       /// Model-view matrix
+  Vector4           color{};                        /// Color
+  Vector4           updatedPositionSize{};          /// Updated position/size (x, y, width, height)
+  Vector3           size{};                         /// Size
+  uint32_t          depthIndex{0u};                 /// Depth index
+  uint32_t          hash;                           /// Last frame's hash
+  bool              isOpaque{};                     /// Opacity state
+
+  bool mVisible{true};   /// Visible state (Not hashed)
+  bool mRendered{false}; /// Rendering state (Not hashed)
+
+  /**
+   * Calculate a hash from the cache data
+   */
+  void CalculateHash()
+  {
+    hash = Dali::INITIAL_HASH_VALUE;
+    AddToHash(hash, &node, sizeof(decltype(node)));
+    AddToHash(hash, &renderer, sizeof(decltype(renderer)));
+    AddToHash(hash, &textureSet, sizeof(decltype(textureSet)));
+    AddToHash(hash, &matrix, sizeof(decltype(matrix)));
+    AddToHash(hash, &color, sizeof(decltype(color)));
+    AddToHash(hash, &updatedPositionSize, sizeof(decltype(updatedPositionSize)));
+    AddToHash(hash, &size, sizeof(decltype(size)));
+    AddToHash(hash, &depthIndex, sizeof(decltype(depthIndex)));
+    AddToHash(hash, &isOpaque, sizeof(decltype(isOpaque)));
+  }
+
+  /**
+   * @brief Tests whether cache changed since last frame
+   * @return True if changed
+   */
+  bool IsUpdated(PartialRenderingData& frameCache)
+  {
+    frameCache.CalculateHash();
+
+    return hash != frameCache.hash ||
+           node != frameCache.node ||
+           renderer != frameCache.renderer ||
+           textureSet != frameCache.textureSet ||
+           matrix != frameCache.matrix ||
+           color != frameCache.color ||
+           updatedPositionSize != frameCache.updatedPositionSize ||
+           size != frameCache.size ||
+           depthIndex != frameCache.depthIndex ||
+           isOpaque != frameCache.isOpaque ||
+
+           !mRendered; // If everything is the same, check if we didn't render last frame.
+  }
+
+  void Update(const PartialRenderingData& frameCache)
+  {
+    node                = frameCache.node;
+    renderer            = frameCache.renderer;
+    textureSet          = frameCache.textureSet;
+    matrix              = frameCache.matrix;
+    color               = frameCache.color;
+    updatedPositionSize = frameCache.updatedPositionSize;
+    size                = frameCache.size;
+    depthIndex          = frameCache.depthIndex;
+    isOpaque            = frameCache.isOpaque;
+    hash                = frameCache.hash;
+
+    mRendered = true;
+    // Don't change mVisible.
+  }
+
+private:
+  void AddToHash(uint32_t& aHash, void* el, size_t numBytes)
+  {
+    uint8_t* elBytes = static_cast<uint8_t*>(el);
+    for(size_t i = 0; i < numBytes; ++i)
+    {
+      aHash = aHash * 33 + *elBytes++;
+    }
+  }
+};
+
+} // namespace Dali::Internal::SceneGraph
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_PARTIAL_RENDERING_DATA_H