Merge "Added shader support to pipeline cache" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-shader.cpp
index 46a2968..676884f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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 "gles-graphics-shader.h"
 
 // INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
 #include "egl-graphics-controller.h"
 
 namespace Dali::Graphics::GLES
 {
-struct Shader::Impl
+struct ShaderImpl::Impl
 {
-  Impl()  = default;
-  ~Impl() = default;
-
-  std::vector<char> source{};
-  uint32_t          glShader{};
-};
-
-Shader::Shader(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
-: ShaderResource(createInfo, controller)
-{
-  // push shader to the create queue
-  mImpl = std::make_unique<Impl>();
+  explicit Impl(Graphics::EglGraphicsController& _controller, const Graphics::ShaderCreateInfo& _createInfo)
+  : controller(_controller)
+  {
+    createInfo.pipelineStage  = _createInfo.pipelineStage;
+    createInfo.shaderlanguage = _createInfo.shaderlanguage;
+    createInfo.sourceMode     = _createInfo.sourceMode;
+    createInfo.sourceSize     = _createInfo.sourceSize;
+
+    // Make a copy of source code
+    source.resize(_createInfo.sourceSize);
+    std::copy(reinterpret_cast<const char*>(_createInfo.sourceData),
+              reinterpret_cast<const char*>(_createInfo.sourceData) + _createInfo.sourceSize,
+              source.data());
+
+    // Substitute pointer
+    createInfo.sourceData = source.data();
+  }
 
-  // Make a copy of source code
-  mImpl->source.resize(createInfo.sourceSize);
-  std::copy(reinterpret_cast<const char*>(mCreateInfo.sourceData),
-            reinterpret_cast<const char*>(mCreateInfo.sourceData) + mCreateInfo.sourceSize,
-            mImpl->source.begin());
+  ~Impl(){};
 
-  // Substitute pointer
-  mCreateInfo.sourceData = mImpl->source.data();
-}
+  bool Compile()
+  {
+    auto gl = controller.GetGL();
 
-Shader::~Shader() = default;
+    if(!gl)
+    {
+      return false;
+    }
 
-bool Shader::Compile() const
-{
-  auto& gl = *GetController().GetGL();
-  if(!mImpl->glShader)
-  {
-    GLenum pipelineStage{0u};
-    switch(GetCreateInfo().pipelineStage)
+    if(!glShader)
     {
-      case Graphics::PipelineStage::TOP_OF_PIPELINE:
-      {
-        break;
-      }
-      case Graphics::PipelineStage::VERTEX_SHADER:
+      GLenum pipelineStage{0u};
+      switch(createInfo.pipelineStage)
       {
-        pipelineStage = GL_VERTEX_SHADER;
-        break;
+        case Graphics::PipelineStage::TOP_OF_PIPELINE:
+        {
+          break;
+        }
+        case Graphics::PipelineStage::VERTEX_SHADER:
+        {
+          pipelineStage = GL_VERTEX_SHADER;
+          break;
+        }
+        case Graphics::PipelineStage::GEOMETRY_SHADER:
+        {
+          break;
+        }
+        case Graphics::PipelineStage::FRAGMENT_SHADER:
+        {
+          pipelineStage = GL_FRAGMENT_SHADER;
+          break;
+        }
+        case Graphics::PipelineStage::COMPUTE_SHADER:
+        {
+          break;
+        }
+        case Graphics::PipelineStage::TESSELATION_CONTROL:
+        {
+          break;
+        }
+        case Graphics::PipelineStage::TESSELATION_EVALUATION:
+        {
+          break;
+        }
+        case Graphics::PipelineStage::BOTTOM_OF_PIPELINE:
+        {
+          break;
+        }
       }
-      case Graphics::PipelineStage::GEOMETRY_SHADER:
-      {
-        break;
-      }
-      case Graphics::PipelineStage::FRAGMENT_SHADER:
-      {
-        pipelineStage = GL_FRAGMENT_SHADER;
-        break;
-      }
-      case Graphics::PipelineStage::COMPUTE_SHADER:
-      {
-        break;
-      }
-      case Graphics::PipelineStage::TESSELATION_CONTROL:
-      {
-        break;
-      }
-      case Graphics::PipelineStage::TESSELATION_EVALUATION:
-      {
-        break;
-      }
-      case Graphics::PipelineStage::BOTTOM_OF_PIPELINE:
+
+      if(pipelineStage)
       {
-        break;
+        auto       shader = gl->CreateShader(pipelineStage);
+        const auto src    = reinterpret_cast<const char*>(createInfo.sourceData);
+        GLint      size   = createInfo.sourceSize;
+        gl->ShaderSource(shader, 1, const_cast<const char**>(&src), &size);
+        gl->CompileShader(shader);
+
+        GLint status{0};
+        gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
+        if(status != GL_TRUE)
+        {
+          char    output[4096];
+          GLsizei size{0u};
+          gl->GetShaderInfoLog(shader, 4096, &size, output);
+          DALI_LOG_ERROR("Code: %s\n", reinterpret_cast<const char*>(createInfo.sourceData));
+          DALI_LOG_ERROR("glCompileShader() failed: \n%s\n", output);
+          gl->DeleteShader(shader);
+          return false;
+        }
+        glShader = shader;
       }
+      return true;
     }
+    return true;
+  }
 
-    if(pipelineStage)
-    {
-      auto       shader = gl.CreateShader(pipelineStage);
-      const auto src    = reinterpret_cast<const char*>(GetCreateInfo().sourceData);
-      GLint      size   = GetCreateInfo().sourceSize;
-      gl.ShaderSource(shader, 1, const_cast<const char**>(&src), &size);
-      gl.CompileShader(shader);
-
-      GLint status{0};
-      gl.GetShaderiv(shader, GL_COMPILE_STATUS, &status);
-      if(status != GL_TRUE)
-      {
-        char    output[4096];
-        GLsizei size{0u};
-        gl.GetShaderInfoLog(shader, 4096, &size, output);
-        printf("Code: %s\n", reinterpret_cast<const char*>(GetCreateInfo().sourceData));
-        printf("Log: %s\n", output);
-        gl.DeleteShader(shader);
-        return false;
-      }
+  void Destroy()
+  {
+    auto gl = controller.GetGL();
 
-      // TODO: check error
-      mImpl->glShader = shader;
+    if(gl && glShader)
+    {
+      gl->DeleteShader(glShader);
+      glShader = 0;
     }
-    return true;
   }
-  return true;
+
+  EglGraphicsController& controller;
+  ShaderCreateInfo       createInfo;
+  std::vector<char>      source{};
+
+  uint32_t glShader{};
+  uint32_t refCount{0u};
+  uint32_t flushCount{0u}; ///< Number of frames at refCount=0
+};
+
+ShaderImpl::ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+{
+  mImpl = std::make_unique<Impl>(controller, createInfo);
+}
+
+ShaderImpl::~ShaderImpl()
+{
+  if(!mImpl->controller.IsShuttingDown())
+  {
+    mImpl->Destroy();
+  }
+}
+
+uint32_t ShaderImpl::Retain()
+{
+  mImpl->flushCount = 0;
+  return ++mImpl->refCount;
+}
+
+uint32_t ShaderImpl::Release()
+{
+  uint32_t remainingCount = --mImpl->refCount;
+  mImpl->flushCount       = 0;
+  return remainingCount;
+}
+
+[[nodiscard]] uint32_t ShaderImpl::GetRefCount() const
+{
+  return mImpl->refCount;
+}
+
+[[nodiscard]] uint32_t ShaderImpl::IncreaseFlushCount()
+{
+  return ++mImpl->flushCount;
 }
 
-uint32_t Shader::GetGLShader() const
+[[nodiscard]] uint32_t ShaderImpl::GetFlushCount() const
+{
+  return mImpl->flushCount;
+}
+
+/**
+ * @brief Compiles shader
+ *
+ * @return True on success
+ */
+[[nodiscard]] bool ShaderImpl::Compile() const
+{
+  return mImpl->Compile();
+}
+
+[[nodiscard]] uint32_t ShaderImpl::GetGLShader() const
 {
   return mImpl->glShader;
 }
 
-void Shader::DestroyResource()
+const ShaderCreateInfo& ShaderImpl::GetCreateInfo() const
 {
-  if(mImpl->glShader)
+  return mImpl->createInfo;
+}
+
+[[nodiscard]] EglGraphicsController& ShaderImpl::GetController() const
+{
+  return mImpl->controller;
+}
+
+Shader::~Shader()
+{
+  if(!mShader->Release())
   {
-    auto gl = GetController().GetGL();
-    if(!gl)
-    {
-      return;
-    }
-    gl->DeleteShader(mImpl->glShader);
+    GetImplementation()->GetController().GetPipelineCache().MarkShaderCacheFlushRequired();
   }
 }
 
+[[nodiscard]] const ShaderCreateInfo& Shader::GetCreateInfo() const
+{
+  return GetImplementation()->GetCreateInfo();
+}
+
 void Shader::DiscardResource()
 {
-  GetController().DiscardResource(this);
+  auto& controller = GetImplementation()->GetController();
+  if(!controller.IsShuttingDown())
+  {
+    controller.DiscardResource(this);
+  }
 }
 
-} // namespace Dali::Graphics::GLES
\ No newline at end of file
+} // namespace Dali::Graphics::GLES