Lock uniform buffer only 1 times per each render + minor fixup of uniforms 81/272981/20
authorEunki, Hong <eunkiki.hong@samsung.com>
Tue, 29 Mar 2022 06:09:08 +0000 (15:09 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 21 Apr 2022 05:53:16 +0000 (14:53 +0900)
1. Don't lock-unlock Graphics::Memory for each properties.
This patch lock stand-alone uniform buffer map and unlock only few times during rendering.
(We called this API as ReadyToLockUniformBuffer and UnlockUniformBuffer)

It will reduce Renderer::Render time near 6%

2. Don't convert from std::string_vew to std::string
when we get uniform map info from shader

3. Make BufferPropertiesFlags as input of UniformBuffer Constructor

Change-Id: I50055a24c1aad59e2a29b8c50485254b71ea5b73
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
12 files changed:
automated-tests/src/dali/utc-Dali-VertexBuffer.cpp
dali/internal/render/common/render-manager.cpp
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/uniform-buffer-manager.cpp
dali/internal/render/renderers/uniform-buffer-manager.h
dali/internal/render/renderers/uniform-buffer-view-pool.cpp
dali/internal/render/renderers/uniform-buffer-view-pool.h
dali/internal/render/renderers/uniform-buffer-view.h
dali/internal/render/renderers/uniform-buffer.cpp
dali/internal/render/renderers/uniform-buffer.h
dali/internal/render/shaders/program.cpp
dali/internal/render/shaders/program.h

index abb8154..153e8c9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -241,9 +241,14 @@ int UtcDaliVertexBufferSetData02(void)
   application.Render();
 
   {
+    const TestGlAbstraction::BufferSubDataCalls& bufferSubDataCalls =
+      application.GetGlAbstraction().GetBufferSubDataCalls();
+
     const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
       application.GetGlAbstraction().GetBufferDataCalls();
 
+    // Should be 1 (Flush standalone uniform buffer per each RenderScene)
+    DALI_TEST_EQUALS(bufferSubDataCalls.size(), 1u, TEST_LOCATION);
     DALI_TEST_EQUALS(bufferDataCalls.size(), 2u, TEST_LOCATION);
 
     DALI_TEST_EQUALS(bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION);
@@ -262,13 +267,13 @@ int UtcDaliVertexBufferSetData02(void)
     const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
       application.GetGlAbstraction().GetBufferDataCalls();
 
-    // Should be 17 (using single uniform buffer now)
-    DALI_TEST_EQUALS(bufferSubDataCalls.size(), 17u, TEST_LOCATION);
+    // Should be 3 (2 Render + 1 vertexBuffer reload)
+    DALI_TEST_EQUALS(bufferSubDataCalls.size(), 3u, TEST_LOCATION);
     DALI_TEST_EQUALS(bufferDataCalls.size(), 3u, TEST_LOCATION);
 
-    if(bufferSubDataCalls.size())
+    if(bufferSubDataCalls.size() >= 2)
     {
-      DALI_TEST_EQUALS(bufferSubDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION);
+      DALI_TEST_EQUALS(bufferSubDataCalls[1], sizeof(texturedQuadVertexData), TEST_LOCATION);
     }
   }
 
index b14261b..d0de5ef 100644 (file)
@@ -768,6 +768,9 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
     clippingRect = Rect<int>();
   }
 
+  // Prepare to lock and map standalone uniform buffer.
+  mImpl->uniformBufferManager->ReadyToLockUniformBuffer(mImpl->renderBufferIndex);
+
   for(uint32_t i = 0; i < count; ++i)
   {
     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
@@ -979,6 +982,10 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
     }
     mainCommandBuffer->EndRenderPass(syncObject);
   }
+
+  // Unlock standalone uniform buffer.
+  mImpl->uniformBufferManager->UnlockUniformBuffer(mImpl->renderBufferIndex);
+
   mImpl->renderAlgorithms.SubmitCommandBuffer();
 
   std::sort(targetstoPresent.begin(), targetstoPresent.end());
index afd7656..40490fb 100644 (file)
@@ -572,13 +572,15 @@ void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::N
     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
 
-    auto maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
-    mUniformIndexMap.Clear();                                                          // Clear contents, but keep memory if we don't change size
-    mUniformIndexMap.Resize(maxMaps);
+    const uint32_t mapCount     = uniformMap.Count();
+    const uint32_t mapNodeCount = uniformMapNode.Count();
+
+    mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
+    mUniformIndexMap.Resize(mapCount + mapNodeCount);
 
     // Copy uniform map into mUniformIndexMap
     uint32_t mapIndex = 0;
-    for(; mapIndex < uniformMap.Count(); ++mapIndex)
+    for(; mapIndex < mapCount; ++mapIndex)
     {
       mUniformIndexMap[mapIndex].propertyValue          = uniformMap[mapIndex].propertyPtr;
       mUniformIndexMap[mapIndex].uniformName            = uniformMap[mapIndex].uniformName;
@@ -587,12 +589,12 @@ void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::N
       mUniformIndexMap[mapIndex].arrayIndex             = uniformMap[mapIndex].arrayIndex;
     }
 
-    for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
+    for(uint32_t nodeMapIndex = 0; nodeMapIndex < mapNodeCount; ++nodeMapIndex)
     {
       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
       auto& name = uniformMapNode[nodeMapIndex].uniformName;
       bool  found(false);
-      for(uint32_t i = 0; i < uniformMap.Count(); ++i)
+      for(uint32_t i = 0; i < mapCount; ++i)
       {
         if(mUniformIndexMap[i].uniformNameHash == hash &&
            mUniformIndexMap[i].uniformName == name)
@@ -642,8 +644,7 @@ void Renderer::WriteUniformBuffer(
   if(uniformBlockAllocationBytes)
   {
     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex);
-
-    uboView = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
+    uboView          = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
   }
 
   // update the uniform buffer
@@ -758,7 +759,7 @@ void Renderer::FillUniformBuffer(Program&                                      p
       if(!uniform.uniformFunc)
       {
         auto uniformInfo  = Graphics::UniformInfo{};
-        auto uniformFound = program.GetUniform(uniform.uniformName.GetCString(),
+        auto uniformFound = program.GetUniform(uniform.uniformName.GetStringView(),
                                                uniform.uniformNameHash,
                                                uniform.uniformNameHashNoArray,
                                                uniformInfo);
index 8342a21..5e04f82 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -19,9 +19,9 @@
 #include <dali/internal/render/renderers/uniform-buffer-manager.h>
 
 // INTERNAL INCLUDES
-#include <dali/internal/render/renderers/uniform-buffer.h>
-#include <dali/internal/render/renderers/uniform-buffer-view.h>
 #include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
+#include <dali/internal/render/renderers/uniform-buffer-view.h>
+#include <dali/internal/render/renderers/uniform-buffer.h>
 
 #include <dali/graphics-api/graphics-buffer-create-info.h>
 #include <dali/graphics-api/graphics-buffer.h>
@@ -31,7 +31,6 @@
 
 namespace Dali::Internal::Render
 {
-
 UniformBufferManager::UniformBufferManager(Dali::Graphics::Controller* controller)
 : mController(controller)
 {
@@ -41,24 +40,28 @@ UniformBufferManager::~UniformBufferManager() = default;
 
 Graphics::UniquePtr<UniformBuffer> UniformBufferManager::AllocateUniformBuffer(uint32_t size, uint32_t alignment)
 {
+  // TODO : Current code only assume CPU_ALLOCATED uniform buffer now
   return Graphics::UniquePtr<UniformBuffer>(
-    new UniformBuffer(mController, size, alignment, true, Dali::Graphics::BufferUsageFlags{0u} | Dali::Graphics::BufferUsage::TRANSFER_DST | Dali::Graphics::BufferUsage::UNIFORM_BUFFER));
+    new UniformBuffer(mController,
+                      size,
+                      alignment,
+                      Dali::Graphics::BufferUsageFlags{0u} | Dali::Graphics::BufferUsage::TRANSFER_DST | Dali::Graphics::BufferUsage::UNIFORM_BUFFER,
+                      Dali::Graphics::BufferPropertiesFlags{0u} | Dali::Graphics::BufferPropertiesFlagBit::CPU_ALLOCATED));
 }
 
-Graphics::UniquePtr<UniformBufferView> UniformBufferManager::CreateUniformBufferView( UniformBuffer* uniformBuffer, uint32_t offset, uint32_t size )
+Graphics::UniquePtr<UniformBufferView> UniformBufferManager::CreateUniformBufferView(UniformBuffer* uniformBuffer, uint32_t offset, uint32_t size)
 {
   // Allocate offset of given UBO (allocation strategy may reuse memory)
-  return Graphics::UniquePtr<UniformBufferView>( new UniformBufferView(*uniformBuffer, offset, size) );
+  return Graphics::UniquePtr<UniformBufferView>(new UniformBufferView(*uniformBuffer, offset, size));
 }
 
 Graphics::UniquePtr<UniformBufferViewPool> UniformBufferManager::CreateUniformBufferViewPool()
 {
   return Graphics::UniquePtr<UniformBufferViewPool>(
-    new UniformBufferViewPool( *this, 1 )
-    );
+    new UniformBufferViewPool(*this, 1));
 }
 
-[[nodiscard]] UniformBufferViewPool* UniformBufferManager::GetUniformBufferViewPool( uint32_t bufferIndex )
+[[nodiscard]] UniformBufferViewPool* UniformBufferManager::GetUniformBufferViewPool(uint32_t bufferIndex)
 {
   if(!mUniformBufferPoolStorage[bufferIndex])
   {
@@ -68,4 +71,14 @@ Graphics::UniquePtr<UniformBufferViewPool> UniformBufferManager::CreateUniformBu
   return mUniformBufferPoolStorage[bufferIndex].get();
 }
 
+void UniformBufferManager::ReadyToLockUniformBuffer(uint32_t bufferIndex)
+{
+  GetUniformBufferViewPool(bufferIndex)->ReadyToLockUniformBuffer();
+}
+
+void UniformBufferManager::UnlockUniformBuffer(uint32_t bufferIndex)
+{
+  GetUniformBufferViewPool(bufferIndex)->UnlockUniformBuffer();
+}
+
 } // namespace Dali::Internal::Render
index cfcaac6..4c651d6 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_UNIFORM_BUFFER_MANAGER_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.
@@ -36,13 +36,12 @@ class UniformBufferViewPool;
 class UniformBufferManager
 {
 public:
-
   explicit UniformBufferManager(Dali::Graphics::Controller* controller);
 
   ~UniformBufferManager();
 
   /**
-   * Allocates uniform buffer with given size and alignment
+   * @brief Allocates uniform buffer with given size and alignment
    * @param size Size of uniform buffer
    * @param alignment Alignment
    * @return new UniformBuffer
@@ -50,23 +49,23 @@ public:
   Graphics::UniquePtr<UniformBuffer> AllocateUniformBuffer(uint32_t size, uint32_t alignment = 256);
 
   /**
-   * Creates a view on UniformBuffer
+   * @brief Creates a view on UniformBuffer
    *
    * @param uniformBuffer
    * @param size
    * @return Uniform buffer view
    */
-  Graphics::UniquePtr<UniformBufferView> CreateUniformBufferView( UniformBuffer* uniformBuffer, uint32_t offset, uint32_t size);
+  Graphics::UniquePtr<UniformBufferView> CreateUniformBufferView(UniformBuffer* uniformBuffer, uint32_t offset, uint32_t size);
 
   /**
-   * Creates uniform buffer pool view
+   * @brief Creates uniform buffer pool view
    * @param size
    * @return
    */
   Graphics::UniquePtr<UniformBufferViewPool> CreateUniformBufferViewPool();
 
   /**
-   * Returns Controller object
+   * @brief Returns Controller object
    * @return controller object
    */
   [[nodiscard]] Graphics::Controller& GetController() const
@@ -75,18 +74,34 @@ public:
   }
 
   /**
-   * Returns embedded uniform buffer pool view for specified DAli buffer index
+   * @brief Returns embedded uniform buffer pool view for specified DAli buffer index
    * @return Pointer to valid uniform buffer pool view
    */
-  [[nodiscard]] UniformBufferViewPool* GetUniformBufferViewPool( uint32_t bufferIndex );
+  [[nodiscard]] UniformBufferViewPool* GetUniformBufferViewPool(uint32_t bufferIndex);
 
-private:
+  /**
+   * @brief Prepare to lock the uniform buffer so we can write to the standalone uniform map directly.
+   * Uniform buffer will be locked at the first call of UniformBuffer::Write after call this API.
+   * @note After all write done, We should call UnlockUniformBuffer.
+   *
+   * @param bufferIndex current update/render buffer index
+   */
+  void ReadyToLockUniformBuffer(uint32_t bufferIndex);
 
+  /**
+   * @brief Unlock the uniform buffer.
+   * @note We should call ReadyToLockUniformBuffer before call this.
+   *
+   * @param bufferIndex current update/render buffer index
+   */
+  void UnlockUniformBuffer(uint32_t bufferIndex);
+
+private:
   Dali::Graphics::Controller* mController;
 
   Graphics::UniquePtr<UniformBufferViewPool> mUniformBufferPoolStorage[2u]; ///< The pool view into UniformBuffer (double buffered)
 };
 
-} // namespace Dali
+} // namespace Dali::Internal::Render
 
 #endif // DALI_INTERNAL_UNIFORM_BUFFER_MANAGER_H
index ef57ea8..6cc5150 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
 #include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
 
 // INTERNAL INCLUDES
-#include <dali/internal/render/renderers/uniform-buffer-manager.h>
-#include <dali/internal/render/renderers/uniform-buffer.h>
-#include <dali/internal/render/renderers/uniform-buffer-view.h>
 #include <dali/graphics-api/graphics-buffer-create-info.h>
 #include <dali/graphics-api/graphics-buffer.h>
+#include <dali/internal/render/renderers/uniform-buffer-manager.h>
+#include <dali/internal/render/renderers/uniform-buffer-view.h>
+#include <dali/internal/render/renderers/uniform-buffer.h>
 
 namespace Dali::Internal::Render
 {
@@ -31,15 +31,15 @@ namespace
 {
 // Default UBO page size set to 32kb
 const uint32_t DEFAULT_UBO_PAGE_SIZE = 32768;
-}
+} // namespace
 
-UniformBufferViewPool::UniformBufferViewPool( UniformBufferManager& manager, uint32_t alignment ) :
-  mUboManager(manager)
+UniformBufferViewPool::UniformBufferViewPool(UniformBufferManager& manager, uint32_t alignment)
+: mUboManager(manager)
 {
   // Create initial UBO
-  mUniformBufferStorage = mUboManager.AllocateUniformBuffer( DEFAULT_UBO_PAGE_SIZE, alignment );
-  mAlignment = alignment;
-  mCurrentOffset = 0;
+  mUniformBufferStorage = mUboManager.AllocateUniformBuffer(DEFAULT_UBO_PAGE_SIZE, alignment);
+  mAlignment            = alignment;
+  mCurrentOffset        = 0;
 }
 
 UniformBufferViewPool::~UniformBufferViewPool() = default;
@@ -52,10 +52,10 @@ void UniformBufferViewPool::Rollback()
   // turn buffer into single allocation by resizing it
   // to current size with invalidation
   auto currentSize = mUniformBufferStorage->GetSize();
-  mUniformBufferStorage->Resize( currentSize ? currentSize : DEFAULT_UBO_PAGE_SIZE, true );
+  mUniformBufferStorage->Resize(currentSize ? currentSize : DEFAULT_UBO_PAGE_SIZE, true);
 }
 
-Graphics::UniquePtr<UniformBufferView> UniformBufferViewPool::CreateUniformBufferView( size_t size )
+Graphics::UniquePtr<UniformBufferView> UniformBufferViewPool::CreateUniformBufferView(size_t size)
 {
   // find new offset
   auto newOffset = ((mCurrentOffset + size) / mAlignment) * mAlignment;
@@ -65,20 +65,19 @@ Graphics::UniquePtr<UniformBufferView> UniformBufferViewPool::CreateUniformBuffe
   }
 
   // resize Ubo if needed
-  if( newOffset >= mUniformBufferStorage->GetSize())
+  if(newOffset >= mUniformBufferStorage->GetSize())
   {
     // move offset to the new buffer
     mCurrentOffset = mUniformBufferStorage->GetSize();
-    newOffset = ((mCurrentOffset + size) / mAlignment) * mAlignment;
-
-    // Adjust current offset so the view doesn't intersect multiple buffers
-    auto prevSize = mUniformBufferStorage->GetSize();
-    if(mCurrentOffset + size >= prevSize )
+    newOffset      = ((mCurrentOffset + size) / mAlignment) * mAlignment;
+    if(mAlignment > 1 && newOffset < mCurrentOffset + size)
     {
-      mCurrentOffset = prevSize;
-      newOffset = ((mCurrentOffset + size) / mAlignment) * mAlignment;
+      newOffset += mAlignment;
     }
-    mUniformBufferStorage->Resize( mUniformBufferStorage->GetSize()+DEFAULT_UBO_PAGE_SIZE, false );
+
+    size_t increaseBufferStorageSize = DALI_LIKELY(size > 0) ? ((size - 1) / DEFAULT_UBO_PAGE_SIZE + 1) * DEFAULT_UBO_PAGE_SIZE : DEFAULT_UBO_PAGE_SIZE;
+
+    mUniformBufferStorage->Resize(mUniformBufferStorage->GetSize() + increaseBufferStorageSize, false);
   }
 
   // create buffer view from
@@ -90,4 +89,14 @@ Graphics::UniquePtr<UniformBufferView> UniformBufferViewPool::CreateUniformBuffe
   return uboView;
 }
 
