Added GLES command buffer pool 71/260971/8
authorAdam Bialogonski <adam.b@samsung.com>
Wed, 7 Jul 2021 14:57:25 +0000 (15:57 +0100)
committerAdam Bialogonski <adam.b@samsung.com>
Mon, 12 Jul 2021 10:04:12 +0000 (11:04 +0100)
Added GLES command buffer pool to improve internal
commands and transient memory allocation

Change-Id: Iad386cdf8fd88aa7b7676df706163e87b6eb74ba

dali/internal/graphics/gles-impl/egl-graphics-controller-debug.cpp
dali/internal/graphics/gles-impl/egl-graphics-controller.cpp
dali/internal/graphics/gles-impl/egl-graphics-controller.h
dali/internal/graphics/gles-impl/gles-context.cpp
dali/internal/graphics/gles-impl/gles-context.h
dali/internal/graphics/gles-impl/gles-graphics-command-buffer.cpp
dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h
dali/internal/graphics/gles-impl/gles-graphics-types.h

index ff11704..9ee5721 100644 (file)
@@ -86,9 +86,12 @@ std::string DumpStencilOp(Graphics::StencilOp stencilOp)
 
 void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer)
 {
-  bool first{true};
-  for(auto& cmd : commandBuffer->GetCommands())
+  bool       first{true};
+  uint32_t   count   = 0u;
+  const auto command = commandBuffer->GetCommands(count);
+  for(auto i = 0u; i < count; ++i)
   {
+    auto& cmd = command[i];
     if(!first)
     {
       fprintf(output, ",");
@@ -251,8 +254,9 @@ void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer)
                 cmd.beginRenderPass.renderArea.height);
         fprintf(output, "\"clearValues\":[");
         bool firstV = true;
-        for(auto& value : cmd.beginRenderPass.clearValues)
+        for(auto i = 0u; i < cmd.beginRenderPass.clearValuesCount; ++i)
         {
+          auto value = cmd.beginRenderPass.clearValues.Ptr()[i];
           if(!firstV)
           {
             fprintf(output, ",");
@@ -277,14 +281,15 @@ void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer)
       {
         fprintf(output, "{\"Cmd\":\"EXECUTE_COMMAND_BUFFERS\",\n\"buffers\":[");
         bool firstBuf{true};
-        for(auto& buf : cmd.executeCommandBuffers.buffers)
+        for(auto i = 0u; i < cmd.executeCommandBuffers.buffersCount; ++i)
         {
+          const auto buf = cmd.executeCommandBuffers.buffers.Ptr()[i];
           if(!firstBuf)
           {
             fprintf(output, ", ");
           }
           firstBuf = false;
-          DumpCommandBuffer(output, static_cast<const GLES::CommandBuffer*>(buf));
+          DumpCommandBuffer(output, buf);
         }
         fprintf(output, "]\n}");
         break;
index bd0d499..eec74af 100644 (file)
@@ -144,11 +144,20 @@ void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
 
 void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
 {
-  // Use command buffer to execute presentation (we should pool it)
-  CommandBufferCreateInfo info;
-  info.SetLevel(CommandBufferLevel::PRIMARY);
-  info.fixedCapacity        = 1; // only one command
-  auto presentCommandBuffer = new GLES::CommandBuffer(info, *this);
+  GLES::CommandBuffer* presentCommandBuffer{nullptr};
+  if(mPresentationCommandBuffers.empty())
+  {
+    CommandBufferCreateInfo info;
+    info.SetLevel(CommandBufferLevel::PRIMARY);
+    info.fixedCapacity   = 1; // only one command
+    presentCommandBuffer = new GLES::CommandBuffer(info, *this);
+  }
+  else
+  {
+    presentCommandBuffer = const_cast<GLES::CommandBuffer*>(mPresentationCommandBuffers.front());
+    presentCommandBuffer->Reset();
+    mPresentationCommandBuffers.pop();
+  }
   presentCommandBuffer->PresentRenderTarget(static_cast<GLES::RenderTarget*>(renderTarget));
   SubmitInfo submitInfo;
   submitInfo.cmdBuffer = {presentCommandBuffer};
@@ -368,8 +377,11 @@ void EglGraphicsController::ProcessCreateQueues()
 
 void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer)
 {
-  for(auto& cmd : commandBuffer.GetCommands())
+  auto       count    = 0u;
+  const auto commands = commandBuffer.GetCommands(count);
+  for(auto i = 0u; i < count; ++i)
   {
+    auto& cmd = commands[i];
     // process command
     switch(cmd.type)
     {
@@ -380,19 +392,19 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
       }
       case GLES::CommandType::BIND_TEXTURES:
       {
-        mCurrentContext->BindTextures(cmd.bindTextures.textureBindings);
+        mCurrentContext->BindTextures(cmd.bindTextures.textureBindings.Ptr(), cmd.bindTextures.textureBindingsCount);
         break;
       }
       case GLES::CommandType::BIND_VERTEX_BUFFERS:
       {
-        auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
-        mCurrentContext->BindVertexBuffers(bindings);
+        auto bindings = cmd.bindVertexBuffers.vertexBufferBindings.Ptr();
+        mCurrentContext->BindVertexBuffers(bindings, cmd.bindVertexBuffers.vertexBufferBindingsCount);
         break;
       }
       case GLES::CommandType::BIND_UNIFORM_BUFFER:
       {
         auto& bindings = cmd.bindUniformBuffers;
-        mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding);
+        mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindingsCount ? bindings.uniformBufferBindings.Ptr() : nullptr, bindings.uniformBufferBindingsCount, bindings.standaloneUniformsBufferBinding);
         break;
       }
       case GLES::CommandType::BIND_INDEX_BUFFER:
@@ -535,8 +547,12 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
       {
         ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent);
 
-        // push this command buffer to the discard queue
-        mDiscardCommandBufferQueue.push(const_cast<GLES::CommandBuffer*>(&commandBuffer));
+        // The command buffer will be pushed into the queue of presentation command buffers
+        // for further reuse.
+        if(commandBuffer.GetCreateInfo().fixedCapacity == 1)
+        {
+          mPresentationCommandBuffers.push(&commandBuffer);
+        }
         break;
       }
       case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
@@ -545,8 +561,10 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
         // todo: check validity of the secondaries
         //       there are operations which are illigal to be done
         //       within secondaries.
-        for(auto& buf : cmd.executeCommandBuffers.buffers)
+        auto buffers = cmd.executeCommandBuffers.buffers.Ptr();
+        for(auto j = 0u; j < cmd.executeCommandBuffers.buffersCount; ++j)
         {
+          auto& buf = buffers[j];
           ProcessCommandBuffer(*static_cast<const GLES::CommandBuffer*>(buf));
         }
         break;
@@ -557,10 +575,6 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm
 
 void EglGraphicsController::ProcessCommandQueues()
 {
-  // TODO: command queue per context, sync between queues should be
-  // done externally
-  currentFramebuffer = nullptr;
-
   DUMP_FRAME_START();
 
   while(!mCommandQueue.empty())
index 2491aba..a792eea 100644 (file)
@@ -772,8 +772,7 @@ private:
 
   bool mIsShuttingDown{false}; ///< Indicates whether the controller is shutting down
 
-  // todo: to be removed after renderpass
-  const Graphics::Framebuffer* currentFramebuffer{nullptr};
+  std::queue<const GLES::CommandBuffer*> mPresentationCommandBuffers{}; ///< Queue of reusable command buffers used by presentation engine
 };
 
 } // namespace Graphics
index 89a6010..d5064a7 100644 (file)
@@ -322,11 +322,13 @@ void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
   }
 }
 
-void Context::BindTextures(const std::vector<Graphics::TextureBinding>& bindings)
+void Context::BindTextures(const Graphics::TextureBinding* bindings, uint32_t count)
 {
   // for each texture allocate slot
-  for(const auto& binding : bindings)
+  for(auto i = 0u; i < count; ++i)
   {
+    auto& binding = bindings[i];
+
     // Resize binding array if needed
     if(mImpl->mCurrentTextureBindings.size() <= binding.binding)
     {
@@ -337,14 +339,14 @@ void Context::BindTextures(const std::vector<Graphics::TextureBinding>& bindings
   }
 }
 
-void Context::BindVertexBuffers(const std::vector<GLES::VertexBufferBindingDescriptor>& bindings)
+void Context::BindVertexBuffers(const GLES::VertexBufferBindingDescriptor* bindings, uint32_t count)
 {
-  if(bindings.size() > mImpl->mCurrentVertexBufferBindings.size())
+  if(count > mImpl->mCurrentVertexBufferBindings.size())
   {
-    mImpl->mCurrentVertexBufferBindings.resize(bindings.size());
+    mImpl->mCurrentVertexBufferBindings.resize(count);
   }
   // Copy only set slots
-  std::copy_if(bindings.begin(), bindings.end(), mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) {
+  std::copy_if(bindings, bindings + count, mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) {
     return (nullptr != item.buffer);
   });
 }
@@ -360,21 +362,22 @@ void Context::BindPipeline(const GLES::Pipeline* newPipeline)
   mImpl->mNewPipeline = &newPipeline->GetPipeline();
 }
 
-void Context::BindUniformBuffers(const std::vector<UniformBufferBindingDescriptor>& uboBindings,
-                                 const UniformBufferBindingDescriptor&              standaloneBindings)
+void Context::BindUniformBuffers(const UniformBufferBindingDescriptor* uboBindings,
+                                 uint32_t                              uboCount,
+                                 const UniformBufferBindingDescriptor& standaloneBindings)
 {
   if(standaloneBindings.buffer)
   {
     mImpl->mCurrentStandaloneUBOBinding = standaloneBindings;
   }
 
-  if(uboBindings.size() >= mImpl->mCurrentUBOBindings.size())
+  if(uboCount >= mImpl->mCurrentUBOBindings.size())
   {
-    mImpl->mCurrentUBOBindings.resize(uboBindings.size() + 1);
+    mImpl->mCurrentUBOBindings.resize(uboCount + 1);
   }
 
-  auto it = uboBindings.begin();
-  for(auto i = 0u; i < uboBindings.size(); ++i)
+  auto it = uboBindings;
+  for(auto i = 0u; i < uboCount; ++i)
   {
     if(it->buffer)
     {
@@ -554,22 +557,24 @@ void Context::BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin)
     // Something goes wrong here if Alpha mask is GL_TRUE
     ColorMask(true);
 
+    const auto clearValues = renderPassBegin.clearValues.Ptr();
+
     if(!mImpl->mGlStateCache.mClearColorSet ||
-       mImpl->mGlStateCache.mClearColor.r != renderPassBegin.clearValues[0].color.r ||
-       mImpl->mGlStateCache.mClearColor.g != renderPassBegin.clearValues[0].color.g ||
-       mImpl->mGlStateCache.mClearColor.b != renderPassBegin.clearValues[0].color.b ||
-       mImpl->mGlStateCache.mClearColor.a != renderPassBegin.clearValues[0].color.a)
+       mImpl->mGlStateCache.mClearColor.r != clearValues[0].color.r ||
+       mImpl->mGlStateCache.mClearColor.g != clearValues[0].color.g ||
+       mImpl->mGlStateCache.mClearColor.b != clearValues[0].color.b ||
+       mImpl->mGlStateCache.mClearColor.a != clearValues[0].color.a)
     {
-      gl.ClearColor(renderPassBegin.clearValues[0].color.r,
-                    renderPassBegin.clearValues[0].color.g,
-                    renderPassBegin.clearValues[0].color.b,
-                    renderPassBegin.clearValues[0].color.a);
+      gl.ClearColor(clearValues[0].color.r,
+                    clearValues[0].color.g,
+                    clearValues[0].color.b,
+                    clearValues[0].color.a);
 
       mImpl->mGlStateCache.mClearColorSet = true;
-      mImpl->mGlStateCache.mClearColor    = Vector4(renderPassBegin.clearValues[0].color.r,
-                                                 renderPassBegin.clearValues[0].color.g,
-                                                 renderPassBegin.clearValues[0].color.b,
-                                                 renderPassBegin.clearValues[0].color.a);
+      mImpl->mGlStateCache.mClearColor    = Vector4(clearValues[0].color.r,
+                                                 clearValues[0].color.g,
+                                                 clearValues[0].color.b,
+                                                 clearValues[0].color.a);
     }
   }
 
index 973536a..a4c3c8b 100644 (file)
@@ -72,7 +72,7 @@ public:
    * @param[in] bindings List of bindings
    *
    */
-  void BindTextures(const std::vector<Graphics::TextureBinding>& bindings);
+  void BindTextures(const Graphics::TextureBinding* bindings, uint32_t count);
 
   /**
    * @brief Vertex buffers to bind
@@ -81,7 +81,7 @@ public:
    * currently processed and copied into the local storage.
    */
 
-  void BindVertexBuffers(const std::vector<GLES::VertexBufferBindingDescriptor>& bindings);
+  void BindVertexBuffers(const GLES::VertexBufferBindingDescriptor* bindings, uint32_t count);
 
   /**
    * @brief Binds index buffer
@@ -102,7 +102,7 @@ public:
    * @param[in] uboBindings real UBO binfins
    * @param[in] standaloneBindings emulated (legacy) UBO object
    */
-  void BindUniformBuffers(const std::vector<UniformBufferBindingDescriptor>& uboBindings, const UniformBufferBindingDescriptor& standaloneBindings);
+  void BindUniformBuffers(const UniformBufferBindingDescriptor* uboBindings, uint32_t uboCount, const UniformBufferBindingDescriptor& standaloneBindings);
 
   /**
    * @brief Resolves blend state on the currently attached pipeline
index b79607b..7cc24f8 100644 (file)
 
 namespace Dali::Graphics::GLES
 {
+class CommandPool
+{
+  static const uint32_t COMMAND_POOL_DEFAULT_INCREMENT = 1024 * 32; // 32kb banks
+  static const uint32_t MEMORY_POOL_DEFAULT_INCREMENT  = 1024;      // 4kb memory pool increment
+  static const uint32_t MEMORY_POOL_DEFAULT_ALIGNMENT  = 64;        // 64bytes alignment
+
+  template<class T>
+  struct Block
+  {
+    Block() = default;
+    ~Block()
+    {
+      if(ptr)
+      {
+        free(ptr);
+      }
+    }
+
+    T*        ptr{nullptr};
+    uint32_t  dataSize{0u};
+    uint32_t  capacity{0u};
+    inline T& operator[](int index) const
+    {
+      return ptr[index];
+    }
+
+    inline void clear()
+    {
+      free(ptr);
+      capacity = 0;
+      dataSize = 0;
+    }
+
+    inline void resize(int newSize)
+    {
+      ptr      = reinterpret_cast<T*>(realloc(ptr, newSize * sizeof(T)));
+      capacity = newSize;
+      dataSize = newSize;
+    }
+
+    inline T* data() const
+    {
+      return ptr;
+    }
+
+    inline uint32_t size() const
+    {
+      return dataSize;
+    }
+  };
+  // This memory pool guarantees all items will be placed
+  // in the continuous memory area but returned pointers are relative
+  // and require translation before using
+  template<class T, int Increment, int Alignment = 0>
+  struct MemoryPool
+  {
+    Block<T>  data;
+    inline T& operator[](int index)
+    {
+      return data[index];
+    }
+    MemoryPool() = default;
+
+    IndirectPtr<T> Allocate(uint32_t count)
+    {
+      // set fixed capacity
+      if(fixedCapacity && data.size() != fixedCapacity)
+      {
+        data.resize(fixedCapacity);
+        totalCapacity = data.size();
+      }
+
+      // or resize dynamically
+      else if(data.size() <= offset + count)
+      {
+        data.resize(data.size() + Increment);
+
+        // update base pointer, required for address translation
+        totalCapacity = data.size();
+      }
+
+      basePtr = data.data();
+
+      IndirectPtr<T> retval{uint32_t(uintptr_t(&data[offset]) - uintptr_t(basePtr)), &basePtr};
+      size += count;
+      offset += count;
+
+      // align offset if needed (only if type size is 1)
+      if(Alignment && sizeof(T) == 1)
+      {
+        offset = ((offset / Alignment) * Alignment) + ((offset % Alignment) ? Alignment : 0);
+      }
+      return retval;
+    }
+
+    // Rolls back pool
+    void Rollback()
+    {
+      offset = 0;
+      size   = 0;
+    }
+
+    // Discards all data and storage
+    void Clear()
+    {
+      data.clear();
+      totalCapacity = 0;
+      offset        = 0;
+      size          = 0;
+    }
+
+    uint32_t offset{0u};
+    uint32_t totalCapacity{0u};
+    uint32_t size{0u};
+    uint32_t increment{Increment};
+    uint32_t alignment{Alignment};
+    uint32_t fixedCapacity{0u};
+    void*    basePtr{nullptr};
+  };
+
+  MemoryPool<uint8_t, MEMORY_POOL_DEFAULT_INCREMENT, MEMORY_POOL_DEFAULT_ALIGNMENT>  memoryPool;
+  MemoryPool<Command, COMMAND_POOL_DEFAULT_INCREMENT, MEMORY_POOL_DEFAULT_ALIGNMENT> commandPool;
+
+public:
+  CommandPool() = default;
+  CommandPool(uint32_t fixedCapacity)
+  {
+    commandPool.fixedCapacity = fixedCapacity;
+    memoryPool.fixedCapacity  = fixedCapacity * 1024;
+  }
+
+  /**
+   * Return value may become invalid if pool is resized (by allocating another command)
+   * @param type
+   * @return
+   */
+  Command* AllocateCommand(CommandType type)
+  {
+    auto command  = commandPool.Allocate(1);
+    command->type = type;
+    auto* cmd     = command.Ptr();
+    return cmd;
+  }
+
+  template<class T>
+  IndirectPtr<T> Allocate(uint32_t count)
+  {
+    const auto typeSize       = sizeof(T);
+    const auto memoryRequired = typeSize * count;
+    auto       ptr            = memoryPool.Allocate(memoryRequired);
+
+    // Convert generic pointer and return
+    return IndirectPtr<T>{ptr.ptr, ptr.base};
+  }
+
+  // New (should not be needed)
+  template<class T>
+  T* New(uint32_t count)
+  {
+    auto ptr = Allocate<T>(count);
+    for(auto i = 0u; i < count; ++i)
+    {
+      new(&ptr[i]) T();
+    }
+    return ptr;
+  }
+
+  // TODO: explicit delete?
+  void Rollback(bool discard)
+  {
+    if(discard)
+    {
+      commandPool.Clear();
+      memoryPool.Clear();
+    }
+    else
+    {
+      commandPool.Rollback();
+      memoryPool.Rollback();
+    }
+  }
+
+  const Command* GetCommands(uint32_t& size) const
+  {
+    size = commandPool.size;
+    return commandPool.data.ptr;
+  }
+};
+
 CommandBuffer::CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller)
 : CommandBufferResource(createInfo, controller)
 {
+  mCommandPool = std::make_unique<CommandPool>(createInfo.fixedCapacity);
 }
 
 CommandBuffer::~CommandBuffer() = default;
