Merge "Added shader support to pipeline cache" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-program.cpp
index 5c833f5..3b28c23 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 <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/gl-defines.h>
 
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gGraphicsProgramLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_GRAPHICS_PROGRAM");
+#endif
+
 namespace Dali::Graphics::GLES
 {
 using Integration::GlAbstraction;
 
 /**
+ * Memory compare working on 4-byte types. Since all types used in shaders are
+ * size of 4*N then no need for size and alignment checks.
+ */
+template<class A, class B>
+inline bool memcmp4(A* a, B* b, uint32_t size)
+{
+  auto* pa = reinterpret_cast<const uint32_t*>(a);
+  auto* pb = reinterpret_cast<const uint32_t*>(b);
+  size >>= 2;
+  while(size-- && *pa++ == *pb++)
+    ;
+  return (-1u == size);
+};
+
+/**
  * Structure stores pointer to the function
  * which will set the uniform of particular type
  */
@@ -129,9 +148,9 @@ bool ProgramImpl::Create()
     const auto* shader = static_cast<const GLES::Shader*>(state.shader);
 
     // Compile shader first (ignored when compiled)
-    if(shader->Compile())
+    if(shader->GetImplementation()->Compile())
     {
-      gl->AttachShader(program, shader->GetGLShader());
+      gl->AttachShader(program, shader->GetImplementation()->GetGLShader());
     }
   }
   gl->LinkProgram(program);
@@ -145,8 +164,7 @@ bool ProgramImpl::Create()
     gl->GetProgramInfoLog(program, 4096, &size, output);
 
     // log on error
-    // TODO: un-printf-it
-    printf("Log: %s\n", output);
+    DALI_LOG_ERROR("glLinkProgam failed:\n%s\n", output);
     gl->DeleteProgram(program);
     return false;
   }
@@ -154,8 +172,8 @@ bool ProgramImpl::Create()
   mImpl->glProgram = program;
 
   // Initialize reflection
-  mImpl->reflection->BuildUniformReflection();
   mImpl->reflection->BuildVertexAttributeReflection();
+  mImpl->reflection->BuildUniformBlockReflection();
 
   // populate uniform cache memory for standalone uniforms (it's not needed
   // for real UBOs as real UBOs work with whole memory blocks)
@@ -163,7 +181,7 @@ bool ProgramImpl::Create()
   if(!reflection->GetStandaloneUniformExtraInfo().empty())
   {
     UniformBlockInfo blockInfo;
-    mImpl->reflection->GetUniformBlock(0, blockInfo);
+    reflection->GetUniformBlock(0, blockInfo);
     auto uniformCacheSize = blockInfo.size;
     mImpl->uniformData.resize(uniformCacheSize);
 
@@ -171,6 +189,20 @@ bool ProgramImpl::Create()
 
     BuildStandaloneUniformCache();
   }
+
+  // Set up uniform block bindings
+  auto binding    = 0u;
+  auto blockCount = reflection->GetUniformBlockCount();
+  for(uint32_t i = 1; i < blockCount; ++i) // Ignore emulated block at #0
+  {
+    UniformBlockInfo uboInfo{};
+    reflection->GetUniformBlock(i, uboInfo);
+
+    // make binding point
+    auto blockIndex = gl->GetUniformBlockIndex(program, uboInfo.name.c_str());
+    gl->UniformBlockBinding(program, blockIndex, binding++);
+  }
+
   return true;
 }
 
@@ -189,6 +221,11 @@ uint32_t ProgramImpl::Release()
   return --mImpl->refCount;
 }
 
+uint32_t ProgramImpl::GetRefCount() const
+{
+  return mImpl->refCount;
+}
+
 const GLES::Reflection& ProgramImpl::GetReflection() const
 {
   return *mImpl->reflection;
@@ -228,42 +265,34 @@ void ProgramImpl::UpdateStandaloneUniformBlock(const char* ptr)
   for(const auto& info : extraInfos)
   {
     auto& setter = mImpl->uniformSetters[index++];
-
-    auto offset = info.offset;
-    switch(setter.type)
+    auto  offset = info.offset;
+    if(!memcmp4(&cachePtr[offset], &ptr[offset], info.size * info.arraySize))
     {
-      case UniformSetter::Type::FLOAT:
+      switch(setter.type)
       {
-        if(0 != memcmp(&cachePtr[offset], &ptr[offset], info.size * info.arraySize))
+        case UniformSetter::Type::FLOAT:
         {
           (gl.*(setter.uniformfProc))(info.location, info.arraySize, reinterpret_cast<const float*>(&ptr[offset]));
-          memcpy(&cachePtr[offset], &ptr[offset], info.size * info.arraySize);
+          break;
         }
-        break;
-      }
-      case UniformSetter::Type::INT:
-      {
-        if(0 != memcmp(&cachePtr[offset], &ptr[offset], info.size * info.arraySize))
+        case UniformSetter::Type::INT:
         {
           (gl.*(setter.uniformiProc))(info.location, info.arraySize, reinterpret_cast<const int*>(&ptr[offset]));
-          memcpy(&cachePtr[offset], &ptr[offset], info.size * info.arraySize);
+          break;
         }
-        break;
-      }
-      case UniformSetter::Type::MATRIX:
-      {
-        if(0 != memcmp(&cachePtr[offset], &ptr[offset], info.size * info.arraySize))
+        case UniformSetter::Type::MATRIX:
         {
           (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:
+        {
         }
-        break;
-      }
-      case UniformSetter::Type::UNDEFINED:
-      {
       }
     }
   }
+  // Update caches
+  memmove(mImpl->uniformData.data(), ptr, mImpl->uniformData.size());
 }
 
 void ProgramImpl::BuildStandaloneUniformCache()
@@ -316,6 +345,12 @@ void ProgramImpl::BuildStandaloneUniformCache()
         mImpl->uniformSetters[index].type         = UniformSetter::Type::INT;
         break;
       }
+      case GLType::INT:
+      {
+        mImpl->uniformSetters[index].uniformiProc = &GlAbstraction::Uniform1iv;
+        mImpl->uniformSetters[index].type         = UniformSetter::Type::INT;
+        break;
+      }
       case GLType::BOOL:
       case GLType::BOOL_VEC2:
       case GLType::BOOL_VEC3: