Fixed memory leaks 37/256637/6
authorAdam Bialogonski <adam.b@samsung.com>
Thu, 8 Apr 2021 08:43:24 +0000 (09:43 +0100)
committerAdam Bialogonski <adam.b@samsung.com>
Thu, 8 Apr 2021 16:34:08 +0000 (17:34 +0100)
The resources couldn't be freed as the controller didn't invoke
a final flush. The controller destructor has been scheduled to be run
after gl-abstraction (egl-graphics.h).

Some resources were not folowing the lifecycle flow. This has been fixed.

Change-Id: I0d1447a16e0c374d3c7eb8d02d6918335b9bc8a6

16 files changed:
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.h
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-graphics-buffer.cpp
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-pipeline-cache.cpp
dali/internal/graphics/gles-impl/gles-graphics-program.cpp
dali/internal/graphics/gles-impl/gles-graphics-sampler.cpp
dali/internal/graphics/gles-impl/gles-graphics-sampler.h
dali/internal/graphics/gles-impl/gles-graphics-shader.cpp
dali/internal/graphics/gles-impl/gles-graphics-shader.h
dali/internal/graphics/gles-impl/gles-graphics-texture.cpp
dali/internal/graphics/gles/egl-graphics.cpp

index 54e8f77..51f0721 100644 (file)
@@ -682,6 +682,16 @@ void TestGraphicsController::Resume()
   mCallStack.PushCall("Resume", "");
 }
 