@@ -40,26 +230,39 @@ void CommandBuffer::BindVertexBuffers(uint32_t                             first
                                       std::vector<const Graphics::Buffer*> buffers,
                                       std::vector<uint32_t>                offsets)
 {
-  mCommands.emplace_back(CommandType::BIND_VERTEX_BUFFERS);
-  auto& bindings = mCommands.back().bindVertexBuffers.vertexBufferBindings;
-  if(bindings.size() < firstBinding + buffers.size())
+  auto command                                         = mCommandPool->AllocateCommand(CommandType::BIND_VERTEX_BUFFERS);
+  command->bindVertexBuffers.vertexBufferBindingsCount = firstBinding + buffers.size();
+  auto pBindings                                       = mCommandPool->Allocate<GLES::VertexBufferBindingDescriptor>(firstBinding + buffers.size());
+
+  command->bindVertexBuffers.vertexBufferBindings = pBindings;
+  auto index                                      = firstBinding;
+  for(auto& buf : buffers)
   {
-    bindings.resize(firstBinding + buffers.size());
-    auto index = firstBinding;
-    for(auto& buf : buffers)
-    {
-      bindings[index].buffer = static_cast<const GLES::Buffer*>(buf);
-      bindings[index].offset = offsets[index - firstBinding];
-      index++;
-    }
+    pBindings[index].buffer = static_cast<const GLES::Buffer*>(buf);
+    pBindings[index].offset = offsets[index - firstBinding];
+    index++;
   }
 }
 
 void CommandBuffer::BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings)
 {
-  mCommands.emplace_back(CommandType::BIND_UNIFORM_BUFFER);
-  auto& cmd     = mCommands.back();
+  auto command = mCommandPool->AllocateCommand(CommandType::BIND_UNIFORM_BUFFER);
+
+  auto& cmd     = *command;
   auto& bindCmd = cmd.bindUniformBuffers;
+
+  // temporary static set of binding slots (thread local)
+  static const auto MAX_UNIFORM_BUFFER_BINDINGS = 64; // TODO: this should be read from introspection
+
+  // TODO: could use vector?
+  static thread_local UniformBufferBindingDescriptor sTempBindings[MAX_UNIFORM_BUFFER_BINDINGS];
+
+  // reset temp bindings
+  memset(sTempBindings, 0, sizeof(UniformBufferBindingDescriptor) * MAX_UNIFORM_BUFFER_BINDINGS);
+
+  auto maxBinding = 0u;
+
+  // find max binding and standalone UBO
   for(const auto& binding : bindings)
   {
     if(binding.buffer)
@@ -74,37 +277,51 @@ void CommandBuffer::BindUniformBuffers(const std::vector<Graphics::UniformBuffer
       }
       else // Bind regular UBO
       {
-        // resize binding slots
-        if(binding.binding >= bindCmd.uniformBufferBindings.size())
-        {
-          bindCmd.uniformBufferBindings.resize(binding.binding + 1);
-        }
-        auto& slot    = bindCmd.uniformBufferBindings[binding.binding];
+        auto& slot    = sTempBindings[binding.binding];
         slot.buffer   = glesBuffer;
         slot.offset   = binding.offset;
         slot.binding  = binding.binding;
         slot.emulated = false;
+        maxBinding    = std::max(maxBinding, binding.binding);
       }
     }
   }
