Merge changes I7234d85c,I6a771210 into devel/master
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 18 Jun 2021 13:29:10 +0000 (13:29 +0000)
committerGerrit Code Review <gerrit@review>
Fri, 18 Jun 2021 13:29:10 +0000 (13:29 +0000)
* changes:
  Standalone uniforms cache
  Reduced number of glTexParameteri() calls

dali/internal/graphics/gles-impl/gles-context.cpp
dali/internal/graphics/gles-impl/gles-graphics-program.cpp
dali/internal/graphics/gles-impl/gles-graphics-program.h
dali/internal/graphics/gles-impl/gles-graphics-texture.cpp
dali/internal/graphics/gles-impl/gles-graphics-texture.h

index a0843e6..2a6677d 100644 (file)
@@ -509,106 +509,12 @@ void Context::ResolveUniformBuffers()
 
 void Context::ResolveStandaloneUniforms()
 {
-  auto& gl = *mImpl->mController.GetGL();
-
   // Find reflection for program
   const auto program = static_cast<const GLES::Program*>(mImpl->mNewPipeline->GetCreateInfo().programState->program);
+  const auto ptr     = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress()) + mImpl->mCurrentStandaloneUBOBinding.offset;
 
-  const auto& reflection = program->GetReflection();
-
-  auto extraInfos = reflection.GetStandaloneUniformExtraInfo();
-
-  const auto ptr = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress()) + mImpl->mCurrentStandaloneUBOBinding.offset;
-
-  for(const auto& info : extraInfos)
-  {
-    auto type   = GLTypeConversion(info.type).type;
-    auto offset = info.offset;
-    switch(type)
-    {
-      case GLType::FLOAT_VEC2:
-      {
-        gl.Uniform2fv(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
-        break;
-      }
-      case GLType::FLOAT_VEC3:
-      {
-        gl.Uniform3fv(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
-        break;
-      }
-      case GLType::FLOAT_VEC4:
-      {
-        gl.Uniform4fv(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
-        break;
-      }
-      case GLType::INT_VEC2:
-      {
-        gl.Uniform2iv(info.location, info.arraySize, reinterpret_cast<const GLint*>(&ptr[offset]));
-        break;
-      }
-      case GLType::INT_VEC3:
-      {
-        gl.Uniform3iv(info.location, info.arraySize, reinterpret_cast<const GLint*>(&ptr[offset]));
-        break;
-      }
-      case GLType::INT_VEC4:
-      {
-        gl.Uniform4iv(info.location, info.arraySize, reinterpret_cast<const GLint*>(&ptr[offset]));
-        break;
-      }
-      case GLType::BOOL:
-      {
-        // not supported by DALi
-        break;
-      }
-      case GLType::BOOL_VEC2:
-      {
-        // not supported by DALi
-        break;
-      }
-      case GLType::BOOL_VEC3:
-      {
-        // not supported by DALi
-        break;
-      }
-      case GLType::BOOL_VEC4:
-      {
-        // not supported by DALi
-        break;
-      }
-      case GLType::FLOAT:
-      {
-        gl.Uniform1fv(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
-        break;
-      }
-      case GLType::FLOAT_MAT2:
-      {
-        gl.UniformMatrix2fv(info.location, info.arraySize, GL_FALSE, reinterpret_cast<const float*>(&ptr[offset]));
-        break;
-      }
-      case GLType::FLOAT_MAT3:
-      {
-        gl.UniformMatrix3fv(info.location, info.arraySize, GL_FALSE, reinterpret_cast<const float*>(&ptr[offset]));
-        break;
-      }
-      case GLType::FLOAT_MAT4:
-      {
-        gl.UniformMatrix4fv(info.location, info.arraySize, GL_FALSE, reinterpret_cast<const float*>(&ptr[offset]));
-        break;
-      }
-      case GLType::SAMPLER_2D:
-      {
-        break;
-      }
-      case GLType::SAMPLER_CUBE:
-      {
-        break;
-      }
-      default:
-      {
-      }
-    }
-  }
+  // Update program uniforms
+  program->GetImplementation()->UpdateStandaloneUniformBlock(ptr);
 }
 
 void Context::BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin)
index 64de708..5c833f5 100644 (file)
 
 namespace Dali::Graphics::GLES
 {
+using Integration::GlAbstraction;
+
+/**
+ * Structure stores pointer to the function
+ * which will set the uniform of particular type
+ */
+struct UniformSetter
+{
+  union
+  {
+    void (GlAbstraction::*uniformfProc)(GLint, GLsizei, const float*);
+    void (GlAbstraction::*uniformiProc)(GLint, GLsizei, const int*);
+    void (GlAbstraction::*uniformMatrixProc)(GLint, GLsizei, GLboolean, const float*);
+  };
+
+  enum class Type
+  {
+    UNDEFINED = 0,
+    FLOAT,
+    INT,
+    MATRIX
+  };
+
+  Type type;
+};
+
 struct ProgramImpl::Impl
 {
   explicit Impl(EglGraphicsController& _controller, const ProgramCreateInfo& info)
@@ -51,6 +77,12 @@ struct ProgramImpl::Impl
   uint32_t               refCount{0u};
 
   std::unique_ptr<GLES::Reflection> reflection{nullptr};
+
+  // Uniform cache
+  std::vector<uint8_t> uniformData;
+
+  // List of standalone uniform setters
+  std::vector<UniformSetter> uniformSetters;
 };
 
 ProgramImpl::ProgramImpl(const Graphics::ProgramCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
@@ -125,6 +157,20 @@ bool ProgramImpl::Create()
   mImpl->reflection->BuildUniformReflection();
   mImpl->reflection->BuildVertexAttributeReflection();
 
+  // populate uniform cache memory for standalone uniforms (it's not needed
+  // for real UBOs as real UBOs work with whole memory blocks)
+  auto& reflection = mImpl->reflection;
+  if(!reflection->GetStandaloneUniformExtraInfo().empty())
+  {
+    UniformBlockInfo blockInfo;
+    mImpl->reflection->GetUniformBlock(0, blockInfo);
+    auto uniformCacheSize = blockInfo.size;
+    mImpl->uniformData.resize(uniformCacheSize);
+
+    std::fill(mImpl->uniformData.begin(), mImpl->uniformData.end(), 0);
+
+    BuildStandaloneUniformCache();
+  }
   return true;
 }
 
@@ -168,6 +214,146 @@ const ProgramCreateInfo& ProgramImpl::GetCreateInfo() const
   return mImpl->createInfo;
 }
 
+void ProgramImpl::UpdateStandaloneUniformBlock(const char* ptr)
+{
+  const auto& reflection = GetReflection();
+
+  const auto& extraInfos = reflection.GetStandaloneUniformExtraInfo();
+
+  auto& gl = *GetController().GetGL();
+
+  // Set uniforms
+  int  index    = 0;
+  auto cachePtr = reinterpret_cast<char*>(mImpl->uniformData.data());
+  for(const auto& info : extraInfos)
+  {
+    auto& setter = mImpl->uniformSetters[index++];
+
+    auto offset = info.offset;
+    switch(setter.type)
+    {
+      case UniformSetter::Type::FLOAT:
+      {
+        if(0 != memcmp(&cachePtr[offset], &ptr[offset], info.size * info.arraySize))
+        {
+          (gl.*(setter.uniformfProc))(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
+          memcpy(&cachePtr[offset], &ptr[offset], info.size * info.arraySize);
+        }
+        break;
+      }
+      case UniformSetter::Type::INT:
+      {
+        if(0 != memcmp(&cachePtr[offset], &ptr[offset], info.size * info.arraySize))
+        {
+          (gl.*(setter.uniformiProc))(info.location, info.arraySize, reinterpret_cast<const int*>(&ptr[offset]));
+          memcpy(&cachePtr[offset], &ptr[offset], info.size * info.arraySize);
+        }
+        break;
+      }
+      case UniformSetter::Type::MATRIX:
+      {
+        if(0 != memcmp(&cachePtr[offset], &ptr[offset], info.size * info.arraySize))
+        {
+          (gl.*(setter.uniformMatrixProc))(info.location, info.arraySize, GL_FALSE, reinterpret_cast<const float*>(&ptr[offset]));
+          memcpy(&cachePtr[offset], &ptr[offset], info.size * info.arraySize);
+        }
+        break;
+      }
+      case UniformSetter::Type::UNDEFINED:
+      {
+      }
+    }
+  }
+}
+
+void ProgramImpl::BuildStandaloneUniformCache()
+{
+  const auto& reflection = GetReflection();
+  const auto& extraInfos = reflection.GetStandaloneUniformExtraInfo();
+
+  // Prepare pointers to the uniform setter calls
+  mImpl->uniformSetters.resize(extraInfos.size());
+  int index = 0;
+  for(const auto& info : extraInfos)
+  {
+    auto type                         = GLTypeConversion(info.type).type;
+    mImpl->uniformSetters[index].type = UniformSetter::Type::UNDEFINED;
+    switch(type)
+    {
+      case GLType::FLOAT_VEC2:
+      {
+        mImpl->uniformSetters[index].uniformfProc = &GlAbstraction::Uniform2fv;
+        mImpl->uniformSetters[index].type         = UniformSetter::Type::FLOAT;
+        break;
+      }
+      case GLType::FLOAT_VEC3:
+      {
+        mImpl->uniformSetters[index].uniformfProc = &GlAbstraction::Uniform3fv;
+        mImpl->uniformSetters[index].type         = UniformSetter::Type::FLOAT;
+        break;
+      }
+      case GLType::FLOAT_VEC4:
+      {
+        mImpl->uniformSetters[index].uniformfProc = &GlAbstraction::Uniform4fv;
+        mImpl->uniformSetters[index].type         = UniformSetter::Type::FLOAT;
+        break;
+      }
+      case GLType::INT_VEC2:
+      {
+        mImpl->uniformSetters[index].uniformiProc = &GlAbstraction::Uniform2iv;
+        mImpl->uniformSetters[index].type         = UniformSetter::Type::INT;
+        break;
+      }
+      case GLType::INT_VEC3:
+      {
+        mImpl->uniformSetters[index].uniformiProc = &GlAbstraction::Uniform3iv;
+        mImpl->uniformSetters[index].type         = UniformSetter::Type::INT;
+        break;
+      }
+      case GLType::INT_VEC4:
+      {
+        mImpl->uniformSetters[index].uniformiProc = &GlAbstraction::Uniform4iv;
+        mImpl->uniformSetters[index].type         = UniformSetter::Type::INT;
+        break;
+      }
+      case GLType::BOOL:
+      case GLType::BOOL_VEC2:
+      case GLType::BOOL_VEC3:
+      case GLType::BOOL_VEC4:
+      case GLType::FLOAT:
+      {
+        mImpl->uniformSetters[index].uniformfProc = &GlAbstraction::Uniform1fv;
+        mImpl->uniformSetters[index].type         = UniformSetter::Type::FLOAT;
+        break;
+      }
+      case GLType::FLOAT_MAT2:
+      {
+        mImpl->uniformSetters[index].uniformMatrixProc = &GlAbstraction::UniformMatrix2fv;
+        mImpl->uniformSetters[index].type              = UniformSetter::Type::MATRIX;
+        break;
+      }
+      case GLType::FLOAT_MAT3:
+      {
+        mImpl->uniformSetters[index].uniformMatrixProc = &GlAbstraction::UniformMatrix3fv;
+        mImpl->uniformSetters[index].type              = UniformSetter::Type::MATRIX;
+        break;
+      }
+      case GLType::FLOAT_MAT4:
+      {
+        mImpl->uniformSetters[index].uniformMatrixProc = &GlAbstraction::UniformMatrix4fv;
+        mImpl->uniformSetters[index].type              = UniformSetter::Type::MATRIX;
+        break;
+      }
+      case GLType::SAMPLER_2D:
+      case GLType::SAMPLER_CUBE:
+      default:
+      {
+      }
+    }
+    index++;
+  }
+}
+
 Program::~Program()
 {
   // Destroy GL resources of implementation. This should happen
index 73ed75c..e657e5e 100644 (file)
@@ -120,6 +120,24 @@ public:
    */
   bool GetParameter(uint32_t parameterId, void* out);
 
+  /**
+   * @brief Updates standalone uniforms
+   *
+   * Updates standalone uniforms (issues the GL calls) and
+   * updates internal uniform cache
+   *
+   * @param[in] ptr Valid pointer to the uniform block memory
+   */
+  void UpdateStandaloneUniformBlock(const char* ptr);
+
+  /**
+   * @brief Builds standalone uniform cache
+   *
+   * This function allocates cache memory and
+   * gathers a list of GL functions per uniform type.
+   */
+  void BuildStandaloneUniformCache();
+
 private:
   friend class Program;
 
index 672e56f..aaafc0e 100644 (file)
@@ -134,10 +134,10 @@ bool Texture::InitializeNativeImage()
     gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
 
     // Apply default sampling parameters
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_MIN_FILTER, DALI_MINIFY_DEFAULT);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_MAG_FILTER, DALI_MAGNIFY_DEFAULT);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT);
+    SetSamplerParameter(GL_TEXTURE_MIN_FILTER, mDefaultSamplerState.minFilter, DALI_MINIFY_DEFAULT);
+    SetSamplerParameter(GL_TEXTURE_MAG_FILTER, mDefaultSamplerState.magFilter, DALI_MAGNIFY_DEFAULT);
+    SetSamplerParameter(GL_TEXTURE_WRAP_S, mDefaultSamplerState.wrapS, GL_WRAP_DEFAULT);
+    SetSamplerParameter(GL_TEXTURE_WRAP_T, mDefaultSamplerState.wrapT, GL_WRAP_DEFAULT);
 
     // platform specific implementation decides on what GL extension to use
     if(nativeImage->TargetTexture() != 0u)
@@ -217,12 +217,11 @@ bool Texture::InitializeTexture()
         // Clear staging buffer if there was any
         mStagingBuffer.clear();
         mTextureId = texture;
-
         // Default texture filtering (to be set later via command buffer binding)
-        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
-        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
-        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT);
-        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT);
+        SetSamplerParameter(GL_TEXTURE_MIN_FILTER, mDefaultSamplerState.minFilter, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+        SetSamplerParameter(GL_TEXTURE_MAG_FILTER, mDefaultSamplerState.magFilter, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+        SetSamplerParameter(GL_TEXTURE_WRAP_S, mDefaultSamplerState.wrapS, GL_WRAP_DEFAULT);
+        SetSamplerParameter(GL_TEXTURE_WRAP_T, mDefaultSamplerState.wrapT, GL_WRAP_DEFAULT);
       }
       break;
     }