+void TestGraphicsController::Shutdown()
+{
+  mCallStack.PushCall("Shutdown", "");
+}
+
+void TestGraphicsController::Destroy()
+{
+  mCallStack.PushCall("Destroy", "");
+}
+
 void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureUpdateInfo>&       updateInfoList,
                                             const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList)
 {
index d70ed3b..803678e 100644 (file)
@@ -87,6 +87,16 @@ public:
   void Resume() override;
 
   /**
+   * @brief Lifecycle shutdown event
+   */
+  void Shutdown() override;
+
+  /**
+   * @brief Lifecycle destroy event
+   */
+  void Destroy() override;
+
+  /**
    * @brief Executes batch update of textures
    *
    * This function may perform full or partial update of many textures.
index 9746ac4..8fe7b73 100644 (file)
@@ -90,6 +90,8 @@ T0* CastObject(T1* apiObject)
 
 } // namespace
 
+EglGraphicsController::~EglGraphicsController() = default;
+
 void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
 {
   DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #1\n");
@@ -219,6 +221,15 @@ void EglGraphicsController::ProcessDiscardQueues()
 
   // Process programs
   ProcessDiscardQueue<GLES::Program>(mDiscardProgramQueue);
+
+  // Process shaders
+  ProcessDiscardQueue<GLES::Shader>(mDiscardShaderQueue);
+
+  // Process samplers
+  ProcessDiscardQueue<GLES::Sampler>(mDiscardSamplerQueue);
+
+  // Process command buffers
+  ProcessDiscardQueue<GLES::CommandBuffer>(mDiscardCommandBufferQueue);
 }
 
 void EglGraphicsController::ProcessCreateQueues()
index 5bf2e0d..ccfe519 100644 (file)
 // INTERNAL INCLUDES
 #include "gles-context.h"
 #include "gles-graphics-buffer.h"
+#include "gles-graphics-command-buffer.h"
 #include "gles-graphics-pipeline-cache.h"
 #include "gles-graphics-pipeline.h"
 #include "gles-graphics-reflection.h"
 #include "gles-graphics-sampler.h"
+#include "gles-graphics-shader.h"
 #include "gles-graphics-texture.h"
 #include "gles-graphics-types.h"
 #include "gles2-graphics-memory.h"
@@ -65,7 +67,7 @@ public:
   /**
    * @brief Destructor
    */
-  ~EglGraphicsController() override = default;
+  ~EglGraphicsController() override;
 
   /**
    * Initialize the GLES abstraction. This can be called from the main thread.
@@ -118,6 +120,23 @@ public:
   }
 
   /**
+   * @copydoc Dali::Graphics::Shutdown()
+   */
+  void Shutdown() override
+  {
+    mIsShuttingDown = true;
+  }
+
+  /**
+   * @copydoc Dali::Graphics::Destroy()
+   */
+  void Destroy() override
+  {
+    // Final flush
+    Flush();
+  }
+
+  /**
    * @copydoc Dali::Graphics::UpdateTextures()
    */
   void UpdateTextures(const std::vector<TextureUpdateInfo>&       updateInfoList,
@@ -281,6 +300,10 @@ public:
 
   [[nodiscard]] Integration::GlAbstraction* GetGL() const
   {
+    if(mIsShuttingDown)
+    {
+      return nullptr;
+    }
     return mGlAbstraction;
   }
 
@@ -312,9 +335,9 @@ public:
    *
    * @param[in] texture Pointer to the texture
    */
-  void DiscardResource(GLES::Buffer* texture)
+  void DiscardResource(GLES::Buffer* buffer)
   {
-    mDiscardBufferQueue.push(texture);
+    mDiscardBufferQueue.push(buffer);
   }
 
   /**
@@ -330,6 +353,42 @@ public:
   }
 
   /**
+   * @brief Pushes Shader to the discard queue
+   *
+   * Function is called from the UniquePtr custom deleter.
+   *
+   * @param[in] program Pointer to the Shader
+   */
+  void DiscardResource(GLES::Shader* shader)
+  {
+    mDiscardShaderQueue.push(shader);
+  }
+
+  /**
+   * @brief Pushes CommandBuffer to the discard queue
+   *
+   * Function is called from the UniquePtr custom deleter.
+   *
+   * @param[in] program Pointer to the CommandBuffer
+   */
+  void DiscardResource(GLES::CommandBuffer* commandBuffer)
+  {
+    mDiscardCommandBufferQueue.push(commandBuffer);
+  }
+
+  /**
+   * @brief Pushes Sampler to the discard queue
+   *
+   * Function is called from the UniquePtr custom deleter.
+   *
+   * @param[in] program Pointer to the Sampler
+   */
+  void DiscardResource(GLES::Sampler* sampler)
+  {
+    mDiscardSamplerQueue.push(sampler);
+  }
+
+  /**
    * @brief Pushes Pipeline to the discard queue
    *
    * Function is called from the UniquePtr custom deleter.
@@ -472,6 +531,11 @@ public:
     return GLES::GLESVersion::GLES_20;
   }
 
+  bool IsShuttingDown() const
+  {
+    return mIsShuttingDown;
+  }
+
 private:
   Integration::GlAbstraction*              mGlAbstraction{nullptr};
   Integration::GlSyncAbstraction*          mGlSyncAbstraction{nullptr};
@@ -483,9 +547,11 @@ private:
   std::queue<GLES::Buffer*> mCreateBufferQueue;  ///< Create queue for buffer resource
   std::queue<GLES::Buffer*> mDiscardBufferQueue; ///< Discard queue for buffer resource
 
-  std::queue<GLES::Program*> mDiscardProgramQueue; ///< Discard queue for program resource
-
-  std::queue<GLES::Pipeline*> mDiscardPipelineQueue; ///< Discard queue of pipelines
+  std::queue<GLES::Program*>       mDiscardProgramQueue;       ///< Discard queue for program resource
+  std::queue<GLES::Pipeline*>      mDiscardPipelineQueue;      ///< Discard queue of pipelines
+  std::queue<GLES::Shader*>        mDiscardShaderQueue;        ///< Discard queue of shaders
+  std::queue<GLES::Sampler*>       mDiscardSamplerQueue;       ///< Discard queue of samplers
+  std::queue<GLES::CommandBuffer*> mDiscardCommandBufferQueue; ///< Discard queue of command buffers
 
   std::queue<GLES::CommandBuffer*> mCommandQueue; ///< we may have more in the future
 
@@ -495,6 +561,8 @@ private:
   std::unique_ptr<GLES::Context> mContext{nullptr}; ///< Context object handling command buffers execution
 
   std::unique_ptr<GLES::PipelineCache> mPipelineCache{nullptr}; ///< Internal pipeline cache
+
+  bool mIsShuttingDown{false}; ///< Indicates whether the controller is shutting down
 };
 
 } // namespace Graphics
index eef1268..f7cf80d 100644 (file)
@@ -18,8 +18,8 @@
 #include "gles-context.h"
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/gl-defines.h>
+#include "egl-graphics-controller.h"
 #include "gles-graphics-buffer.h"
-#include "gles-graphics-command-buffer.h"
 #include "gles-graphics-pipeline.h"
 #include "gles-graphics-program.h"
 
index 2e4d4dc..3e4805a 100644 (file)
@@ -109,7 +109,10 @@ void Buffer::DestroyResource()
   else
   {
     auto gl = mController.GetGL();
-    gl->DeleteBuffers(1, &mBufferId);
+    if(gl)
+    {
+      gl->DeleteBuffers(1, &mBufferId);
+    }
   }
 }
 
index 70006da..8cb90b1 100644 (file)
 
 // CLASS HEADER
 #include "gles-graphics-command-buffer.h"
+
+// INTERNAL INCLUDES
+#include "egl-graphics-controller.h"
+#include "gles-graphics-buffer.h"
+#include "gles-graphics-pipeline.h"
+#include "gles-graphics-texture.h"
+
+namespace Dali::Graphics::GLES
+{
+CommandBuffer::CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller)
+: CommandBufferResource(createInfo, controller)
+{
+}
+
+CommandBuffer::~CommandBuffer() = default;
+
+void CommandBuffer::BindVertexBuffers(uint32_t                             firstBinding,
+                                      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())
+  {
+    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++;
+    }
+  }
+}
+
+void CommandBuffer::BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings)
+{
+  mCommands.emplace_back(CommandType::BIND_UNIFORM_BUFFER);
+  auto& cmd     = mCommands.back();
+  auto& bindCmd = cmd.bindUniformBuffers;
+  for(const auto& binding : bindings)
+  {
+    if(binding.buffer)
+    {
+      auto glesBuffer = static_cast<const GLES::Buffer*>(binding.buffer);
+      if(glesBuffer->IsCPUAllocated()) // standalone uniforms
+      {
+        bindCmd.standaloneUniformsBufferBinding.buffer   = glesBuffer;
+        bindCmd.standaloneUniformsBufferBinding.offset   = binding.offset;
+        bindCmd.standaloneUniformsBufferBinding.binding  = binding.binding;
+        bindCmd.standaloneUniformsBufferBinding.emulated = true;
+      }
+      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];
+        slot.buffer   = glesBuffer;
+        slot.offset   = binding.offset;
+        slot.binding  = binding.binding;
+        slot.emulated = false;
+      }
+    }
+  }
+}
+
+void CommandBuffer::BindPipeline(const Graphics::Pipeline& pipeline)
+{
+  mCommands.emplace_back(CommandType::BIND_PIPELINE);
+  mCommands.back().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);
+}
+
+void CommandBuffer::BindSamplers(std::vector<SamplerBinding>& samplerBindings)
+{
+  mCommands.emplace_back(CommandType::BIND_SAMPLERS);
+  mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings);
+}
+
+void CommandBuffer::BindPushConstants(void*    data,
+                                      uint32_t size,
+                                      uint32_t binding)
+{
+}
+
+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;
+}
+
+void CommandBuffer::BeginRenderPass(
+  Graphics::RenderPass&   renderPass,
+  Graphics::RenderTarget& renderTarget,
+  Extent2D                renderArea,
+  std::vector<ClearValue> clearValues)
+{
+}
+
+/**
+ * @brief Ends current render pass
+ *
+ * This command must be issued in order to finalize the render pass.
+ * It's up to the implementation whether anything has to be done but
+ * the Controller may use end RP marker in order to resolve resource
+ * dependencies (for example, to know when target texture is ready
+ * before passing it to another render pass).
+ */
+void CommandBuffer::EndRenderPass()
+{
+}
+
+void CommandBuffer::Draw(
+  uint32_t vertexCount,
+  uint32_t instanceCount,
+  uint32_t firstVertex,
+  uint32_t firstInstance)
+{
+  mCommands.emplace_back(CommandType::DRAW);
+  auto& cmd              = mCommands.back().draw;
+  cmd.type               = DrawCallDescriptor::Type::DRAW;
+  cmd.draw.vertexCount   = vertexCount;
+  cmd.draw.instanceCount = instanceCount;
+  cmd.draw.firstInstance = firstInstance;
+  cmd.draw.firstVertex   = firstVertex;
+}
+
+void CommandBuffer::DrawIndexed(
+  uint32_t indexCount,
+  uint32_t instanceCount,
+  uint32_t firstIndex,
+  int32_t  vertexOffset,
+  uint32_t firstInstance)
+{
+  mCommands.emplace_back(CommandType::DRAW_INDEXED);
+  auto& cmd                     = mCommands.back().draw;
+  cmd.type                      = DrawCallDescriptor::Type::DRAW_INDEXED;
+  cmd.drawIndexed.firstIndex    = firstIndex;
+  cmd.drawIndexed.firstInstance = firstInstance;
+  cmd.drawIndexed.indexCount    = indexCount;
+  cmd.drawIndexed.vertexOffset  = vertexOffset;
+  cmd.drawIndexed.instanceCount = instanceCount;
+}
+
+void CommandBuffer::DrawIndexedIndirect(
+  Graphics::Buffer& buffer,
+  uint32_t          offset,
+  uint32_t          drawCount,
+  uint32_t          stride)
+{
+  mCommands.emplace_back(CommandType::DRAW_INDEXED_INDIRECT);
+  auto& cmd                         = mCommands.back().draw;
+  cmd.type                          = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
+  cmd.drawIndexedIndirect.buffer    = static_cast<const GLES::Buffer*>(&buffer);
+  cmd.drawIndexedIndirect.offset    = offset;
+  cmd.drawIndexedIndirect.drawCount = drawCount;
+  cmd.drawIndexedIndirect.stride    = stride;
+}
+
+void CommandBuffer::Reset()
+{
+  mCommands.clear();
+}
+
+void CommandBuffer::SetScissor(Graphics::Rect2D value)
+{
+  mCommands.emplace_back(CommandType::SET_SCISSOR);
+  mCommands.back().scissor.region = value;
+}
+
+void CommandBuffer::SetScissorTestEnable(bool value)
+{
+  mCommands.emplace_back(CommandType::SET_SCISSOR_TEST);
+  mCommands.back().scissorTest.enable = value;
+}
+
+void CommandBuffer::SetViewport(Viewport value)
+{
+  mCommands.emplace_back(CommandType::SET_VIEWPORT);
+  mCommands.back().viewport.region = value;
+}
+
+void CommandBuffer::SetViewportEnable(bool value)
+{
+  // There is no GL equivalent
+}
+
+[[nodiscard]] const std::vector<Command>& CommandBuffer::GetCommands() const
+{
+  return mCommands;
+}
+
+void CommandBuffer::DestroyResource()
+{
+  // Nothing to do
+}
+
+bool CommandBuffer::InitializeResource()
+{
+  // Nothing to do
+  return true;
+}
+
+void CommandBuffer::DiscardResource()
+{
+  GetController().DiscardResource(this);
+}
+
+} // namespace Dali::Graphics::GLES
\ No newline at end of file
index e976883..cad69bd 100644 (file)
  */
 
 // EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-command-buffer-create-info.h>
 #include <dali/graphics-api/graphics-command-buffer.h>
+#include <dali/graphics-api/graphics-types.h>
 
 // INTERNAL INCLUDES
-#include "egl-graphics-controller.h"
-#include "gles-graphics-buffer.h"
-#include "gles-graphics-pipeline.h"
+#include "gles-graphics-resource.h"
 #include "gles-graphics-types.h"
 
 namespace Dali::Graphics::GLES
@@ -50,16 +50,60 @@ enum class CommandType
 };
 
 /**
+ * @brief Helper function to invoke destructor on anonymous struct
+ */
+template<class T>
+static void InvokeDestructor(T& object)
+{
+  object.~T();
+}
+
+/**
  * Command structure allocates memory to store a single command
  */
 struct Command
 {
-  Command()
+  Command() = delete;
+
+  Command(CommandType commandType)
   {
+    type = commandType;
+    switch(type)
+    {
+      case CommandType::BIND_VERTEX_BUFFERS:
+      {
+        new(&bindVertexBuffers) decltype(bindVertexBuffers);
+        break;
+      }
+      case CommandType::BIND_TEXTURES:
+      {
+        new(&bindTextures) decltype(bindTextures);
+        break;
+      }
+      default:
+      {
+      }
+    }
   }
 
   ~Command()
   {
+    switch(type)
+    {
+      case CommandType::BIND_VERTEX_BUFFERS:
+      {
+        InvokeDestructor(bindVertexBuffers);
+        break;
+      }
+      case CommandType::BIND_TEXTURES:
+      {
+        InvokeDestructor(bindTextures);
+        break;
+      }
+      default:
+      {
+      }
+    }
   }
 
   /**
@@ -72,6 +116,7 @@ struct Command
     {
       case CommandType::BIND_VERTEX_BUFFERS:
       {
+        new(&bindVertexBuffers) decltype(bindVertexBuffers);
         bindVertexBuffers = rhs.bindVertexBuffers;
         break;
       }
@@ -87,6 +132,7 @@ struct Command
       }
       case CommandType::BIND_TEXTURES:
       {
+        new(&bindTextures) decltype(bindTextures);
         bindTextures = rhs.bindTextures;
         break;
       }
@@ -152,6 +198,7 @@ struct Command
     {
       case CommandType::BIND_VERTEX_BUFFERS:
       {
+        new(&bindVertexBuffers) decltype(bindVertexBuffers);
         bindVertexBuffers = std::move(rhs.bindVertexBuffers);
         break;
       }
@@ -172,6 +219,7 @@ struct Command
       }
       case CommandType::BIND_TEXTURES:
       {
+        new(&bindTextures) decltype(bindTextures);
         bindTextures = std::move(rhs.bindTextures);
         break;
       }
@@ -284,112 +332,35 @@ using CommandBufferResource = Resource<Graphics::CommandBuffer, Graphics::Comman
 class CommandBuffer : public CommandBufferResource
 {
 public:
-  CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller)
-  : CommandBufferResource(createInfo, controller)
-  {
-  }
+  CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller);
 
-  ~CommandBuffer() override = default;
+  ~CommandBuffer() override;
 
   void BindVertexBuffers(uint32_t                             firstBinding,
                          std::vector<const Graphics::Buffer*> buffers,
-                         std::vector<uint32_t>                offsets) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type = CommandType::BIND_VERTEX_BUFFERS;
-    auto& bindings        = mCommands.back().bindVertexBuffers.vertexBufferBindings;
-    if(bindings.size() < firstBinding + buffers.size())
-    {
-      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++;
-      }
-    }
-  }
+                         std::vector<uint32_t>                offsets) override;
 
-  void BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings) override
-  {
-    mCommands.emplace_back();
-    auto& cmd     = mCommands.back();
-    cmd.type      = CommandType::BIND_UNIFORM_BUFFER;
-    auto& bindCmd = cmd.bindUniformBuffers;
-    for(const auto& binding : bindings)
-    {
-      if(binding.buffer)
-      {
-        auto glesBuffer = static_cast<const GLES::Buffer*>(binding.buffer);
-        if(glesBuffer->IsCPUAllocated()) // standalone uniforms
-        {
-          bindCmd.standaloneUniformsBufferBinding.buffer   = glesBuffer;
-          bindCmd.standaloneUniformsBufferBinding.offset   = binding.offset;
-          bindCmd.standaloneUniformsBufferBinding.binding  = binding.binding;
-          bindCmd.standaloneUniformsBufferBinding.emulated = true;
-        }
-        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];
-          slot.buffer   = glesBuffer;
-          slot.offset   = binding.offset;
-          slot.binding  = binding.binding;
-          slot.emulated = false;
-        }
-      }
-    }
-  }
+  void BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings) override;
 
-  void BindPipeline(const Graphics::Pipeline& pipeline) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type                  = CommandType::BIND_PIPELINE;
-    mCommands.back().bindPipeline.pipeline = static_cast<const GLES::Pipeline*>(&pipeline);
-  }
+  void BindPipeline(const Graphics::Pipeline& pipeline) override;
 
-  void BindTextures(std::vector<TextureBinding>& textureBindings) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type                         = CommandType::BIND_TEXTURES;
-    mCommands.back().bindTextures.textureBindings = std::move(textureBindings);
-  }
+  void BindTextures(std::vector<TextureBinding>& textureBindings) override;
 
-  void BindSamplers(std::vector<SamplerBinding>& samplerBindings) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings);
-  }
+  void BindSamplers(std::vector<SamplerBinding>& samplerBindings) override;
 
   void BindPushConstants(void*    data,
                          uint32_t size,
-                         uint32_t binding) override
-  {
-  }
+                         uint32_t binding) override;
 
   void BindIndexBuffer(const Graphics::Buffer& buffer,
                        uint32_t                offset,
-                       Format                  format) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type                   = CommandType::BIND_INDEX_BUFFER;
-    mCommands.back().bindIndexBuffer.buffer = static_cast<const GLES::Buffer*>(&buffer);
-    mCommands.back().bindIndexBuffer.offset = offset;
-    mCommands.back().bindIndexBuffer.format = format;
-  }
+                       Format                  format) override;
 
   void BeginRenderPass(
     Graphics::RenderPass&   renderPass,
     Graphics::RenderTarget& renderTarget,
     Extent2D                renderArea,
-    std::vector<ClearValue> clearValues) override
-  {
-  }
+    std::vector<ClearValue> clearValues) override;
 
   /**
    * @brief Ends current render pass
@@ -400,111 +371,43 @@ public:
    * dependencies (for example, to know when target texture is ready
    * before passing it to another render pass).
    */
-  void EndRenderPass() override
-  {
-  }
+  void EndRenderPass() override;
 
   void Draw(
     uint32_t vertexCount,
     uint32_t instanceCount,
     uint32_t firstVertex,
-    uint32_t firstInstance) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type  = CommandType::DRAW;
-    auto& cmd              = mCommands.back().draw;
-    cmd.type               = DrawCallDescriptor::Type::DRAW;
-    cmd.draw.vertexCount   = vertexCount;
-    cmd.draw.instanceCount = instanceCount;
-    cmd.draw.firstInstance = firstInstance;
-    cmd.draw.firstVertex   = firstVertex;
-  }
+    uint32_t firstInstance) override;
 
   void DrawIndexed(
     uint32_t indexCount,
     uint32_t instanceCount,
     uint32_t firstIndex,
     int32_t  vertexOffset,
-    uint32_t firstInstance) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type         = CommandType::DRAW_INDEXED;
-    auto& cmd                     = mCommands.back().draw;
-    cmd.type                      = DrawCallDescriptor::Type::DRAW_INDEXED;
-    cmd.drawIndexed.firstIndex    = firstIndex;
-    cmd.drawIndexed.firstInstance = firstInstance;
-    cmd.drawIndexed.indexCount    = indexCount;
-    cmd.drawIndexed.vertexOffset  = vertexOffset;
-    cmd.drawIndexed.instanceCount = instanceCount;
-  }
+    uint32_t firstInstance) override;
 
   void DrawIndexedIndirect(
     Graphics::Buffer& buffer,
     uint32_t          offset,
     uint32_t          drawCount,
-    uint32_t          stride) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type             = CommandType::DRAW_INDEXED_INDIRECT;
-    auto& cmd                         = mCommands.back().draw;
-    cmd.type                          = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
-    cmd.drawIndexedIndirect.buffer    = static_cast<const GLES::Buffer*>(&buffer);
-    cmd.drawIndexedIndirect.offset    = offset;
-    cmd.drawIndexedIndirect.drawCount = drawCount;
-    cmd.drawIndexedIndirect.stride    = stride;
-  }
+    uint32_t          stride) override;
 
