Skip duplicated vertex binding 88/289288/5
authorEunki Hong <eunkiki.hong@samsung.com>
Sun, 5 Mar 2023 14:42:00 +0000 (23:42 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Tue, 7 Mar 2023 15:34:50 +0000 (00:34 +0900)
Let we skip some useless commands for vertex attributes binding.
If latest rendered geometry is same as previous, we don't need to
re-bind vertex attributes.

For hueristic way, Most of Visuals, like image and text, are used
simplest QUAD geometry. So for real world app are use only 1 geometry.
We can reduce for this case's rendering time.

Change-Id: I3643bdb728964365f42284dec3ff0ab77819f42b
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/renderers/render-geometry.cpp
dali/internal/render/renderers/render-geometry.h
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h

index 152798d..13dfcc4 100644 (file)
@@ -643,6 +643,9 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
     mHasLayerScissor = true;
   }
 
+  // Prepare Render::Renderer Render for this secondary command buffer.
+  Renderer::PrepareCommandBuffer();
+
   // Loop through all RenderItems in the RenderList, set up any prerequisites to render them, then perform the render.
   for(uint32_t index = 0u; index < count; ++index)
   {
index feb6244..b407b6f 100644 (file)
@@ -149,11 +149,7 @@ void Geometry::Upload(Graphics::Controller& graphicsController)
   }
 }
 
-bool Geometry::Draw(
-  Graphics::Controller&    graphicsController,
-  Graphics::CommandBuffer& commandBuffer,
-  uint32_t                 elementBufferOffset,
-  uint32_t                 elementBufferCount)
+bool Geometry::BindVertexAttributes(Graphics::CommandBuffer& commandBuffer)
 {
   //Bind buffers to attribute locations
   const auto vertexBufferCount = static_cast<uint32_t>(mVertexBuffers.Count());
@@ -183,6 +179,15 @@ bool Geometry::Draw(
 
   commandBuffer.BindVertexBuffers(0, buffers, offsets);
 
+  return true;
+}
+
+bool Geometry::Draw(
+  Graphics::Controller&    graphicsController,
+  Graphics::CommandBuffer& commandBuffer,
+  uint32_t                 elementBufferOffset,
+  uint32_t                 elementBufferCount)
+{
   uint32_t numIndices(0u);
   intptr_t firstIndexOffset(0u);
   if(mIndexBuffer)
@@ -220,7 +225,8 @@ bool Geometry::Draw(
   {
     // Un-indexed draw call
     uint32_t numVertices(0u);
-    if(vertexBufferCount > 0)
+
+    if(mVertexBuffers.Count() > 0)
     {
       // truncated, no value loss happening in practice
       numVertices = static_cast<uint32_t>(mVertexBuffers[0]->GetElementCount());
index a23c7a0..2f04c97 100644 (file)
@@ -125,7 +125,7 @@ public:
    * Set up the attributes and perform the Draw call corresponding to the geometry type.
    *
    * @param[in] graphicsController The graphics controller
-   * @param[in] bufferIndex The current buffer index
+   * @param[in,out] commandBuffer The current command buffer queue
    * @param[in] elementBufferOffset The index of first element to draw if index buffer bound
    * @param[in] elementBufferCount Number of elements to draw if index buffer bound, uses whole buffer when 0
    * @return true if the draw command was issued, false otherwise
@@ -135,6 +135,14 @@ public:
             uint32_t                 elementBufferOffset,
             uint32_t                 elementBufferCount);
 
+  /**
+   * @brief Set up the attributes bind commaneds
+   *
+   * @param[in,out] commandBuffer The current command buffer queue
+   * @return true if the bind command was issued, false otherwise
+   */
+  bool BindVertexAttributes(Graphics::CommandBuffer& commandBuffer);
+
 private:
   // VertexBuffers
   Vector<Render::VertexBuffer*> mVertexBuffers;
index 9b8c2c9..45aa582 100644 (file)
@@ -146,6 +146,23 @@ inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
 }
 
+/**
+ * @brief Store latest binded RenderGeometry, and help that we can skip duplicated vertex attributes bind.
+ *
+ * @param[in] geometry Current geometry to be used, or nullptr if render finished
+ * @return True if we can reuse latest binded vertex attributes. False otherwise.
+ */
+inline bool ReuseLatestBindedVertexAttributes(const Render::Geometry* geometry)
+{
+  static const Render::Geometry* gLatestVertexBindedGeometry = nullptr;
+  if(gLatestVertexBindedGeometry == geometry)
+  {
+    return true;
+  }
+  gLatestVertexBindedGeometry = geometry;
+  return false;
+}
+
 } // namespace
 
 namespace Render
@@ -155,6 +172,14 @@ namespace
 MemoryPoolObjectAllocator<Renderer> gRenderRendererMemoryPool;
 }
 
+void Renderer::PrepareCommandBuffer()
+{
+  // Reset latest geometry informations, So we can bind the first of geometry.
+  ReuseLatestBindedVertexAttributes(nullptr);
+
+  // todo : Fill here as many caches as we can store for reduce the number of command buffers
+}
+
 RendererKey Renderer::NewKey(SceneGraph::RenderDataProvider* dataProvider,
                              Render::Geometry*               geometry,
                              uint32_t                        blendingBitmask,
@@ -571,16 +596,25 @@ bool Renderer::Render(Graphics::CommandBuffer&                             comma
   bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
                       // @todo We should detect this case much earlier to prevent unnecessary work
 
-  if(mDrawCommands.empty())
+  // Reuse latest binded vertex attributes location, or Bind buffers to attribute locations.
+  if(ReuseLatestBindedVertexAttributes(mGeometry) || mGeometry->BindVertexAttributes(commandBuffer))
   {
-    drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
+    if(mDrawCommands.empty())
+    {
+      drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
+    }
+    else
+    {
+      for(auto& cmd : commands)
+      {
+        drawn |= mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
+      }
+    }
   }
   else
   {
-    for(auto& cmd : commands)
-    {
-      mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
-    }
+    // BindVertexAttributes failed. Reset cached geometry.
+    ReuseLatestBindedVertexAttributes(nullptr);
   }
 
   return drawn;
index 9f25651..38b0493 100644 (file)
@@ -115,6 +115,11 @@ public:
   };
 
   /**
+   * @brief Global static initialize for Render::Renderer before new CommandBuffer's Render fill start.
+   */
+  static void PrepareCommandBuffer();
+
+  /**
    * Create a new renderer instance
    * @param[in] dataProviders The data providers for the renderer
    * @param[in] geometry The geometry for the renderer