@@ -238,10 +237,10 @@ bool Texture::InitializeTexture()
         context->BindTexture(GL_TEXTURE_CUBE_MAP, GetTextureTypeId(), texture);
         gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
 
-        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
-        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
-        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT);
-        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT);
+        SetSamplerParameter(GL_TEXTURE_MIN_FILTER, mDefaultSamplerState.minFilter, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+        SetSamplerParameter(GL_TEXTURE_MAG_FILTER, mDefaultSamplerState.magFilter, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+        SetSamplerParameter(GL_TEXTURE_WRAP_S, mDefaultSamplerState.wrapS, GL_WRAP_DEFAULT);
+        SetSamplerParameter(GL_TEXTURE_WRAP_T, mDefaultSamplerState.wrapT, GL_WRAP_DEFAULT);
 
         // Allocate memory for the texture
         for(uint32_t i = 0; i < 6; ++i)
@@ -276,7 +275,7 @@ bool Texture::InitializeTexture()
 
         mTextureId = texture;
 
-        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_WRAP_DEFAULT);
+        SetSamplerParameter(GL_TEXTURE_WRAP_R, mDefaultSamplerState.wrapR, GL_WRAP_DEFAULT);
       }
       break;
     }
@@ -332,30 +331,31 @@ void Texture::Bind(const TextureBinding& binding) const
 
     auto mipMapMode = samplerCreateInfo.mipMapMode;
 
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_MIN_FILTER, GLSamplerFilterAndMipMapMode(samplerCreateInfo.minFilter, mipMapMode).glFilter);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_MAG_FILTER, GLSamplerFilter(samplerCreateInfo.magFilter).glFilter);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_S, GLAddressMode(samplerCreateInfo.addressModeU).texParameter);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_T, GLAddressMode(samplerCreateInfo.addressModeV).texParameter);
+    SetSamplerParameter(GL_TEXTURE_MIN_FILTER, mDefaultSamplerState.minFilter, GLSamplerFilterAndMipMapMode(samplerCreateInfo.minFilter, mipMapMode).glFilter);
+    SetSamplerParameter(GL_TEXTURE_MAG_FILTER, mDefaultSamplerState.magFilter, GLSamplerFilter(samplerCreateInfo.magFilter).glFilter);
+    SetSamplerParameter(GL_TEXTURE_WRAP_S, mDefaultSamplerState.wrapS, GLAddressMode(samplerCreateInfo.addressModeU).texParameter);
+    SetSamplerParameter(GL_TEXTURE_WRAP_T, mDefaultSamplerState.wrapT, GLAddressMode(samplerCreateInfo.addressModeV).texParameter);
+
     if(mGlTarget == GL_TEXTURE_CUBE_MAP)
     {
-      gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_R, GLAddressMode(samplerCreateInfo.addressModeW).texParameter);
+      SetSamplerParameter(GL_TEXTURE_WRAP_R, mDefaultSamplerState.wrapR, GLAddressMode(samplerCreateInfo.addressModeW).texParameter);
     }
   }
   else
   {
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_MIN_FILTER, DALI_MINIFY_DEFAULT);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_MAG_FILTER, DALI_MAGNIFY_DEFAULT);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT);
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT);
+    SetSamplerParameter(GL_TEXTURE_MIN_FILTER, mDefaultSamplerState.minFilter, DALI_MINIFY_DEFAULT);
+    SetSamplerParameter(GL_TEXTURE_MAG_FILTER, mDefaultSamplerState.magFilter, DALI_MAGNIFY_DEFAULT);
+    SetSamplerParameter(GL_TEXTURE_WRAP_S, mDefaultSamplerState.wrapS, GL_WRAP_DEFAULT);
+    SetSamplerParameter(GL_TEXTURE_WRAP_T, mDefaultSamplerState.wrapT, GL_WRAP_DEFAULT);
     if(mGlTarget == GL_TEXTURE_CUBE_MAP)
     {
-      gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_R, GL_WRAP_DEFAULT);
+      SetSamplerParameter(GL_TEXTURE_WRAP_R, mDefaultSamplerState.wrapR, GL_WRAP_DEFAULT);
     }
   }
 
   if(mMaxMipMapLevel)
   {
-    gl->TexParameteri(mGlTarget, GL_TEXTURE_MAX_LEVEL, mMaxMipMapLevel);
+    SetSamplerParameter(GL_TEXTURE_MAX_LEVEL, mDefaultSamplerState.maxLevel, mMaxMipMapLevel);
   }
 }
 
@@ -403,4 +403,14 @@ bool Texture::TryConvertPixelData(const void* pData, Graphics::Format srcFormat,
   return !outputBuffer.empty();
 }
 
+void Texture::SetSamplerParameter(uint32_t param, uint32_t& cacheValue, uint32_t value) const
+{
+  if(cacheValue != value)
+  {
+    auto gl = mController.GetGL();
+    gl->TexParameteri(mGlTarget, param, value);
+    cacheValue = value;
+  }
+}
+
 } // namespace Dali::Graphics::GLES
index 19619e4..2ae566f 100644 (file)
@@ -147,7 +147,19 @@ public:
     return mIsCompressed;
   }
 
+  void SetSamplerParameter(uint32_t param, uint32_t& cacheValue, uint32_t value) const;
+
 private:
+  mutable struct SamplerStateCache
+  {
+    uint32_t minFilter{0};
+    uint32_t magFilter{0};
+    uint32_t wrapS{0};
+    uint32_t wrapT{0};
+    uint32_t wrapR{0};
+    uint32_t maxLevel{0};
+  } mDefaultSamplerState;
+
   std::vector<char> mStagingBuffer;
   uint32_t          mTextureId{0u};
   GLenum            mGlTarget{0u};