-  void Reset() override
-  {
-    mCommands.clear();
-  }
-
-  void SetScissor(Graphics::Rect2D value) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type           = CommandType::SET_SCISSOR;
-    mCommands.back().scissor.region = value;
-  }
+  void Reset() override;
 
-  void SetScissorTestEnable(bool value) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type               = CommandType::SET_SCISSOR_TEST;
-    mCommands.back().scissorTest.enable = value;
-  }
+  void SetScissor(Graphics::Rect2D value) override;
 
-  void SetViewport(Viewport value) override
-  {
-    mCommands.emplace_back();
-    mCommands.back().type            = CommandType::SET_VIEWPORT;
-    mCommands.back().viewport.region = value;
-  }
+  void SetScissorTestEnable(bool value) override;
 
-  void SetViewportEnable(bool value) override
-  {
-    // There is no GL equivalent
-  }
+  void SetViewport(Viewport value) override;
 
-  [[nodiscard]] const std::vector<Command>& GetCommands() const
-  {
-    return mCommands;
-  }
+  void SetViewportEnable(bool value) override;
 
-  void DestroyResource() override
-  {
-    // Nothing to do
-  }
+  [[nodiscard]] const std::vector<Command>& GetCommands() const;
 
-  bool InitializeResource() override
-  {
-    // Nothing to do
-    return true;
-  }
+  void DestroyResource() override;
+  bool InitializeResource() override;
 