+  bindCmd.uniformBufferBindings      = nullptr;
+  bindCmd.uniformBufferBindingsCount = 0u;
+
+  // copy data
+  if(maxBinding)
+  {
+    auto destBindings = mCommandPool->Allocate<UniformBufferBindingDescriptor>(maxBinding + 1);
+    // copy
+    memcpy(destBindings.Ptr(), sTempBindings, sizeof(UniformBufferBindingDescriptor) * (maxBinding + 1));
+    bindCmd.uniformBufferBindings      = destBindings;
+    bindCmd.uniformBufferBindingsCount = maxBinding + 1;
+  }
 }
 
 void CommandBuffer::BindPipeline(const Graphics::Pipeline& pipeline)
 {
-  mCommands.emplace_back(CommandType::BIND_PIPELINE);
-  mCommands.back().bindPipeline.pipeline = static_cast<const GLES::Pipeline*>(&pipeline);
+  auto command                   = mCommandPool->AllocateCommand(CommandType::BIND_PIPELINE);
+  command->bindPipeline.pipeline = static_cast<const GLES::Pipeline*>(&pipeline);
 }
 
 void CommandBuffer::BindTextures(std::vector<TextureBinding>& textureBindings)
 {
-  mCommands.emplace_back(CommandType::BIND_TEXTURES);
-  mCommands.back().bindTextures.textureBindings = std::move(textureBindings);
+  auto  command                        = mCommandPool->AllocateCommand(CommandType::BIND_TEXTURES);
+  auto& bindTexturesCmd                = command->bindTextures;
+  bindTexturesCmd.textureBindings      = mCommandPool->Allocate<TextureBinding>(textureBindings.size());
+  bindTexturesCmd.textureBindingsCount = textureBindings.size();
+  memcpy(bindTexturesCmd.textureBindings.Ptr(), textureBindings.data(), sizeof(TextureBinding) * textureBindings.size());
 }
 
 void CommandBuffer::BindSamplers(std::vector<SamplerBinding>& samplerBindings)
 {
-  mCommands.emplace_back(CommandType::BIND_SAMPLERS);
-  mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings);
+  auto  command                        = mCommandPool->AllocateCommand(CommandType::BIND_SAMPLERS);
+  auto& bindSamplersCmd                = command->bindSamplers;
+  bindSamplersCmd.samplerBindings      = mCommandPool->Allocate<SamplerBinding>(samplerBindings.size());
+  bindSamplersCmd.samplerBindingsCount = samplerBindings.size();
+  memcpy(bindSamplersCmd.samplerBindings.Ptr(), samplerBindings.data(), sizeof(TextureBinding) * samplerBindings.size());
 }
 
 void CommandBuffer::BindPushConstants(void*    data,
@@ -117,10 +334,10 @@ void CommandBuffer::BindIndexBuffer(const Graphics::Buffer& buffer,
                                     uint32_t                offset,
                                     Format                  format)
 {
-  mCommands.emplace_back(CommandType::BIND_INDEX_BUFFER);
-  mCommands.back().bindIndexBuffer.buffer = static_cast<const GLES::Buffer*>(&buffer);
-  mCommands.back().bindIndexBuffer.offset = offset;
-  mCommands.back().bindIndexBuffer.format = format;
+  auto command                    = mCommandPool->AllocateCommand(CommandType::BIND_INDEX_BUFFER);
+  command->bindIndexBuffer.buffer = static_cast<const GLES::Buffer*>(&buffer);
+  command->bindIndexBuffer.offset = offset;
+  command->bindIndexBuffer.format = format;
 }
 
 void CommandBuffer::BeginRenderPass(
@@ -129,30 +346,32 @@ void CommandBuffer::BeginRenderPass(
   Rect2D                  renderArea,
   std::vector<ClearValue> clearValues)
 {
-  mCommands.emplace_back(CommandType::BEGIN_RENDERPASS);
-  auto& cmd                        = mCommands.back();
+  auto  command                    = mCommandPool->AllocateCommand(CommandType::BEGIN_RENDERPASS);
+  auto& cmd                        = *command;
   cmd.beginRenderPass.renderPass   = static_cast<GLES::RenderPass*>(renderPass);
   cmd.beginRenderPass.renderTarget = static_cast<GLES::RenderTarget*>(renderTarget);
   cmd.beginRenderPass.renderArea   = renderArea;
-  cmd.beginRenderPass.clearValues  = clearValues;
+
+  cmd.beginRenderPass.clearValues = mCommandPool->Allocate<ClearValue>(clearValues.size());
+  memcpy(cmd.beginRenderPass.clearValues.Ptr(), clearValues.data(), sizeof(ClearValue) * clearValues.size());
+  cmd.beginRenderPass.clearValuesCount = clearValues.size();
 }
 
 void CommandBuffer::EndRenderPass(Graphics::SyncObject* syncObject)
 {
-  mCommands.emplace_back(CommandType::END_RENDERPASS);
-  auto& cmd = mCommands.back();
-
-  cmd.endRenderPass.syncObject = static_cast<GLES::SyncObject*>(syncObject);
+  auto command                      = mCommandPool->AllocateCommand(CommandType::END_RENDERPASS);
+  command->endRenderPass.syncObject = static_cast<GLES::SyncObject*>(syncObject);
 }
 
 void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& commandBuffers)
 {
-  mCommands.emplace_back(CommandType::EXECUTE_COMMAND_BUFFERS);
-  auto& cmd = mCommands.back();
-  cmd.executeCommandBuffers.buffers.reserve(commandBuffers.size());
-  for(auto&& item : commandBuffers)
+  auto  command    = mCommandPool->AllocateCommand(CommandType::EXECUTE_COMMAND_BUFFERS);
+  auto& cmd        = command->executeCommandBuffers;
+  cmd.buffers      = mCommandPool->Allocate<const GLES::CommandBuffer*>(commandBuffers.size());
+  cmd.buffersCount = commandBuffers.size();
+  for(auto i = 0u; i < cmd.buffersCount; ++i)
   {
-    cmd.executeCommandBuffers.buffers.emplace_back(static_cast<const GLES::CommandBuffer*>(item));
+    cmd.buffers[i] = static_cast<const GLES::CommandBuffer*>(commandBuffers[i]);
   }
 }
 
@@ -162,8 +381,8 @@ void CommandBuffer::Draw(
   uint32_t firstVertex,
   uint32_t firstInstance)
 {
-  mCommands.emplace_back(CommandType::DRAW);
-  auto& cmd              = mCommands.back().draw;
+  auto  command          = mCommandPool->AllocateCommand(CommandType::DRAW);
+  auto& cmd              = command->draw;
   cmd.type               = DrawCallDescriptor::Type::DRAW;
   cmd.draw.vertexCount   = vertexCount;
   cmd.draw.instanceCount = instanceCount;
@@ -178,8 +397,8 @@ void CommandBuffer::DrawIndexed(
   int32_t  vertexOffset,
   uint32_t firstInstance)
 {
-  mCommands.emplace_back(CommandType::DRAW_INDEXED);
-  auto& cmd                     = mCommands.back().draw;
+  auto  command                 = mCommandPool->AllocateCommand(CommandType::DRAW_INDEXED);
+  auto& cmd                     = command->draw;
   cmd.type                      = DrawCallDescriptor::Type::DRAW_INDEXED;
   cmd.drawIndexed.firstIndex    = firstIndex;
   cmd.drawIndexed.firstInstance = firstInstance;
@@ -194,8 +413,8 @@ void CommandBuffer::DrawIndexedIndirect(
   uint32_t          drawCount,
   uint32_t          stride)
 {
-  mCommands.emplace_back(CommandType::DRAW_INDEXED_INDIRECT);
-  auto& cmd                         = mCommands.back().draw;
+  auto  command                     = mCommandPool->AllocateCommand(CommandType::DRAW_INDEXED_INDIRECT);
+  auto& cmd                         = command->draw;
   cmd.type                          = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
   cmd.drawIndexedIndirect.buffer    = static_cast<const GLES::Buffer*>(&buffer);
   cmd.drawIndexedIndirect.offset    = offset;
@@ -205,25 +424,25 @@ void CommandBuffer::DrawIndexedIndirect(
 
 void CommandBuffer::Reset()
 {
-  mCommands.clear();
+  mCommandPool->Rollback(false);
 }
 
 void CommandBuffer::SetScissor(Graphics::Rect2D value)
 {
-  mCommands.emplace_back(CommandType::SET_SCISSOR);
-  mCommands.back().scissor.region = value;
+  auto command            = mCommandPool->AllocateCommand(CommandType::SET_SCISSOR);
+  command->scissor.region = value;
 }
 
 void CommandBuffer::SetScissorTestEnable(bool value)
 {
-  mCommands.emplace_back(CommandType::SET_SCISSOR_TEST);
-  mCommands.back().scissorTest.enable = value;
+  auto command                = mCommandPool->AllocateCommand(CommandType::SET_SCISSOR_TEST);
+  command->scissorTest.enable = value;
 }
 
 void CommandBuffer::SetViewport(Viewport value)
 {
-  mCommands.emplace_back(CommandType::SET_VIEWPORT);
-  mCommands.back().viewport.region = value;
+  auto command             = mCommandPool->AllocateCommand(CommandType::SET_VIEWPORT);
+  command->viewport.region = value;
 }
 
 void CommandBuffer::SetViewportEnable(bool value)
@@ -233,35 +452,33 @@ void CommandBuffer::SetViewportEnable(bool value)
 
 void CommandBuffer::SetColorMask(bool enabled)
 {
-  mCommands.emplace_back(CommandType::SET_COLOR_MASK);
-  auto& cmd = mCommands.back().colorMask;
-  ;
-  cmd.enabled = enabled;
+  auto command               = mCommandPool->AllocateCommand(CommandType::SET_COLOR_MASK);
+  command->colorMask.enabled = enabled;
 }
 
 void CommandBuffer::ClearStencilBuffer()
 {
-  mCommands.emplace_back(CommandType::CLEAR_STENCIL_BUFFER);
+  mCommandPool->AllocateCommand(CommandType::CLEAR_STENCIL_BUFFER);
 }
 
 void CommandBuffer::SetStencilTestEnable(bool stencilEnable)
 {
-  mCommands.emplace_back(CommandType::SET_STENCIL_TEST_ENABLE);
-  mCommands.back().stencilTest.enabled = stencilEnable;
+  auto command                 = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_TEST_ENABLE);
+  command->stencilTest.enabled = stencilEnable;
 }
 
 void CommandBuffer::SetStencilWriteMask(uint32_t writeMask)
 {
-  mCommands.emplace_back(CommandType::SET_STENCIL_WRITE_MASK);
-  mCommands.back().stencilWriteMask.mask = writeMask;
+  auto command                   = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_WRITE_MASK);
+  command->stencilWriteMask.mask = writeMask;
 }
 
 void CommandBuffer::SetStencilOp(Graphics::StencilOp failOp,
                                  Graphics::StencilOp passOp,
                                  Graphics::StencilOp depthFailOp)
 {
-  mCommands.emplace_back(CommandType::SET_STENCIL_OP);
-  auto& cmd       = mCommands.back().stencilOp;
+  auto  command   = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_OP);
+  auto& cmd       = command->stencilOp;
   cmd.failOp      = failOp;
   cmd.passOp      = passOp;
   cmd.depthFailOp = depthFailOp;
@@ -271,8 +488,8 @@ void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp,
                                    uint32_t            reference,
                                    uint32_t            compareMask)
 {
-  mCommands.emplace_back(CommandType::SET_STENCIL_FUNC);
-  auto& cmd       = mCommands.back().stencilFunc;
+  auto  command   = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_FUNC);
+  auto& cmd       = command->stencilFunc;
   cmd.compareOp   = compareOp;
   cmd.compareMask = compareMask;
   cmd.reference   = reference;
@@ -280,34 +497,34 @@ void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp,
 
 void CommandBuffer::SetDepthCompareOp(Graphics::CompareOp compareOp)
 {
-  mCommands.emplace_back(CommandType::SET_DEPTH_COMPARE_OP);
-  mCommands.back().depth.compareOp = compareOp;
+  auto command             = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_COMPARE_OP);
+  command->depth.compareOp = compareOp;
 }
 
 void CommandBuffer::SetDepthTestEnable(bool depthTestEnable)
 {
-  mCommands.emplace_back(CommandType::SET_DEPTH_TEST_ENABLE);
-  mCommands.back().depth.testEnabled = depthTestEnable;
+  auto command               = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_TEST_ENABLE);
+  command->depth.testEnabled = depthTestEnable;
 }
 void CommandBuffer::SetDepthWriteEnable(bool depthWriteEnable)
 {
-  mCommands.emplace_back(CommandType::SET_DEPTH_WRITE_ENABLE);
-  mCommands.back().depth.writeEnabled = depthWriteEnable;
+  auto command                = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_WRITE_ENABLE);
+  command->depth.writeEnabled = depthWriteEnable;
 }
 void CommandBuffer::ClearDepthBuffer()
 {
-  mCommands.emplace_back(CommandType::CLEAR_DEPTH_BUFFER);
+  mCommandPool->AllocateCommand(CommandType::CLEAR_DEPTH_BUFFER);
 }
 
 void CommandBuffer::PresentRenderTarget(GLES::RenderTarget* renderTarget)
 {
-  mCommands.emplace_back(CommandType::PRESENT_RENDER_TARGET);
-  mCommands.back().presentRenderTarget.targetToPresent = renderTarget;
+  auto command                                 = mCommandPool->AllocateCommand(CommandType::PRESENT_RENDER_TARGET);
+  command->presentRenderTarget.targetToPresent = renderTarget;
 }
 