+void UniformBufferViewPool::ReadyToLockUniformBuffer()
+{
+  mUniformBufferStorage->ReadyToLockUniformBuffer();
+}
+
+void UniformBufferViewPool::UnlockUniformBuffer()
+{
+  mUniformBufferStorage->UnlockUniformBuffer();
+}
+
 } // namespace Dali::Internal::Render
\ No newline at end of file
index 9318f39..8f7a1bd 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_UNIFORM_BUFFER_VIEW_POOL_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.
@@ -27,7 +27,6 @@
 
 namespace Dali::Internal::Render
 {
-
 class UniformBufferManager;
 class UniformBufferView;
 class UniformBuffer;
@@ -53,26 +52,33 @@ class UniformBufferViewPool
   friend class UniformBufferManager;
 
 private:
-
-  UniformBufferViewPool( UniformBufferManager& manager, uint32_t alignment );
+  UniformBufferViewPool(UniformBufferManager& manager, uint32_t alignment);
 
 public:
-
   ~UniformBufferViewPool();
 
   /**
-   * Rolls back allocation to the beginning of pool
+   * @brief Rolls back allocation to the beginning of pool
    */
   void Rollback();
 
   /**
-   * Creates view for next free chunk of UBO memory of specified size.
+   * @brief Creates view for next free chunk of UBO memory of specified size.
    */
-  Graphics::UniquePtr<UniformBufferView> CreateUniformBufferView( size_t size );
+  Graphics::UniquePtr<UniformBufferView> CreateUniformBufferView(size_t size);
 
-private:
+  /**
+   * @copydoc Dali::Internal::Render::UniformBufferManager::ReadyToLockUniformBuffer
+   */
+  void ReadyToLockUniformBuffer();
 
-  UniformBufferManager& mUboManager;
+  /**
+   * @copydoc Dali::Internal::Render::UniformBufferManager::UnlockUniformBuffer
+   */
+  void UnlockUniformBuffer();
+
+private:
+  UniformBufferManager&              mUboManager;
   Graphics::UniquePtr<UniformBuffer> mUniformBufferStorage;
 
   uint32_t mAlignment; // 1 for tightly packed emulated UBO
index 2e6a608..dfe8c23 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_UNIFORM_BUFFER_VIEW_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.
@@ -30,7 +30,6 @@ class Buffer;
 }
 namespace Internal::Render
 {
-
 class UniformBuffer;
 
 /**
@@ -48,15 +47,23 @@ class UniformBuffer;
 class UniformBufferView
 {
 public:
-
-  UniformBufferView(UniformBuffer &ubo, uint32_t offset, size_t size);
+  UniformBufferView(UniformBuffer& ubo, uint32_t offset, size_t size);
 
   ~UniformBufferView();
 
-  void Write(const void *data, uint32_t size, uint32_t offset);
+  /**
+   * @brief Writes data into the current uniform buffer view.
+   * @note We prefer to call UniformBuffer::ReadyToLockUniformBuffer before call Write API.
+   * And also, prefer to call UniformBuffer::UnlockUniformBuffer if current frame's all Write API action done.
+   *
+   * @param[in] data pointer to the source data
+   * @param[in] size size of source data
+   * @param[in] offset destination offset
+   */
+  void Write(const void* data, uint32_t size, uint32_t offset);
 
   /**
-   * Returns the size of the view
+   * @brief Returns the size of the view
    *
    * @return size of view
    */
@@ -66,7 +73,7 @@ public:
   }
 
   /**
-   * Returns the offset within the UBO
+   * @brief Returns the offset within the UBO
    * @return Offset
    */
   [[nodiscard]] uint32_t GetOffset() const