-  void DiscardResource() override
-  {
-    // Nothing to do
-  }
+  void DiscardResource() override;
 
 private:
   std::vector<Command> mCommands;
index 5d575f7..ad98fb0 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "gles-graphics-pipeline-cache.h"
 #include <algorithm>
+#include "egl-graphics-controller.h"
 #include "gles-graphics-pipeline.h"
 #include "gles-graphics-program.h"
 
@@ -37,6 +38,26 @@ struct CachedObjectDeleter
   }
 };
 
+template<>
+struct CachedObjectDeleter<GLES::Program>
+{
+  CachedObjectDeleter() = default;
+
+  void operator()(GLES::Program* object)
+  {
+    // Program deleter should skip discard queue if controller shutting down
+    if(!object->GetController().IsShuttingDown())
+    {
+      object->DiscardResource();
+    }
+    else
+    {
+      // delete object otherwise
+      delete object;
+    }
+  }
+};
+
 /**
  * @brief The order of states being stored in the cache and mask
  */
@@ -278,8 +299,8 @@ struct PipelineCache::Impl
   struct ProgramCacheEntry
   {
     // sorted array of shaders
-    std::vector<const Shader*> shaders;
-    UniquePtr<ProgramImpl>     program{nullptr};
+    std::vector<const Graphics::Shader*> shaders;
+    UniquePtr<ProgramImpl>               program{nullptr};
   };
 
   std::vector<ProgramCacheEntry> programEntries;