-[[nodiscard]] const std::vector<Command>& CommandBuffer::GetCommands() const
+[[nodiscard]] const Command* CommandBuffer::GetCommands(uint32_t& size) const
 {
-  return mCommands;
+  return mCommandPool->GetCommands(size);
 }
 
 void CommandBuffer::DestroyResource()
index f539103..8e2aeac 100644 (file)
 #include "gles-graphics-types.h"
 #include "gles-sync-object.h"
 
+#include <cstring>
+
 namespace Dali::Graphics::GLES
 {
 class Pipeline;
 class RenderPass;
 class Framebuffer;
 class CommandBuffer;
+class CommandPool;
 enum class CommandType
 {
   FLUSH,
@@ -79,370 +82,25 @@ static void InvokeDestructor(T& object)
  */
 struct Command
 {
-  Command() = delete;
-
-  Command(CommandType commandType)
+  Command()
   {
-    type = commandType;
-    switch(type)
-    {
-      case CommandType::BIND_VERTEX_BUFFERS:
-      {
-        new(&bindVertexBuffers) decltype(bindVertexBuffers);
-        break;
-      }
-      case CommandType::BIND_TEXTURES:
-      {
-        new(&bindTextures) decltype(bindTextures);
-        break;
-      }
-      case CommandType::BEGIN_RENDERPASS:
-      {
-        // run destructor
-        new(&beginRenderPass) decltype(beginRenderPass);
-        break;
-      }
-      default:
-      {
-      }
-    }
   }
 
-  ~Command()
+  explicit Command(CommandType commandType)
   {
-    switch(type)
-    {
-      case CommandType::BIND_VERTEX_BUFFERS:
-      {
-        InvokeDestructor(bindVertexBuffers);
-        break;
-      }
-      case CommandType::BIND_TEXTURES:
-      {
-        InvokeDestructor(bindTextures);
-        break;
-      }
-      case CommandType::BEGIN_RENDERPASS:
-      {
-        // run destructor
-        InvokeDestructor(beginRenderPass);
-        break;
-      }
-      default:
-      {
-      }
-    }
+    type = commandType;
   }
 
-  /**
-   * @brief Copy constructor
-   * @param[in] rhs Command
-   */
-  Command(const Command& rhs)
-  {
-    switch(rhs.type)
-    {
-      case CommandType::BIND_VERTEX_BUFFERS:
-      {
-        new(&bindVertexBuffers) decltype(bindVertexBuffers);
-        bindVertexBuffers = rhs.bindVertexBuffers;
-        break;
-      }
-      case CommandType::BIND_INDEX_BUFFER:
-      {
-        bindIndexBuffer = rhs.bindIndexBuffer;
-        break;
-      }
-      case CommandType::BIND_SAMPLERS:
-      {
-        bindSamplers = rhs.bindSamplers;
-        break;
-      }
-      case CommandType::BIND_TEXTURES:
-      {
-        new(&bindTextures) decltype(bindTextures);
-        bindTextures = rhs.bindTextures;
-        break;
-      }
-      case CommandType::BIND_PIPELINE:
-      {
-        bindPipeline = rhs.bindPipeline;
-        break;
-      }
-      case CommandType::BIND_UNIFORM_BUFFER:
-      {
-        bindUniformBuffers = rhs.bindUniformBuffers;
-        break;
-      }
-      case CommandType::DRAW:
-      {
-        draw.type = rhs.draw.type;
-        draw.draw = rhs.draw.draw;
-        break;
-      }
-      case CommandType::DRAW_INDEXED:
-      {
-        draw.type        = rhs.draw.type;
-        draw.drawIndexed = rhs.draw.drawIndexed;
-        break;
-      }
-      case CommandType::DRAW_INDEXED_INDIRECT:
-      {
-        draw.type                = rhs.draw.type;
-        draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
-        break;
-      }
-      case CommandType::BEGIN_RENDERPASS:
-      {
-        new(&beginRenderPass) BeginRenderPassDescriptor(rhs.beginRenderPass);
-        break;
-      }
-      case CommandType::END_RENDERPASS:
-      {
-        endRenderPass.syncObject = rhs.endRenderPass.syncObject;
-        break;
-      }
-      case CommandType::EXECUTE_COMMAND_BUFFERS:
-      {
-        executeCommandBuffers = rhs.executeCommandBuffers;
-        break;
-      }
-      case CommandType::FLUSH:
-      {
-        // Nothing to do
-        break;
-      }
-      case CommandType::SET_SCISSOR:
-      {
-        scissor.region = rhs.scissor.region;
-        break;
-      }
-      case CommandType::SET_SCISSOR_TEST:
-      {
-        scissorTest.enable = rhs.scissorTest.enable;
-        break;
-      }
-      case CommandType::SET_VIEWPORT:
-      {
-        viewport.region = rhs.viewport.region;
-        break;
-      }
-      case CommandType::PRESENT_RENDER_TARGET:
-      {
-        presentRenderTarget = rhs.presentRenderTarget;
-        break;
-      }
-      case CommandType::SET_COLOR_MASK:
-      {
-        colorMask.enabled = rhs.colorMask.enabled;
-        break;
-      }
-      case CommandType::CLEAR_STENCIL_BUFFER:
-      {
-        break;
-      }
-      case CommandType::CLEAR_DEPTH_BUFFER:
-      {
-        break;
-      }
-      case CommandType::SET_STENCIL_TEST_ENABLE:
-      {
-        stencilTest.enabled = rhs.stencilTest.enabled;
-        break;
-      }
-      case CommandType::SET_STENCIL_FUNC:
-      {
-        stencilFunc.compareMask = rhs.stencilFunc.compareMask;
-        stencilFunc.compareOp   = rhs.stencilFunc.compareOp;
-        stencilFunc.reference   = rhs.stencilFunc.reference;
-        break;
-      }
-      case CommandType::SET_STENCIL_WRITE_MASK:
-      {
-        stencilWriteMask.mask = rhs.stencilWriteMask.mask;
-        break;
-      }
-      case CommandType::SET_STENCIL_OP:
-      {
-        stencilOp.failOp      = rhs.stencilOp.failOp;
-        stencilOp.depthFailOp = rhs.stencilOp.depthFailOp;
-        stencilOp.passOp      = rhs.stencilOp.passOp;
-        break;
-      }
-
-      case CommandType::SET_DEPTH_COMPARE_OP:
-      {
-        depth.compareOp = rhs.depth.compareOp;
-        break;
-      }
-      case CommandType::SET_DEPTH_TEST_ENABLE:
-      {
-        depth.testEnabled = rhs.depth.testEnabled;
-        break;
-      }
-      case CommandType::SET_DEPTH_WRITE_ENABLE:
-      {
-        depth.writeEnabled = rhs.depth.writeEnabled;
-        break;
-      }
-    }
-    type = rhs.type;
-  }
+  ~Command() = default;
 
   /**
-   * @brief Move constructor
+   * @brief Copy constructor
    * @param[in] rhs Command
    */
-  Command(Command&& rhs) noexcept
-  {
-    switch(rhs.type)
-    {
-      case CommandType::BIND_VERTEX_BUFFERS:
-      {
-        new(&bindVertexBuffers) decltype(bindVertexBuffers);
-        bindVertexBuffers = std::move(rhs.bindVertexBuffers);
-        break;
-      }
-      case CommandType::BIND_INDEX_BUFFER:
-      {
-        bindIndexBuffer = rhs.bindIndexBuffer;
-        break;
-      }
-      case CommandType::BIND_UNIFORM_BUFFER:
-      {
-        bindUniformBuffers = std::move(rhs.bindUniformBuffers);
-        break;
-      }
-      case CommandType::BIND_SAMPLERS:
-      {
-        bindSamplers = std::move(rhs.bindSamplers);
-        break;
-      }
-      case CommandType::BIND_TEXTURES:
-      {
-        new(&bindTextures) decltype(bindTextures);
-        bindTextures = std::move(rhs.bindTextures);
-        break;
-      }
-      case CommandType::BIND_PIPELINE:
-      {
-        bindPipeline = rhs.bindPipeline;
-        break;
-      }
-      case CommandType::DRAW:
-      {
-        draw.type = rhs.draw.type;
-        draw.draw = rhs.draw.draw;
-        break;
-      }
-      case CommandType::DRAW_INDEXED:
-      {
-        draw.type        = rhs.draw.type;
-        draw.drawIndexed = rhs.draw.drawIndexed;
-        break;
-      }
-      case CommandType::DRAW_INDEXED_INDIRECT:
-      {
-        draw.type                = rhs.draw.type;
-        draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
-        break;
-      }
-      case CommandType::BEGIN_RENDERPASS:
-      {
-        new(&beginRenderPass) BeginRenderPassDescriptor(std::move(rhs.beginRenderPass));
-        break;
-      }
-      case CommandType::END_RENDERPASS:
-      {
-        endRenderPass.syncObject = rhs.endRenderPass.syncObject;
-        break;
-      }
-      case CommandType::EXECUTE_COMMAND_BUFFERS:
-      {
-        executeCommandBuffers = std::move(rhs.executeCommandBuffers);
-        break;
-      }
-      case CommandType::FLUSH:
-      {
-        // Nothing to do
-        break;
-      }
-      case CommandType::SET_SCISSOR:
-      {
-        scissor.region = rhs.scissor.region;
-        break;
-      }
-      case CommandType::SET_SCISSOR_TEST:
-      {
-        scissorTest.enable = rhs.scissorTest.enable;
-        break;
-      }
-      case CommandType::SET_VIEWPORT:
-      {
-        viewport.region = rhs.viewport.region;
-        break;
-      }
-      case CommandType::PRESENT_RENDER_TARGET:
-      {
-        presentRenderTarget = rhs.presentRenderTarget;
-        break;
-      }
-      case CommandType::SET_COLOR_MASK:
-      {
-        colorMask.enabled = rhs.colorMask.enabled;
-        break;
-      }
-      case CommandType::CLEAR_STENCIL_BUFFER:
-      {
-        break;
-      }
-      case CommandType::CLEAR_DEPTH_BUFFER:
-      {
-        break;
-      }
-      case CommandType::SET_STENCIL_TEST_ENABLE:
-      {
-        stencilTest.enabled = rhs.stencilTest.enabled;
-        break;
-      }
-      case CommandType::SET_STENCIL_FUNC:
-      {
-        stencilFunc.compareMask = rhs.stencilFunc.compareMask;
-        stencilFunc.compareOp   = rhs.stencilFunc.compareOp;
-        stencilFunc.reference   = rhs.stencilFunc.reference;
-        break;
-      }
-      case CommandType::SET_STENCIL_WRITE_MASK:
-      {
-        stencilWriteMask.mask = rhs.stencilWriteMask.mask;
-        break;
-      }
-      case CommandType::SET_STENCIL_OP:
-      {
-        stencilOp.failOp      = rhs.stencilOp.failOp;
-        stencilOp.depthFailOp = rhs.stencilOp.depthFailOp;
-        stencilOp.passOp      = rhs.stencilOp.passOp;
-        break;
-      }
-
-      case CommandType::SET_DEPTH_COMPARE_OP:
-      {
-        depth.compareOp = rhs.depth.compareOp;
-        break;
-      }
-      case CommandType::SET_DEPTH_TEST_ENABLE:
-      {
-        depth.testEnabled = rhs.depth.testEnabled;
-        break;
-      }
-      case CommandType::SET_DEPTH_WRITE_ENABLE:
-      {
-        depth.writeEnabled = rhs.depth.writeEnabled;
-        break;
-      }
-    }
-    type = rhs.type;
-  }
+  Command(const Command& rhs) = default;
+  Command& operator=(const Command& rhs) = default;
+  Command(Command&& rhs) noexcept        = delete;
+  Command& operator=(Command&& rhs) = delete;
 
   CommandType type{CommandType::FLUSH}; ///< Type of command
 
@@ -450,19 +108,22 @@ struct Command
   {
     struct
     {
-      std::vector<Graphics::TextureBinding> textureBindings;
+      IndirectPtr<Graphics::TextureBinding> textureBindings;
+      uint32_t                              textureBindingsCount;
     } bindTextures{};
 
     // BindSampler command
     struct
     {
-      std::vector<Graphics::SamplerBinding> samplerBindings;
+      IndirectPtr<Graphics::SamplerBinding> samplerBindings;
+      uint32_t                              samplerBindingsCount;
     } bindSamplers;
 
     struct
     {
       using Binding = GLES::VertexBufferBindingDescriptor;
-      std::vector<Binding> vertexBufferBindings;
+      IndirectPtr<Binding> vertexBufferBindings;
+      uint32_t             vertexBufferBindingsCount;
     } bindVertexBuffers;
 
     struct : public IndexBufferBindingDescriptor
@@ -471,7 +132,8 @@ struct Command
 
     struct
     {
-      std::vector<UniformBufferBindingDescriptor> uniformBufferBindings{};
+      IndirectPtr<UniformBufferBindingDescriptor> uniformBufferBindings;
+      uint32_t                                    uniformBufferBindingsCount;
       UniformBufferBindingDescriptor              standaloneUniformsBufferBinding{};
     } bindUniformBuffers;
 
@@ -509,7 +171,8 @@ struct Command
 
     struct
     {
-      std::vector<const GLES::CommandBuffer*> buffers;
+      IndirectPtr<const GLES::CommandBuffer*> buffers;
+      uint32_t                                buffersCount;
     } executeCommandBuffers;
 
     struct
@@ -741,7 +404,13 @@ public:
    */
   void PresentRenderTarget(GLES::RenderTarget* renderTarget);
 
-  [[nodiscard]] const std::vector<Command>& GetCommands() const;
+  /**
+   * @brief Returns pointer to the list of command and size of the list
+   *
+   * @param[out] size Size of the list
+   * @return Valid pointer to the list of commands
+   */
+  [[nodiscard]] const Command* GetCommands(uint32_t& size) const;
 
   /**
    * @brief Destroy the associated resources
@@ -759,7 +428,7 @@ public:
   void DiscardResource() override;
 
 private:
-  std::vector<Command> mCommands; ///< List of commands in this command buffer
+  std::unique_ptr<CommandPool> mCommandPool; ///< Pool of commands and transient memory
 };
 } // namespace Dali::Graphics::GLES
 
index 8c77721..06f95e3 100644 (file)
@@ -2029,14 +2029,56 @@ enum class BoundTextureType
 };
 
 /**
+ * This class stores indirect pointer, used by the CommandBuffer
+ * to store data allocated within resizeable pool
+ */
+template<class T>
+struct IndirectPtr
+{
+  uint32_t ptr;  // relative pointer
+  void**   base; // base pointer
+
+  inline T* operator->()
+  {
+    return reinterpret_cast<T*>((reinterpret_cast<uint8_t*>(*base) + ptr));
+  }
+
+  inline T& operator*()
+  {
+    return *reinterpret_cast<T*>((reinterpret_cast<uint8_t*>(*base) + ptr));
+  }
+
+  // Returns indirect pointer casted to requested type
+  T* Ptr() const
+  {
+    auto val = reinterpret_cast<T*>((reinterpret_cast<uint8_t*>(*base) + ptr));
+    return val;
+  }
+
+  inline T& operator[](int index)
+  {
+    return reinterpret_cast<T*>((reinterpret_cast<uint8_t*>(*base) + ptr))[index];
+  }
+
+  // Fake assignment operator for void* type
+  inline IndirectPtr<T>& operator=(void* p)
+  {
+    ptr  = 0;
+    base = nullptr;
+    return *this;
+  }
+};
+
+/**
  * The descriptor of BeginRenderPass command
  */
 struct BeginRenderPassDescriptor
 {
-  const GLES::RenderPass*   renderPass{};
-  const GLES::RenderTarget* renderTarget{};
-  Rect2D                    renderArea{};
-  std::vector<ClearValue>   clearValues{};
+  const GLES::RenderPass*   renderPass;
+  const GLES::RenderTarget* renderTarget;
+  Rect2D                    renderArea;
+  IndirectPtr<ClearValue>   clearValues;
+  uint32_t                  clearValuesCount;
 };
 
 } // namespace Dali::Graphics::GLES