@@ -75,7 +82,7 @@ public:
   }
 
   /**
-   * Returns Graphics buffer associated with this View
+   * @brief Returns Graphics buffer associated with this View
    *
    * If 'relativeOffset' isn't nullptr then the offset into the individual
    * Graphics::Buffer is written.
@@ -84,13 +91,12 @@ public:
    *
    * @return Pointer to a valid Graphics::Buffer object
    */
-  [[nodiscard]] Graphics::Buffer *GetBuffer(uint32_t *relativeOffset = nullptr);
+  [[nodiscard]] Graphics::Buffer* GetBuffer(uint32_t* relativeOffset = nullptr);
 
 private:
-
-  UniformBuffer *mUniformBuffer{nullptr}; ///< UniformBuffer that the view views
-  uint32_t mOffset{0u}; ///< Offset within the buffer
-  size_t   mSize{0u}; ///< Size of view
+  UniformBuffer* mUniformBuffer{nullptr}; ///< UniformBuffer that the view views
+  uint32_t       mOffset{0u};             ///< Offset within the buffer
+  size_t         mSize{0u};               ///< Size of view
 };
 } // Namespace Internal::Render
 } // Namespace Dali
index c944880..5787c68 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
 // CLASS HEADER
 #include <dali/internal/render/renderers/uniform-buffer.h>
 
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+#ifdef DEBUG_ENABLED
+Debug::Filter* gUniformBufferLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_UNIFORM_BUFFER");
+#endif
+
 namespace Dali::Internal::Render
 {
-UniformBuffer::UniformBuffer(Dali::Graphics::Controller* controller,
-                             uint32_t                    sizeInBytes,
-                             uint32_t                    alignment,
-                             bool                        persistentMappedEnabled,
-                             Graphics::BufferUsageFlags  usageFlags)
-  : mController(controller),
-    mSize(0u),
-    mUsageFlags(usageFlags)
+namespace
+{
+static constexpr uint32_t INVALID_BUFFER_INDEX = std::numeric_limits<uint32_t>::max();
+}
+UniformBuffer::UniformBuffer(Dali::Graphics::Controller*     controller,
+                             uint32_t                        sizeInBytes,
+                             uint32_t                        alignment,
+                             Graphics::BufferUsageFlags      usageFlags,
+                             Graphics::BufferPropertiesFlags propertiesFlags)
+: mController(controller),
+  mSize(0u),
+  mUsageFlags(usageFlags),
+  mPropertiesFlags(propertiesFlags),
+  mLockedBufferIndex(INVALID_BUFFER_INDEX),
+  mLockedPtr(nullptr),
+  mReadyToBeLocked(false)
 {
   mAlignment = alignment;
   if(sizeInBytes)
@@ -39,7 +54,7 @@ UniformBuffer::UniformBuffer(Dali::Graphics::Controller* controller,
 UniformBuffer::~UniformBuffer()
 {
   // Unmap and flush all allocated buffers
-  for( auto i = 0u; i < mBuffers.size(); ++i)
+  for(auto i = 0u; i < mBuffers.size(); ++i)
   {
     Flush(i);
     Unmap(i);
@@ -48,6 +63,7 @@ UniformBuffer::~UniformBuffer()
 
 void UniformBuffer::Flush(uint32_t bufferIndex)
 {
+  DALI_LOG_INFO(gUniformBufferLogFilter, Debug::General, "Flush (bufferIndex : %d / %d [%d])\n", bufferIndex, mBuffers.size(), mSize);
   const auto& buffer = mBuffers[bufferIndex];
   if(buffer.buffer && buffer.memory)
   {
@@ -55,8 +71,15 @@ void UniformBuffer::Flush(uint32_t bufferIndex)
   }
 }
 
-void UniformBuffer::Resize( uint32_t newSize, bool invalidate )
+void UniformBuffer::Resize(uint32_t newSize, bool invalidate)
 {
+  // Adjust alignment, the alignment is needed for
+  // real UBOs (it should be given by the buffer requirements)
+  if(DALI_LIKELY(mAlignment && newSize > 0))
+  {
+    newSize = (((newSize - 1) / mAlignment) + 1) * mAlignment;
+  }
+
   // The buffer is already optimal
   if(newSize == mSize && !invalidate)
   {
@@ -67,26 +90,39 @@ void UniformBuffer::Resize( uint32_t newSize, bool invalidate )
     return;
   }
 
+  if(DALI_UNLIKELY(mReadyToBeLocked))
+  {
+    DALI_LOG_INFO(gUniformBufferLogFilter, Debug::Verbose, "Resize %d --> %d with %s [mBuffers : %d] during lock (lockedBufferIndex : %d, lockedPtr : %p)\n", mSize, newSize, invalidate ? "Invalidate" : "Rendering", mBuffers.size(), mLockedBufferIndex, mLockedPtr);
+  }
+  else
+  {
+    DALI_LOG_INFO(gUniformBufferLogFilter, Debug::Verbose, "Resize %d --> %d with %s [mBuffers : %d]\n", mSize, newSize, invalidate ? "Invalidate" : "Rendering", mBuffers.size());
+  }
+
   // Throw away content
   if(invalidate)
   {
+    if(mReadyToBeLocked)
+    {
+      UnlockUniformBuffer();
+      mReadyToBeLocked = true;
+    }
+    // Flush and unmap all allocated buffers
+    for(auto i = 0u; i < mBuffers.size(); ++i)
+    {
+      Flush(i);
+      Unmap(i);
+    }
     mBuffers.clear();
     mSize = 0;
   }
 
-  // Adjust alignment, the alignment is needed for
-  // real UBOs (it should be given by the buffer requirements)
-  if(mAlignment)
-  {
-    newSize = ((newSize / mAlignment)+1)*mAlignment;
-  }
-
   if(newSize > mSize)
   {
     auto createInfo = Graphics::BufferCreateInfo()
-      .SetSize(newSize - mSize)
-      .SetBufferPropertiesFlags(0 | Graphics::BufferPropertiesFlagBit::CPU_ALLOCATED)
-      .SetUsage(mUsageFlags);
+                        .SetSize(newSize - mSize)
+                        .SetBufferPropertiesFlags(mPropertiesFlags)
+                        .SetUsage(mUsageFlags);
 
     auto buffer = mController->CreateBuffer(createInfo, nullptr);
 
@@ -94,20 +130,35 @@ void UniformBuffer::Resize( uint32_t newSize, bool invalidate )
 
     mSize = newSize;
   }
-}
 
+  // If invalidate during locked, begin lock again.
+  if(DALI_UNLIKELY(invalidate && mReadyToBeLocked))
+  {
+    mReadyToBeLocked = false;
+    ReadyToLockUniformBuffer();
+  }
 
-const UniformBuffer::GfxBuffer* UniformBuffer::GetBufferByOffset( uint32_t offset, uint32_t* newOffset, uint32_t* outBufferIndex ) const
+  if(DALI_UNLIKELY(mReadyToBeLocked))
+  {
+    DALI_LOG_INFO(gUniformBufferLogFilter, Debug::Verbose, "Resize done as %d with %s [mBuffers : %d] during lock (lockedBufferIndex : %d, lockedPtr : %p)\n", newSize, invalidate ? "Invalidate" : "Rendering", mBuffers.size(), mLockedBufferIndex, mLockedPtr);
+  }
+  else
+  {
+    DALI_LOG_INFO(gUniformBufferLogFilter, Debug::Verbose, "Resize done as %d with %s [mBuffers : %d]\n", newSize, invalidate ? "Invalidate" : "Rendering", mBuffers.size());
+  }
+}
+
+const UniformBuffer::GfxBuffer* UniformBuffer::GetBufferByOffset(uint32_t offset, uint32_t* newOffset, uint32_t* outBufferIndex) const
 {
   uint32_t bufferOffset = offset;
-  uint32_t bufferIndex = 0u;
+  uint32_t bufferIndex  = 0u;
 
   // Find buffer if UBO is fragmented
   if(mBuffers.size() > 1)
   {
     for(const auto& buffer : mBuffers)
     {
-      if( bufferOffset >= buffer.createInfo.size)
+      if(bufferOffset >= buffer.createInfo.size)
       {
         bufferOffset -= buffer.createInfo.size;
       }
@@ -131,6 +182,8 @@ const UniformBuffer::GfxBuffer* UniformBuffer::GetBufferByOffset( uint32_t offse
     *newOffset = bufferOffset;
   }
 
+  DALI_LOG_INFO(gUniformBufferLogFilter, Debug::Verbose, "GetBufferByOffset (bufferIndex : %d / %d [%d], bufferOffset : %d, Graphics::BufferPtr : %p)\n", bufferIndex, mBuffers.size(), mSize, bufferOffset, bufferDesc.buffer.get());
+
   return &bufferDesc;
 }
 
@@ -138,14 +191,14 @@ void UniformBuffer::Write(const void* data, uint32_t size, uint32_t dstOffset)
 {
   // find which buffer we want to write into
   uint32_t bufferOffset = dstOffset;
-  uint32_t bufferIndex = 0u;
+  uint32_t bufferIndex  = 0u;
 
   // Find buffer if UBO is fragmented
   if(mBuffers.size() > 1)
   {
     for(const auto& buffer : mBuffers)
     {
-      if( bufferOffset >= buffer.createInfo.size)
+      if(bufferOffset >= buffer.createInfo.size)
       {
         bufferOffset -= buffer.createInfo.size;
       }
@@ -165,36 +218,58 @@ void UniformBuffer::Write(const void* data, uint32_t size, uint32_t dstOffset)
     bufferDesc.needsUpdate = false;
   }
 
-  DALI_ASSERT_ALWAYS( mBuffers.size() > bufferIndex );
-  DALI_ASSERT_ALWAYS( mBuffers[bufferIndex].buffer );
-  DALI_ASSERT_ALWAYS( mBuffers[bufferIndex].createInfo.size > bufferOffset + size );
+  DALI_ASSERT_ALWAYS(mBuffers.size() > bufferIndex);
+  DALI_ASSERT_ALWAYS(mBuffers[bufferIndex].buffer);
+  DALI_ASSERT_ALWAYS(mBuffers[bufferIndex].createInfo.size > bufferOffset + size);
 
-  bool locallyMapped = (bufferDesc.mappedPtr != nullptr);
+  const bool locallyMapped = (bufferDesc.mappedPtr != nullptr);
   if(!locallyMapped)
   {
     // Map once and keep it
-    Map( bufferIndex );
+    Map(bufferIndex);
   }
 
   if(bufferDesc.memory)
   {
-    void* ptr = bufferDesc.memory->LockRegion(bufferOffset, size);
-    if(ptr && bufferOffset + size < mSize)
+    // Rarely happened that we use over the locked memory
+    // Unlock previous buffer, and lock as current bufferIndex again
+    if(DALI_UNLIKELY(mLockedBufferIndex != bufferIndex))
     {
-      // size always divides by 4 (std140 alignment rules, so we can replace memcpy with unrolled assignments)
-      auto ptr32 = reinterpret_cast<uint32_t*>(ptr);
-      auto data32 = reinterpret_cast<const uint32_t*>(data);
-      for(auto i = 0u; i < size; i +=4 )
+      DALI_LOG_INFO(gUniformBufferLogFilter, Debug::General, "Unlock (lockedBufferIndex : %d / %d [%d], lockedPtr : %p)\n", mLockedBufferIndex, mBuffers.size(), mSize, mLockedPtr);
+
+      // mLockedBufferIndex == INVALID_BUFFER_INDEX only first time of current RenderScene.
+      if(DALI_LIKELY(mLockedBufferIndex != INVALID_BUFFER_INDEX))
+      {
+        // Unlock previous memory
+        if(mBuffers[mLockedBufferIndex].memory)
+        {
+          mBuffers[mLockedBufferIndex].memory->Unlock(true);
+        }
+      }
+      mLockedBufferIndex = bufferIndex;
+      mLockedPtr         = nullptr;
+
+      // Initial mapping done previously. Just lock and roll now.
+      if(mBuffers[mLockedBufferIndex].memory)
       {
-        *ptr32++ = *data32++;;
+        mLockedPtr = reinterpret_cast<uint8_t*>(mBuffers[mLockedBufferIndex].memory->LockRegion(0, mBuffers[mLockedBufferIndex].createInfo.size));
       }
+      DALI_LOG_INFO(gUniformBufferLogFilter, Debug::General, "Lock (lockedBufferIndex : %d / %d [%d], lockedPtr : %p)\n", mLockedBufferIndex, mBuffers.size(), mSize, mLockedPtr);
+    }
+
+    DALI_LOG_INFO(gUniformBufferLogFilter, Debug::Verbose, "memcpy (lockedBufferIndex : %d / %d [%d], lockedPtr : %p, offset : %d, size : %d, lockedBufferSize : %d)\n", mLockedBufferIndex, mBuffers.size(), mSize, mLockedPtr, bufferOffset, size, mBuffers[mLockedBufferIndex].createInfo.size);
+
+    // We already check validation of buffer range. We can assume that bufferOffset + size <= mBuffers[mLockedBufferIndex].createInfo.size
+    if(mLockedPtr)
+    {
+      memcpy(mLockedPtr + bufferOffset, data, size);
     }
-    bufferDesc.memory->Unlock(true);
   }
 }
 
-void UniformBuffer::Map( uint32_t bufferIndex)
+void UniformBuffer::Map(uint32_t bufferIndex)
 {
+  DALI_LOG_INFO(gUniformBufferLogFilter, Debug::General, "Map (bufferIndex : %d / %d [%d])\n", bufferIndex, mBuffers.size(), mSize);
   auto& buffer = mBuffers[bufferIndex];
 
   if(buffer.needsUpdate)
@@ -206,20 +281,59 @@ void UniformBuffer::Map( uint32_t bufferIndex)
   if(!buffer.memory)
   {
     Graphics::MapBufferInfo info{};
-    info.buffer = buffer.buffer.get();
-    info.usage  = 0 | Graphics::MemoryUsageFlagBits::WRITE;
-    info.offset = 0;
-    info.size   = buffer.createInfo.size;
+    info.buffer   = buffer.buffer.get();
+    info.usage    = 0 | Graphics::MemoryUsageFlagBits::WRITE;
+    info.offset   = 0;
+    info.size     = buffer.createInfo.size;
     buffer.memory = mController->MapBufferRange(info);
+    DALI_LOG_INFO(gUniformBufferLogFilter, Debug::Verbose, "GraphicsMemoryMapped (bufferIndex : %d / %d [%d], size : %d)\n", bufferIndex, mBuffers.size(), mSize, info.size);
   }
 }
 
-void UniformBuffer::Unmap( uint32_t bufferIndex)
+void UniformBuffer::Unmap(uint32_t bufferIndex)
 {
+  DALI_LOG_INFO(gUniformBufferLogFilter, Debug::General, "Unmap (bufferIndex : %d / %d [%d])\n", bufferIndex, mBuffers.size(), mSize);
   auto& buffer = mBuffers[bufferIndex];
   if(buffer.memory)
   {
     mController->UnmapMemory(std::move(buffer.memory));
   }
 }
-}
\ No newline at end of file
+
+void UniformBuffer::ReadyToLockUniformBuffer()
+{
+  DALI_LOG_INFO(gUniformBufferLogFilter, Debug::General, "LockUniformBuffer\n");
+  if(DALI_UNLIKELY(mReadyToBeLocked && mLockedBufferIndex != INVALID_BUFFER_INDEX))
+  {
+    // Unlock previous locked buffer first
+    DALI_LOG_ERROR("Warning! : called LockUniformBuffer() before called UnlockUniformBuffer()!\n");
+    UnlockUniformBuffer();
+  }
+
+  mReadyToBeLocked   = true;
+  mLockedBufferIndex = INVALID_BUFFER_INDEX;
+  mLockedPtr         = nullptr;
+}
+
+void UniformBuffer::UnlockUniformBuffer()
+{
+  DALI_LOG_INFO(gUniformBufferLogFilter, Debug::General, "UnlockUniformBuffer (lockedBufferIndex : %d / %d [%d], lockedPtr : %p)\n", mLockedBufferIndex, mBuffers.size(), mSize, mLockedPtr);
+  if(mReadyToBeLocked && mLockedBufferIndex != INVALID_BUFFER_INDEX)
+  {
+    auto& bufferDesc = mBuffers[mLockedBufferIndex];
+    if(bufferDesc.memory)
+    {
+      bufferDesc.memory->Unlock(true);
+    }
+    // Flush all allocated buffers
+    for(auto i = 0u; i < mBuffers.size(); ++i)
+    {
+      Flush(i);
+    }
+  }
+  mLockedPtr         = nullptr;
+  mLockedBufferIndex = INVALID_BUFFER_INDEX;
+  mReadyToBeLocked   = false;
+}
+
+} // namespace Dali::Internal::Render
\ No newline at end of file
index d665492..4f83bbd 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_UNIFORM_BUFFER_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.
@@ -49,14 +49,14 @@ private:
    * @param[in] mController Pointer of the graphics controller
    * @param[in] sizeInBytes initial size of allocated buffer
    * @param[in] alignment memory alignment in bytes
-   * @param[in] persistentMappingEnabled if true, buffer is mapped persistently
    * @param[in] usageFlags type of usage ( Graphics::BufferUsage )
+   * @param[in] propertiesFlags buffer properties (Gracphis::BufferPropertiesFlags)
    */
-  UniformBuffer(Dali::Graphics::Controller* mController,
-                uint32_t                    sizeInBytes,
-                uint32_t                    alignment,
-                bool                        persistentMappingEnabled,
-                Graphics::BufferUsageFlags  usageFlags);
+  UniformBuffer(Dali::Graphics::Controller*     mController,
+                uint32_t                        sizeInBytes,
+                uint32_t                        alignment,
+                Graphics::BufferUsageFlags      usageFlags,
+                Graphics::BufferPropertiesFlags propertiesFlags);
 
 public:
   /**
@@ -65,7 +65,9 @@ public:
   ~UniformBuffer();
 
   /**
-   * Writes data into the buffer
+   * @brief Writes data into the buffer
+   * @note We prefer to call ReadyToLockUniformBuffer before call Write API.
+   * And also, prefer to call UnlockUniformBuffer if current frame's all Write API action done.
    *
    * @param[in] data pointer to the source data
    * @param[in] size size of source data
@@ -74,14 +76,14 @@ public:
   void Write(const void* data, uint32_t size, uint32_t offset);
 
   /**
-   * Flushes whole buffer range
+   * @brief Flushes whole buffer range
    *
    * @param[in] bufferIndex Index of Graphics::Buffer
    */
-  void Flush( uint32_t bufferIndex = 0);
+  void Flush(uint32_t bufferIndex = 0);
 
   /**
-   * Returns allocated ( requested ) size
+   * @brief Returns allocated ( requested ) size
    * @return size of buffer
    */
   [[nodiscard]] uint32_t GetSize() const
@@ -90,33 +92,33 @@ public:
   }
 
   /**
-   * Return Graphics::Buffer object at specified array index
+   * @brief Return Graphics::Buffer object at specified array index
    *
    * @param[in] bufferIndex index of Graphics buffer
    *
    * @return pointer to the buffer object
    */
-  [[nodiscard]] Dali::Graphics::Buffer* GetBuffer( uint32_t bufferIndex ) const
+  [[nodiscard]] Dali::Graphics::Buffer* GetBuffer(uint32_t bufferIndex) const
   {
     return mBuffers[bufferIndex].buffer.get();
   }
 
   /**
-   * Maps individual Graphics buffer memory
+   * @brief Maps individual Graphics buffer memory
    *
    * @param[in] bufferIndex index of Graphics buffer
    */
-  void Map( uint32_t bufferIndex = 0);
+  void Map(uint32_t bufferIndex = 0);
 
   /**
    * Unmaps individual Graphics buffer memory
    *
    * @param[in] bufferIndex index of Graphics buffer
    */
-  void Unmap( uint32_t bufferIndex = 0);
+  void Unmap(uint32_t bufferIndex = 0);
 
   /**
-   * Resizes the buffer
+   * @brief Resizes the buffer
    *
    * The resize strategy depends on 'invalidate' parameter.
    *
@@ -131,55 +133,67 @@ public:
    * @param[in] invalidate specifies whether the content should be discarded
    *
    */
-  void Resize( uint32_t newSize, bool invalidate );
+  void Resize(uint32_t newSize, bool invalidate);
 
-private:
+  /**
+   * @copydoc Dali::Internal::Render::UniformBufferViewPool::ReadyToLockUniformBuffer
+   */
+  void ReadyToLockUniformBuffer();
 
   /**
-   * GfxBuffer wraps single GPU buffer and encapsulates individual
+   * @copydoc Dali::Internal::Render::UniformBufferViewPool::UnlockUniformBuffer
+   */
+  void UnlockUniformBuffer();
+
+private:
+  /**
+   * @brief GfxBuffer wraps single GPU buffer and encapsulates individual
    * buffer mapping and create info details.
    *
    * The array of GfxBuffers makes a single UniformBuffer.
    */
   struct GfxBuffer
   {
-    GfxBuffer() = default;
-    ~GfxBuffer() = default;
-    GfxBuffer( GfxBuffer&& ) = default;
-    GfxBuffer(Graphics::UniquePtr<Graphics::Buffer>&& b, const Graphics::BufferCreateInfo& i) :
-      buffer(std::move(b)),
+    GfxBuffer()            = default;
+    ~GfxBuffer()           = default;
+    GfxBuffer(GfxBuffer&&) = default;
+    GfxBuffer(Graphics::UniquePtr<Graphics::Buffer>&& b, const Graphics::BufferCreateInfo& i)
+    : buffer(std::move(b)),
       createInfo(i)
     {
     }
 
-    Graphics::UniquePtr<Graphics::Buffer> buffer{}; ///< Graphics buffer
-    Graphics::UniquePtr<Graphics::Memory> memory{}; ///< Mapped memory associated with buffer
-    Graphics::BufferCreateInfo createInfo{}; ///< create info describing the buffer
-    void* mappedPtr{}; ///< Mapped pointer (if mapped)
-    bool needsUpdate{true}; ///< Indicates whether the buffer needs flushing the queue
+    Graphics::UniquePtr<Graphics::Buffer> buffer{};          ///< Graphics buffer
+    Graphics::UniquePtr<Graphics::Memory> memory{};          ///< Mapped memory associated with buffer
+    Graphics::BufferCreateInfo            createInfo{};      ///< create info describing the buffer
+    void*                                 mappedPtr{};       ///< Mapped pointer (if mapped)
+    bool                                  needsUpdate{true}; ///< Indicates whether the buffer needs flushing the queue
   };
 
   /**
-   * Returns GfxBuffer object by offset
+   * @brief Returns GfxBuffer object by offset
    *
    * The memory of UniformBuffer is considered to be continuous, however,
    * it may contain multiple graphics buffers.
    *
    */
-  const GfxBuffer* GetBufferByOffset( uint32_t offset, uint32_t* newOffset, uint32_t* bufferIndex ) const;
+  const GfxBuffer* GetBufferByOffset(uint32_t offset, uint32_t* newOffset, uint32_t* bufferIndex) const;
 
   std::vector<GfxBuffer> mBuffers; ///< List of GfxBuffer objects
 
   Dali::Graphics::Controller* mController; ///< Pointer to the controller
 
-  uint32_t mSize;        ///< Current size of buffer
+  uint32_t mSize;         ///< Current size of buffer
   uint32_t mAlignment{0}; ///< Buffer alignment
 
-  Graphics::BufferUsageFlags mUsageFlags;
+  Graphics::BufferUsageFlags      mUsageFlags;
+  Graphics::BufferPropertiesFlags mPropertiesFlags;
 
-  bool mValid{false};
+  uint32_t mLockedBufferIndex;   ///< Current locked buffer region index.
+  uint8_t* mLockedPtr;           ///< Current locked buffer pointer.
+  bool     mReadyToBeLocked : 1; ///< True if current uniform buffer is ready to be locked.
 };
 
-}
+} // namespace Dali::Internal::Render
 
 #endif //DALI_INTERNAL_UNIFORM_BUFFER_H
index 1b899fe..4cfbcb4 100644 (file)
@@ -190,7 +190,7 @@ void Program::SetGraphicsProgram(Graphics::UniquePtr<Graphics::Program>&& progra
   BuildReflection(mGfxController.GetProgramReflection(*mGfxProgram.get()));
 }
 
-bool Program::GetUniform(const std::string& name, Hash hashedName, Hash hashedNameNoArray, Graphics::UniformInfo& out) const
+bool Program::GetUniform(const std::string_view& name, Hash hashedName, Hash hashedNameNoArray, Graphics::UniformInfo& out) const
 {
   if(mReflection.empty())
   {
@@ -204,23 +204,21 @@ bool Program::GetUniform(const std::string& name, Hash hashedName, Hash hashedNa
 
   // If the name contains a "]" anywhere but the end, it's a structure element. The reflection
   // does contain such elements, so use normal hash.
-  Hash               hash  = hashedName;
-  const std::string* match = &name;
+  Hash             hash  = hashedName;
+  std::string_view match = name;
 
-  std::string baseName;
   if(!name.empty() && name.back() == ']')
   {
     hash     = hashedNameNoArray;
     auto pos = name.rfind("[");
-    baseName = name.substr(0, pos - 1); // Remove subscript
-    match    = &baseName;
+    match    = name.substr(0, pos - 1); // Remove subscript
   }
 
   for(const ReflectionUniformInfo& item : mReflection)
   {
     if(item.hashValue == hash)
     {
-      if(!item.hasCollision || item.uniformInfo.name == *match)
+      if(!item.hasCollision || item.uniformInfo.name == match)
       {
         out = item.uniformInfo;
         return true;
index 0d22e62..09c5ff8 100644 (file)
@@ -141,7 +141,7 @@ public:
    *
    * @return False when uniform is not found or due to hash collision the result is ambiguous
    */
-  bool GetUniform(const std::string& name, Hash hashedName, Hash hashedNameNoArray, Graphics::UniformInfo& out) const;
+  bool GetUniform(const std::string_view& name, Hash hashedName, Hash hashedNameNoArray, Graphics::UniformInfo& out) const;
 
   /**
    * Retrieves default uniform