@@ -354,7 +375,7 @@ ProgramImpl* PipelineCache::FindProgramImpl(const ProgramCreateInfo& info)
   }
 
   // assert if no shaders given
-  std::vector<const Shader*> shaders;
+  std::vector<const Graphics::Shader*> shaders;
   shaders.reserve(info.shaderState->size());
 
   for(auto& state : *info.shaderState)
index a7686e1..484f400 100644 (file)
@@ -68,8 +68,12 @@ bool ProgramImpl::Destroy()
 {
   if(mImpl->glProgram)
   {
-    auto& gl = *mImpl->controller.GetGL();
-    gl.DeleteProgram(mImpl->glProgram);
+    auto gl = mImpl->controller.GetGL();
+    if(!gl)
+    {
+      return false;
+    }
+    gl->DeleteProgram(mImpl->glProgram);
     return true;
   }
   return false;
@@ -87,9 +91,10 @@ bool ProgramImpl::Create()
     const auto* shader = static_cast<const GLES::Shader*>(state.shader);
 
     // Compile shader first (ignored when compiled)
-    shader->Compile();
-
-    gl.AttachShader(program, shader->GetGLShader());
+    if(shader->Compile())
+    {
+      gl.AttachShader(program, shader->GetGLShader());
+    }
   }
   gl.LinkProgram(program);
 
index 4c4b04e..b9af3ea 100644 (file)
 
 // CLASS HEADER
 #include "gles-graphics-sampler.h"
+
+// INTERNAL INCLUDES
+#include "egl-graphics-controller.h"
+
+namespace Dali::Graphics::GLES
+{
+Sampler::Sampler(const Graphics::SamplerCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: SamplerResource(createInfo, controller)
+{
+}
+
+Sampler::~Sampler() = default;
+
+void Sampler::DestroyResource()
+{
+  // For now, no GL resources are initialized so nothing to destroy
+}
+
+bool Sampler::InitializeResource()
+{
+  // For now, there is no support for the modern GL Sampler type (yet)
+  return true;
+}
+
+void Sampler::DiscardResource()
+{
+  GetController().DiscardResource(this);
+}
+} // namespace Dali::Graphics::GLES
index d036b3e..1efcb02 100644 (file)
@@ -37,42 +37,29 @@ public:
    * @param[in] createInfo Valid createInfo structure
    * @param[in] controller Reference to the controller
    */
-  Sampler(const Graphics::SamplerCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
-  : SamplerResource(createInfo, controller)
-  {
-  }
+  Sampler(const Graphics::SamplerCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
 
   /**
    * @brief Destructor
    */
-  ~Sampler() override = default;
+  ~Sampler() override;
 
   /**
    * @brief Called when GL resources are destroyed
    */
-  void DestroyResource() override
-  {
-    // TODO: Implement destroying the resource
-  }
+  void DestroyResource();
 
   /**
    * @brief Called when initializing the resource
    *
    * @return True on success
    */
-  bool InitializeResource() override
-  {
-    // TODO: Implement initializing resource
-    return {};
-  }
+  bool InitializeResource() override;
 
   /**
    * @brief Called when UniquePtr<> on client-side dies
    */
-  void DiscardResource() override
-  {
-    // TODO: Implement moving to the discard queue
-  }
+  void DiscardResource() override;
 };
 
 } // namespace Dali::Graphics::GLES
index 04a1239..46a2968 100644 (file)
@@ -48,6 +48,8 @@ Shader::Shader(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphi
   mCreateInfo.sourceData = mImpl->source.data();
 }
 
+Shader::~Shader() = default;
+
 bool Shader::Compile() const
 {
   auto& gl = *GetController().GetGL();
@@ -126,4 +128,22 @@ uint32_t Shader::GetGLShader() const
   return mImpl->glShader;
 }
 
+void Shader::DestroyResource()
+{
+  if(mImpl->glShader)
+  {
+    auto gl = GetController().GetGL();
+    if(!gl)
+    {
+      return;
+    }
+    gl->DeleteShader(mImpl->glShader);
+  }
+}
+
+void Shader::DiscardResource()
+{
+  GetController().DiscardResource(this);
+}
+
 } // namespace Dali::Graphics::GLES
\ No newline at end of file
index d96223f..3b2abb8 100644 (file)
@@ -42,15 +42,12 @@ public:
   /**
    * @brief Destructor
    */
-  ~Shader() override = default;
+  ~Shader() override;
 
   /**
    * @brief Called when GL resources are destroyed
    */
-  void DestroyResource() override
-  {
-    // TODO: Implement destroying the resource
-  }
+  void DestroyResource() override;
 
   /**
    * @brief Called when initializing the resource
@@ -59,23 +56,22 @@ public:
    */
   bool InitializeResource() override
   {
-    // TODO: Implement initializing resource
-    return {};
+    // The Shader has instant initialization, hence no need to initialize GL resource
+    // here
+    return true;
   }
 
   /**
    * @brief Compiles shader
-   * @return
+   *
+   * @return True on success
    */
-  bool Compile() const;
+  [[nodiscard]] bool Compile() const;
 
   /**
    * @brief Called when UniquePtr<> on client-side dies
    */
-  void DiscardResource() override
-  {
-    // TODO: Implement moving to the discard queue
-  }
+  void DiscardResource() override;
 
   uint32_t GetGLShader() const;
 
index 3ca3620..738e02c 100644 (file)
@@ -164,10 +164,15 @@ bool Texture::InitializeTexture()
 
 void Texture::DestroyResource()
 {
+  auto gl = mController.GetGL();
+  if(!gl)
+  {
+    return;
+  }
+
   // This is a proper destructor
   if(mTextureId)
   {
-    auto gl = mController.GetGL();
     gl->DeleteTextures(1, &mTextureId);
   }
   if(mCreateInfo.nativeImagePtr)
index 9688fba..e1dd665 100644 (file)
@@ -158,12 +158,17 @@ void EglGraphics::Shutdown()
 {
   if(mEglImplementation)
   {
+    // Shutdown controller
+    mGraphicsController.Shutdown();
+
+    // Terminate GLES
     mEglImplementation->TerminateGles();
   }
 }
 
 void EglGraphics::Destroy()
 {
+  mGraphicsController.Destroy();
 }
 
 GlImplementation& EglGraphics::GetGlesInterface()