Adding uniform block handling for modern shaders 67/294367/5
authorAdam Bialogonski <adam.b@samsung.com>
Thu, 6 Apr 2023 15:15:50 +0000 (16:15 +0100)
committerDavid Steele <david.steele@samsung.com>
Fri, 23 Jun 2023 14:40:50 +0000 (15:40 +0100)
Extract uniform blocks and their uniforms via the reflection interface.

Ensure sampler order is still lexical.

Added buffer offset alignment handling - memory for uniform blocks
within a buffer must be aligned according to the current graphics
context.

Change-Id: I2b06d23057904a2e2ecbb67aff42c229ab89162d

23 files changed:
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.h
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
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-texture.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-trace-call-stack.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-buffer.h
dali/internal/graphics/gles-impl/gles-graphics-command-buffer.cpp
dali/internal/graphics/gles-impl/gles-graphics-program.cpp
dali/internal/graphics/gles-impl/gles-graphics-reflection.cpp
dali/internal/graphics/gles-impl/gles-graphics-reflection.h
dali/internal/graphics/gles-impl/gles-graphics-types.h
dali/internal/graphics/gles-impl/gles3-graphics-memory.cpp

index 1d20a6a..38169a2 100644 (file)
 #include "test-gl-abstraction.h"
 #include "test-trace-call-stack.h"
 
-static const bool TRACE{
-  false};
+static const bool TRACE{false};
+
+uint32_t GetGLDataTypeSize(GLenum type)
+{
+  // There are many more types than what are covered here, but
+  // they are not supported in dali.
+  switch(type)
+  {
+    case GL_FLOAT: // "float", 1 float, 4 bytes
+      return 4;
+    case GL_FLOAT_VEC2: // "vec2", 2 floats, 8 bytes
+      return 8;
+    case GL_FLOAT_VEC3: // "vec3", 3 floats, 12 bytes
+      return 12;
+    case GL_FLOAT_VEC4: // "vec4", 4 floats, 16 bytes
+      return 16;
+    case GL_INT: // "int", 1 integer, 4 bytes
+      return 4;
+    case GL_FLOAT_MAT2: // "mat2", 4 floats, 16 bytes
+      return 16;
+    case GL_FLOAT_MAT3: // "mat3", 3 vec3, 36 bytes
+      return 36;
+    case GL_FLOAT_MAT4: // "mat4", 4 vec4, 64 bytes
+      return 64;
+    default:
+      return 0;
+  }
+}
 
 namespace Dali
 {
@@ -145,6 +171,12 @@ void TestGlAbstraction::Initialize()
     {"uLightCameraProjectionMatrix", GL_FLOAT_MAT4, 1},
     {"uLightCameraViewMatrix", GL_FLOAT_MAT4, 1}};
 
+  int offset = 0;
+  for(uint32_t i = 0; i < mActiveUniforms.size(); ++i)
+  {
+    mActiveUniforms[i].offset = offset;
+    offset += mActiveUniforms[i].size * GetGLDataTypeSize(mActiveUniforms[i].type);
+  }
   // WARNING: IF YOU CHANGE THIS LIST, ALSO CHANGE UNIFORMS IN test-graphics-reflection.cpp
 }
 
@@ -196,6 +228,17 @@ bool TestGlAbstraction::TextureRequiresConverting(const GLenum imageGlFormat, co
   return ((imageGlFormat == GL_RGB) && (textureGlFormat == GL_RGBA));
 }
 
+void TestGlAbstraction::SetActiveUniforms(const std::vector<ActiveUniform>& uniforms)
+{
+  mActiveUniforms = uniforms;
+  int offset      = 0;
+  for(uint32_t i = 0; i < uniforms.size(); ++i)
+  {
+    mActiveUniforms[i].offset = offset;
+    offset += mActiveUniforms[i].size * GetGLDataTypeSize(mActiveUniforms[i].type);
+  }
+}
+
 } // namespace Dali
 
 bool BlendEnabled(const Dali::TraceCallStack& callStack)
index cc27d9e..2ca98dc 100644 (file)
@@ -51,9 +51,10 @@ struct UniformData
 
 struct ActiveUniform
 {
-  std::string name;
-  GLenum      type;
-  GLint       size;
+  std::string name{};
+  GLenum      type{GL_FLOAT};
+  GLint       size{0};
+  GLint       offset{0};
 };
 
 class DALI_CORE_API TestGlAbstraction : public Dali::Integration::GlAbstraction
@@ -457,6 +458,10 @@ public:
 
   inline void DeleteBuffers(GLsizei n, const GLuint* buffers) override
   {
+    TraceCallStack::NamedParams namedParams;
+    namedParams["n"] << n;
+    namedParams["id"] << buffers[0];
+    mBufferTrace.PushCall("DeleteBuffers", namedParams.str(), namedParams);
   }
 
   inline void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) override
@@ -697,13 +702,21 @@ public:
   inline void GenBuffers(GLsizei n, GLuint* buffers) override
   {
     // avoids an assert in GpuBuffers
-    *buffers = 1u;
+    static GLuint id = 1;
 
-    std::ostringstream o;
-    o << n;
     TraceCallStack::NamedParams namedParams;
-    namedParams["n"] << o.str();
-    mBufferTrace.PushCall("GenBuffers", o.str(), namedParams);
+    namedParams["n"] << n;
+
+    // Allocate some buffer names
+    bool first = true;
+    while(n)
+    {
+      namedParams["buffers"] << (first ? "" : ", ") << id;
+      first      = false;
+      *buffers++ = id++;
+      --n;
+    }
+    mBufferTrace.PushCall("GenBuffers", namedParams.str(), namedParams);
   }
 
   inline void GenerateMipmap(GLenum target) override
@@ -800,10 +813,7 @@ public:
     *type = mAttribTypes[index];
   }
 
-  inline void SetActiveUniforms(const std::vector<ActiveUniform>& uniforms)
-  {
-    mActiveUniforms = uniforms;
-  }
+  void SetActiveUniforms(const std::vector<ActiveUniform>& uniforms);
 
   inline void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) override
   {
@@ -865,6 +875,9 @@ public:
       case GL_PROGRAM_BINARY_FORMATS_OES:
         *params = mBinaryFormats;
         break;
+      case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+        *params = mUniformBufferOffsetAlignment;
+        break;
     }
   }
 
@@ -1882,6 +1895,44 @@ public:
 
   inline void GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) override
   {
+    for(int i = 0; i < uniformCount; ++i)
+    {
+      if(i < int(mActiveUniforms.size()))
+      {
+        switch(pname)
+        {
+          case GL_UNIFORM_TYPE:
+          {
+            params[i] = mActiveUniforms[i].type;
+            break;
+          }
+          case GL_UNIFORM_SIZE:
+          {
+            params[i] = mActiveUniforms[i].size;
+            break;
+          }
+          case GL_UNIFORM_NAME_LENGTH:
+          {
+            params[i] = mActiveUniforms[i].name.length();
+            break;
+          }
+          case GL_UNIFORM_BLOCK_INDEX:
+          {
+            params[i] = -1;
+            break;
+          }
+          case GL_UNIFORM_OFFSET:
+          {
+            params[i] = mActiveUniforms[i].offset;
+            break;
+          }
+          case GL_UNIFORM_MATRIX_STRIDE:
+          {
+            break;
+          }
+        }
+      }
+    }
   }
 
   inline GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) override
@@ -2169,7 +2220,10 @@ public: // TEST FUNCTIONS
   {
     mProgramBinaryLength = length;
   }
-
+  inline void SetUniformBufferOffsetAlignment(GLint align)
+  {
+    mUniformBufferOffsetAlignment = align;
+  }
   inline bool GetVertexAttribArrayState(GLuint index)
   {
     if(index >= MAX_ATTRIBUTE_CACHE_SIZE)
@@ -2582,6 +2636,7 @@ public:
   GLint                                 mNumBinaryFormats;
   GLint                                 mBinaryFormats;
   GLint                                 mProgramBinaryLength;
+  GLint                                 mUniformBufferOffsetAlignment{1};
   bool                                  mVertexAttribArrayState[MAX_ATTRIBUTE_CACHE_SIZE];
   bool                                  mVertexAttribArrayChanged; // whether the vertex attrib array has been changed
   bool                                  mGetProgramBinaryCalled;
index 42b53b1..456d978 100644 (file)
 
 namespace Dali
 {
-TestGraphicsBuffer::TestGraphicsBuffer(TraceCallStack& callStack, TestGlAbstraction& glAbstraction, uint32_t size, Graphics::BufferUsageFlags usage)
+TestGraphicsBuffer::TestGraphicsBuffer(const Graphics::BufferCreateInfo& createInfo, TestGraphicsController& controller, TestGlAbstraction& glAbstraction, TraceCallStack& callStack)
 : mCallStack(callStack),
+  mController(controller),
   mGl(glAbstraction),
-  mUsage(usage)
+  mCreateInfo(createInfo),
+  mUsage(createInfo.usage)
 {
-  memory.resize(size);
-  mGl.GetBufferTrace().EnableLogging(false);
+  if(createInfo.propertiesFlags & int(Graphics::BufferPropertiesFlagBit::CPU_ALLOCATED))
+  {
+    mCpuOnly = true;
+  }
+  else
+  {
+    mGl.GenBuffers(1, &mId);
+  }
+  memory.resize(createInfo.size);
+}
+
+TestGraphicsBuffer::~TestGraphicsBuffer()
+{
+  // Not strictly parameters, but useful for testing
+  TraceCallStack::NamedParams namedParams;
+  namedParams["usage"] << "0x" << std::hex << mCreateInfo.usage;
+  namedParams["propertiesFlags"] << mCreateInfo.propertiesFlags;
+
+  mCallStack.PushCall("Buffer::~Buffer", namedParams.str(), namedParams);
+  if(!mCpuOnly && mId)
+  {
+    mGl.DeleteBuffers(1, &mId);
+  }
+}
+
+void TestGraphicsBuffer::DiscardResource()
+{
+  mController.DiscardBuffer(this);
 }
 
 void TestGraphicsBuffer::Bind()
 {
   mCallStack.PushCall("Buffer::Bind", "");
-  if(!mId)
+  if(!mCpuOnly && mId > 0)
   {
-    mGl.GenBuffers(1, &mId);
+    mGl.BindBuffer(GetTarget(), mId);
   }
-  mGl.BindBuffer(GetTarget(), mId);
 }
 
 void TestGraphicsBuffer::Unbind()
 {
   mCallStack.PushCall("Buffer::Unbind", "");
-  if(mId)
+  if(!mCpuOnly)
   {
-    mGl.BindBuffer(GetTarget(), 0);
+    if(mId)
+    {
+      mGl.BindBuffer(GetTarget(), 0);
+    }
   }
 }
 
@@ -58,15 +88,19 @@ void TestGraphicsBuffer::Upload(uint32_t offset, uint32_t size)
   namedParams["offset"] << offset;
   namedParams["size"] << size;
   mCallStack.PushCall("Buffer::Upload", o.str(), namedParams);
-  if(size <= memory.size() && mCreated)
-  {
-    // Use subData to avoid re-allocation
-    mGl.BufferSubData(GetTarget(), static_cast<GLintptr>(static_cast<unsigned long>(offset)), static_cast<GLsizeiptr>(static_cast<unsigned long>(size)), &memory[offset]);
-  }
-  else
+
+  if(!mCpuOnly)
   {
-    mGl.BufferData(GetTarget(), static_cast<GLsizeiptr>(static_cast<unsigned long>(size)), &memory[0], GL_STATIC_DRAW); //@todo Query - do we need other usages?
-    mCreated = true;
+    if(size <= memory.size() && mCreated)
+    {
+      // Use subData to avoid re-allocation
+      mGl.BufferSubData(GetTarget(), static_cast<GLintptr>(static_cast<unsigned long>(offset)), static_cast<GLsizeiptr>(static_cast<unsigned long>(size)), &memory[offset]);
+    }
+    else
+    {
+      mGl.BufferData(GetTarget(), static_cast<GLsizeiptr>(static_cast<unsigned long>(size)), &memory[0], GL_STATIC_DRAW); //@todo Query - do we need other usages?
+      mCreated = true;
+    }
   }
 }
 
index 1dc2715..220ae06 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEST_GRAPHICS_BUFFER_H
 
 /*
- * 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.
@@ -17,6 +17,7 @@
  * limitations under the License.
  */
 
+#include <dali/graphics-api/graphics-buffer-create-info.h>
 #include <dali/graphics-api/graphics-buffer.h>
 #include <dali/graphics-api/graphics-types.h>
 
 namespace Dali
 {
 class TestGraphicsProgram;
+class TestGraphicsController;
 class UniformBufferBindingDescriptor;
+
 class TestGraphicsBuffer : public Graphics::Buffer
 {
 public:
-  TestGraphicsBuffer(TraceCallStack& callStack, TestGlAbstraction& glAbstraction, uint32_t size, Graphics::BufferUsageFlags usage);
+  TestGraphicsBuffer(const Graphics::BufferCreateInfo& createInfo, TestGraphicsController& controller, TestGlAbstraction& glAbstraction, TraceCallStack& callStack);
+  ~TestGraphicsBuffer();
+  void DiscardResource();
+
   void   Bind();
   void   Unbind();
   void   Upload(uint32_t offset, uint32_t size);
@@ -38,17 +44,21 @@ public:
 
   bool IsCPUAllocated() const
   {
-    return true;
+    return mCpuOnly;
   }
 
   void BindAsUniformBuffer(const TestGraphicsProgram* program, const Dali::UniformBufferBindingDescriptor& uboBinding) const;
 
-  TraceCallStack&            mCallStack;
-  TestGlAbstraction&         mGl;
-  std::vector<uint8_t>       memory;
+  TraceCallStack&         mCallStack;
+  TestGraphicsController& mController;
+  TestGlAbstraction&      mGl;
+  std::vector<uint8_t>    memory;
+
+  Graphics::BufferCreateInfo mCreateInfo;
   Graphics::BufferUsageFlags mUsage;
   GLuint                     mId{0};
   bool                       mCreated{false};
+  bool                       mCpuOnly{false};
 };
 
 } // namespace Dali
index 14c6d50..4bac7a6 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "test-graphics-controller.h"
 
+#include <dali/graphics-api/graphics-types.h>
 #include "test-graphics-buffer.h"
 #include "test-graphics-command-buffer.h"
 #include "test-graphics-framebuffer.h"
 #include "test-graphics-texture.h"
 
 #include <dali/integration-api/gl-defines.h>
+#include <any>
 #include <cstdio>
 #include <iostream>
+#include <memory>
 #include <sstream>
 
-#include <any>
-
 namespace Dali
 {
+namespace
+{
+template<class T>
+struct TestGraphicsDeleter
+{
+  TestGraphicsDeleter() = default;
+  void operator()(T* object)
+  {
+    // Discard resource
+    object->DiscardResource();
+  }
+};
+
+} //namespace
+
 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
 {
   return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
@@ -1185,10 +1201,25 @@ bool TestGraphicsController::IsDrawOnResumeRequired()
 
 Graphics::UniquePtr<Graphics::Buffer> TestGraphicsController::CreateBuffer(const Graphics::BufferCreateInfo& createInfo, Graphics::UniquePtr<Graphics::Buffer>&& oldBuffer)
 {
-  std::ostringstream oss;
-  oss << "bufferCreateInfo:" << createInfo;
-  mCallStack.PushCall("CreateBuffer", oss.str());
-  return Graphics::MakeUnique<TestGraphicsBuffer>(mCallStack, mGl, createInfo.size, createInfo.usage);
+  TraceCallStack::NamedParams namedParams;
+  namedParams["usage"] << "0x" << std::hex << createInfo.usage;
+  namedParams["propertiesFlags"] << createInfo.propertiesFlags;
+  namedParams["size"] << createInfo.size;
+  mCallStack.PushCall("CreateBuffer", namedParams.str(), namedParams);
+
+  auto ptr = Graphics::MakeUnique<TestGraphicsBuffer, TestGraphicsDeleter<TestGraphicsBuffer>>(createInfo, *this, mGl, mCallStack);
+  mAllocatedBuffers.push_back(ptr.get());
+  return ptr;
+}
+
+void TestGraphicsController::DiscardBuffer(TestGraphicsBuffer* buffer)
+{
+  auto iter = std::find(mAllocatedBuffers.begin(), mAllocatedBuffers.end(), buffer);
+  if(iter != mAllocatedBuffers.end())
+  {
+    mAllocatedBuffers.erase(iter);
+  }
+  delete buffer;
 }
 
 Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateCommandBuffer(const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr<Graphics::CommandBuffer>&& oldCommandBuffer)
@@ -1258,7 +1289,8 @@ Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(con
   }
 
   mProgramCache.emplace_back();
-  mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats, mCustomUniforms);
+  mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats, mCustomUniforms, mCustomUniformBlocks);
+
   for(auto& shader : *(programCreateInfo.shaderState))
   {
     auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
@@ -1329,8 +1361,24 @@ Graphics::MemoryRequirements TestGraphicsController::GetTextureMemoryRequirement
 
 Graphics::MemoryRequirements TestGraphicsController::GetBufferMemoryRequirements(Graphics::Buffer& buffer) const
 {
+  static GLint uniformAlign{0};
+
+  Graphics::MemoryRequirements reqs{};
   mCallStack.PushCall("GetBufferMemoryRequirements", "");
-  return Graphics::MemoryRequirements{};
+
+  auto gfxBuffer = Uncast<TestGraphicsBuffer>(&buffer);
+  if(gfxBuffer->mCreateInfo.usage & (0 | Graphics::BufferUsage::UNIFORM_BUFFER))
+  {
+    if(!uniformAlign)
+    {
+      // Throw off the shackles of constness
+      auto& gl = *const_cast<TestGlAbstraction*>(&mGl);
+      gl.GetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniformAlign);
+    }
+    reqs.size      = gfxBuffer->mCreateInfo.size;
+    reqs.alignment = uint32_t(uniformAlign);
+  }
+  return reqs;
 }
 
 Graphics::TextureProperties TestGraphicsController::GetTextureProperties(const Graphics::Texture& texture)
index 81b93d2..ade48d7 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_GRAPHICS_CONTROLLER_H
 
 /*
- * Copyright (c) 2022 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.
@@ -207,6 +207,8 @@ public:
    */
   Graphics::UniquePtr<Graphics::Buffer> CreateBuffer(const Graphics::BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Graphics::Buffer>&& oldBuffer) override;
 
+  void DiscardBuffer(TestGraphicsBuffer* buffer);
+
   /**
    * @brief Creates new CommandBuffer object
    *
@@ -384,6 +386,11 @@ public: // Test Functions
     mCustomUniforms = customUniforms;
   }
 
+  void AddCustomUniformBlock(const TestGraphicsReflection::TestUniformBlockInfo& blockInfo)
+  {
+    mCustomUniformBlocks.push_back(blockInfo);
+  }
+
   void ClearSubmitStack()
   {
     mSubmitStack.clear();
@@ -427,11 +434,14 @@ public:
   };
   std::vector<ProgramCache> mProgramCache;
 
+  std::vector<TestGraphicsBuffer*> mAllocatedBuffers;
+
   struct PipelineCache
   {
   };
 
-  std::vector<UniformData> mCustomUniforms;
+  std::vector<UniformData>                                  mCustomUniforms;
+  std::vector<TestGraphicsReflection::TestUniformBlockInfo> mCustomUniformBlocks;
 };
 
 } // namespace Dali
index 8f2e0c7..2706305 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 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.
 
 namespace Dali
 {
-TestGraphicsProgramImpl::TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector<UniformData>& customUniforms)
+TestGraphicsProgramImpl::TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector<UniformData>& customUniforms, std::vector<TestGraphicsReflection::TestUniformBlockInfo>& customUniformBlocks)
 : mGl(gl),
   mId(gl.CreateProgram()),
   mCreateInfo(createInfo),
-  mReflection(gl, mId, vertexFormats, createInfo, customUniforms)
+  mReflection(gl, mId, vertexFormats, createInfo, customUniforms, customUniformBlocks)
 {
   // Ensure active sampler uniforms are set
   mGl.SetCustomUniforms(customUniforms);
index 3899bec..8641800 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEST_GRAPHICS_PROGRAM_H
 
 /*
- * 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.
@@ -27,7 +27,7 @@ namespace Dali
 class TestGraphicsProgramImpl
 {
 public:
-  TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector<UniformData>& customUniforms);
+  TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector<UniformData>& customUniforms, std::vector<TestGraphicsReflection::TestUniformBlockInfo>& customUniformBlocks);
 
   // For API
   const TestGraphicsReflection& GetReflection() const
index 6cb90ba..2822c0a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 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/public-api/object/property-map.h>
 #include <string>
 #include <vector>
+
+extern "C"
+{
+  void tet_infoline(const char* str);
+  void tet_printf(const char* format, ...);
+}
+
 namespace Dali
 {
 namespace
@@ -103,7 +110,7 @@ constexpr int GetSizeForType(Property::Type type)
 
 } // namespace
 
-TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, uint32_t programId, Property::Array& vfs, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms)
+TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, uint32_t programId, Property::Array& vfs, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms, std::vector<TestGraphicsReflection::TestUniformBlockInfo>& customUniformBlocks)
 : mGl(gl),
   mCustomUniforms(customUniforms)
 {
@@ -226,6 +233,10 @@ TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, uint32_t p
   mDefaultUniformBlock.size = offset;
 
   mUniformBlocks.push_back(mDefaultUniformBlock);
+  for(auto& element : customUniformBlocks)
+  {
+    mUniformBlocks.push_back(element);
+  }
 }
 
 uint32_t TestGraphicsReflection::GetVertexAttributeLocation(const std::string& name) const
@@ -247,11 +258,13 @@ uint32_t TestGraphicsReflection::GetVertexAttributeLocation(const std::string& n
 
 Dali::Graphics::VertexInputAttributeFormat TestGraphicsReflection::GetVertexAttributeFormat(uint32_t location) const
 {
+  tet_infoline("Warning, TestGraphicsReflection::GetVertexAttributeFormat is unimplemented\n");
   return Dali::Graphics::VertexInputAttributeFormat{};
 }
 
 std::string TestGraphicsReflection::GetVertexAttributeName(uint32_t location) const
 {
+  tet_infoline("Warning, TestGraphicsReflection::GetVertexAttributeName is unimplemented\n");
   return 0u;
 }
 
@@ -272,7 +285,11 @@ uint32_t TestGraphicsReflection::GetUniformBlockCount() const
 
 uint32_t TestGraphicsReflection::GetUniformBlockBinding(uint32_t index) const
 {
-  return 0u;
+  if(index >= mUniformBlocks.size())
+  {
+    return 0;
+  }
+  return mUniformBlocks[index].binding;
 }
 
 uint32_t TestGraphicsReflection::GetUniformBlockSize(uint32_t index) const
@@ -316,11 +333,13 @@ bool TestGraphicsReflection::GetUniformBlock(uint32_t index, Dali::Graphics::Uni
 
 std::vector<uint32_t> TestGraphicsReflection::GetUniformBlockLocations() const
 {
+  tet_infoline("Warning, TestGraphicsReflection::GetUniformBlockLocations is unimplemented\n");
   return std::vector<uint32_t>{};
 }
 
 std::string TestGraphicsReflection::GetUniformBlockName(uint32_t blockIndex) const
 {
+  tet_infoline("Warning, TestGraphicsReflection::GetUniformBlockName is unimplemented\n");
   return std::string{};
 }
 
@@ -362,11 +381,13 @@ uint32_t TestGraphicsReflection::GetUniformBlockMemberOffset(uint32_t blockIndex
 
 bool TestGraphicsReflection::GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const
 {
+  tet_infoline("Warning, TestGraphicsReflection::GetNamedUniform is unimplemented\n");
   return true;
 }
 
 const std::vector<Dali::Graphics::UniformInfo>& TestGraphicsReflection::GetSamplers() const
 {
+  tet_infoline("Warning, TestGraphicsReflection::GetSamplers is unimplemented\n");
   static std::vector<Dali::Graphics::UniformInfo> samplers{};
   return samplers;
 }
index e968bd5..e701e17 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEST_GRAPHICS_REFLECTION_H
 
 /*
- * Copyright (c) 2022 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.
@@ -26,7 +26,9 @@ namespace Dali
 class TestGraphicsReflection : public Graphics::Reflection
 {
 public:
-  TestGraphicsReflection(TestGlAbstraction& gl, uint32_t program_id, Property::Array& vertexFormats, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms);
+  class TestUniformBlockInfo;
+
+  TestGraphicsReflection(TestGlAbstraction& gl, uint32_t program_id, Property::Array& vertexFormats, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms, std::vector<TestUniformBlockInfo>& customUniformBlocks);
 
   uint32_t                                        GetVertexAttributeLocation(const std::string& name) const override;
   Dali::Graphics::VertexInputAttributeFormat      GetVertexAttributeFormat(uint32_t location) const override;
index 782904c..4d86364 100644 (file)
@@ -31,7 +31,7 @@ class TestGraphicsTexture : public Graphics::Texture
 public:
   TestGraphicsTexture(TestGlAbstraction& glAbstraction, const Graphics::TextureCreateInfo& createInfo);
 
-  ~TestGraphicsTexture();
+  ~TestGraphicsTexture() override;
 
   /**
    * Initialize the texture: allocate gl mem, apply default samplers
index 2316036..1284793 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 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.
@@ -248,11 +248,15 @@ int TraceCallStack::FindIndexFromMethodAndParams(std::string method, const Trace
 
       for(auto iter = params.mParams.begin(); iter != params.mParams.end(); ++iter)
       {
-        auto        paramIter = mCallStack[i].namedParams.find(iter->parameterName);
-        std::string value     = paramIter->value.str();
-        std::string iValue    = iter->value.str();
-
-        if(paramIter == mCallStack[i].namedParams.end() || value.compare(iValue))
+        auto paramIter = mCallStack[i].namedParams.find(iter->parameterName);
+        if(paramIter == mCallStack[i].namedParams.end())
+        {
+          match = false;
+          break;
+        }
+        std::string value  = paramIter->value.str();
+        std::string iValue = iter->value.str();
+        if(value.compare(iValue))
         {
           match = false;
           break;
index 4c02256..81616aa 100644 (file)
@@ -335,6 +335,20 @@ Graphics::UniquePtr<SyncObject> EglGraphicsController::CreateSyncObject(const Sy
   }
 }
 
+MemoryRequirements EglGraphicsController::GetBufferMemoryRequirements(Buffer& buffer) const
+{
+  MemoryRequirements requirements{};
+
+  auto gl = GetGL();
+  if(gl)
+  {
+    GLint align;
+    gl->GetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &align);
+    requirements.alignment = align;
+  }
+  return requirements;
+}
+
 TextureProperties EglGraphicsController::GetTextureProperties(const Texture& texture)
 {
   const GLES::Texture* glesTexture = static_cast<const GLES::Texture*>(&texture);
@@ -916,12 +930,14 @@ void EglGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& text
 
 Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
 {
-  mGraphics->ActivateResourceContext();
-
   // Mapping buffer requires the object to be created NOW
   // Workaround - flush now, otherwise there will be given a staging buffer
   // in case when the buffer is not there yet
-  ProcessCreateQueues();
+  if(!mCreateBufferQueue.empty())
+  {
+    mGraphics->ActivateResourceContext();
+    ProcessCreateQueues();
+  }
 
   if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
   {
index a8edd34..4693721 100644 (file)
@@ -295,10 +295,7 @@ public:
   /**
    * @copydoc Dali::Graphics::GetBufferMemoryRequirements()
    */
-  MemoryRequirements GetBufferMemoryRequirements(Buffer& buffer) const override
-  {
-    return {};
-  }
+  MemoryRequirements GetBufferMemoryRequirements(Buffer& buffer) const override;
 
   /**
    * @copydoc Dali::Graphics::GetTextureProperties()
index 369af21..3f15dae 100644 (file)
@@ -564,9 +564,9 @@ void Context::BindUniformBuffers(const UniformBufferBindingDescriptor* uboBindin
     mImpl->mCurrentStandaloneUBOBinding = standaloneBindings;
   }
 
-  if(uboCount >= mImpl->mCurrentUBOBindings.size())
+  if(uboCount && uboCount > mImpl->mCurrentUBOBindings.size())
   {
-    mImpl->mCurrentUBOBindings.resize(uboCount + 1);
+    mImpl->mCurrentUBOBindings.resize(uboCount);
   }
 
   auto it = uboBindings;
@@ -576,6 +576,7 @@ void Context::BindUniformBuffers(const UniformBufferBindingDescriptor* uboBindin
     {
       mImpl->mCurrentUBOBindings[i] = *it;
     }
+    ++it;
   }
 }
 
@@ -705,6 +706,20 @@ void Context::ResolveUniformBuffers()
   {
     ResolveStandaloneUniforms();
   }
+  if(!mImpl->mCurrentUBOBindings.empty())
+  {
+    ResolveGpuUniformBuffers();
+  }
+}
+
+void Context::ResolveGpuUniformBuffers()
+{
+  auto& gl = *mImpl->mController.GetGL();
+  auto  i  = 0u;
+  for(auto& binding : mImpl->mCurrentUBOBindings)
+  {
+    gl.BindBufferRange(GL_UNIFORM_BUFFER, i++, binding.buffer->GetGLBuffer(), binding.offset, binding.dataSize);
+  }
 }
 
 void Context::ResolveStandaloneUniforms()
@@ -851,6 +866,7 @@ void Context::EndRenderPass(GLES::TextureDependencyChecker& dependencyChecker)
 void Context::ClearState()
 {
   mImpl->mCurrentTextureBindings.clear();
+  mImpl->mCurrentUBOBindings.clear();
 }
 
 void Context::ColorMask(bool enabled)
index 55f1db6..fb6f7ff 100644 (file)
@@ -129,6 +129,11 @@ public:
   void ResolveStandaloneUniforms();
 
   /**
+   * @brief Resolves GPU-based uniform buffers
+   */
+  void ResolveGpuUniformBuffers();
+
+  /**
    * @brief Begins render pass for specified render target
    *
    * @param[in] renderPass render pass object to begin
index 3ac11cf..9810eea 100644 (file)
@@ -79,7 +79,6 @@ public:
   }
 
 private:
-
   void InitializeCPUBuffer();
 
   void InitializeGPUBuffer();
@@ -89,20 +88,9 @@ private:
   bool     mCpuAllocated{false};
   bool     mTransient{false};
 
-  bool     mSetForGLRecycling{false}; ///< If flag set true the buffer will recycle
+  bool mSetForGLRecycling{false}; ///< If flag set true the buffer will recycle
 };
 } // namespace GLES
 } // namespace Dali::Graphics
 
-template<>
-struct std::default_delete<Dali::Graphics::Buffer>
-{
-  void operator()(Dali::Graphics::Buffer* object)
-  {
-    // Add to the queue
-    auto resource = static_cast<Dali::Graphics::GLES::Buffer*>(object);
-    resource->DiscardResource();
-  }
-};
-
-#endif
\ No newline at end of file
+#endif
index 70dfbb8..e1e57af 100644 (file)
@@ -270,9 +270,14 @@ void CommandBuffer::BindUniformBuffers(const std::vector<Graphics::UniformBuffer
   // TODO: could use vector?
   static thread_local UniformBufferBindingDescriptor sTempBindings[MAX_UNIFORM_BUFFER_BINDINGS];
 
-  auto maxBindingCount = 0u;
+  // reset temp bindings
+  memset(sTempBindings, 0, sizeof(UniformBufferBindingDescriptor) * MAX_UNIFORM_BUFFER_BINDINGS);
+
+  auto maxBinding  = 0u;
+  bool hasBindings = false;
 
   // find max binding and standalone UBO
+  memset(&bindCmd.standaloneUniformsBufferBinding, 0, sizeof(UniformBufferBindingDescriptor));
   for(const auto& binding : bindings)
   {
     if(binding.buffer)
@@ -287,18 +292,16 @@ void CommandBuffer::BindUniformBuffers(const std::vector<Graphics::UniformBuffer
       }
       else // Bind regular UBO
       {
-        if(DALI_UNLIKELY(maxBindingCount == 0u))
-        {
-          // We can assume here comes first time. Reset temp bindings
-          std::fill_n(sTempBindings, MAX_UNIFORM_BUFFER_BINDINGS, UniformBufferBindingDescriptor());
-        }
-        auto& slot    = sTempBindings[binding.binding];
-        slot.buffer   = glesBuffer;
-        slot.offset   = binding.offset;
-        slot.binding  = binding.binding;
-        slot.emulated = false;
-
-        maxBindingCount = std::max(maxBindingCount, binding.binding + 1u);
+        auto& slot      = sTempBindings[binding.binding];
+        slot.buffer     = glesBuffer;
+        slot.offset     = binding.offset;
+        slot.binding    = binding.binding;
+        slot.blockIndex = 0;
+        slot.binding    = binding.binding; // implicitly
+        slot.dataSize   = binding.dataSize;
+        slot.emulated   = false;
+        maxBinding      = std::max(maxBinding, binding.binding);
+        hasBindings     = true;
       }
     }
   }
@@ -306,13 +309,26 @@ void CommandBuffer::BindUniformBuffers(const std::vector<Graphics::UniformBuffer
   bindCmd.uniformBufferBindingsCount = 0u;
 
   // copy data
-  if(maxBindingCount)
+  if(hasBindings)
   {
-    auto destBindings = mCommandPool->Allocate<UniformBufferBindingDescriptor>(maxBindingCount);
+    auto destBindings = mCommandPool->Allocate<UniformBufferBindingDescriptor>(maxBinding + 1);
     // copy
-    memcpy(destBindings.Ptr(), sTempBindings, sizeof(UniformBufferBindingDescriptor) * (maxBindingCount));
+    auto size = sizeof(UniformBufferBindingDescriptor) * (maxBinding + 1);
+    if(!(size % sizeof(intptr_t)))
+    {
+      auto* srcPtr = reinterpret_cast<intptr_t*>(sTempBindings);
+      auto* dstPtr = reinterpret_cast<intptr_t*>(destBindings.Ptr());
+      for(auto i = 0u; i < size / sizeof(intptr_t); ++i)
+      {
+        *dstPtr++ = *srcPtr++;
+      }
+    }
+    else
+    {
+      memcpy(destBindings.Ptr(), sTempBindings, size);
+    }
     bindCmd.uniformBufferBindings      = destBindings;
-    bindCmd.uniformBufferBindingsCount = maxBindingCount;
+    bindCmd.uniformBufferBindingsCount = maxBinding + 1;
   }
 }
 
index 8fa051c..25c67c5 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;
@@ -160,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_INFO(gGraphicsProgramLogFilter, Debug::Verbose, "Log: %s\n", output);
     gl->DeleteProgram(program);
     return false;
   }
@@ -169,7 +172,7 @@ bool ProgramImpl::Create()
   mImpl->glProgram = program;
 
   // Initialize reflection
-  mImpl->reflection->BuildUniformReflection();
+  mImpl->reflection->BuildUniformBlockReflection();
   mImpl->reflection->BuildVertexAttributeReflection();
 
   // populate uniform cache memory for standalone uniforms (it's not needed
@@ -178,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);
 
@@ -186,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;
 }
 
index 04247c8..fb83dc3 100644 (file)
@@ -118,16 +118,6 @@ bool IsSampler(GLenum type)
   return type == GL_SAMPLER_2D || type == GL_SAMPLER_3D || type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES;
 }
 
-bool SortUniformInfoByLocation(Dali::Graphics::UniformInfo a, Dali::Graphics::UniformInfo b)
-{
-  return a.location < b.location;
-}
-
-bool SortUniformExtraInfoByLocation(Dali::Graphics::GLES::Reflection::UniformExtraInfo a, Dali::Graphics::GLES::Reflection::UniformExtraInfo b)
-{
-  return a.location < b.location;
-}
-
 std::string GetShaderSource(Dali::Graphics::ShaderState shaderState)
 {
   std::vector<uint8_t> data;
@@ -278,194 +268,161 @@ void Reflection::BuildVertexAttributeReflection()
   delete[] name;
 }
 
-void Reflection::BuildUniformReflection()
+void Reflection::BuildUniformBlockReflection()
 {
-  auto glProgram = mProgram.GetGlProgram();
-
-  int   maxLen;
+  auto  gl        = mController.GetGL();
+  auto  glProgram = mProgram.GetGlProgram();
   char* name;
+  int   numUniformBlocks = 0;
 
-  int numUniforms = 0;
-
-  auto gl = mController.GetGL();
   if(!gl)
   {
     // Do nothing during shutdown
     return;
   }
 
-  DALI_LOG_INFO(gGraphicsReflectionLogFilter, Debug::General, "Build uniform reflection for glProgram : %u\n", glProgram);
+  DALI_LOG_INFO(gGraphicsReflectionLogFilter, Debug::General, "Build uniform block reflection for glProgram : %u\n", glProgram);
 
-  gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
-  gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
+  int   maxUniformNameLength;
+  GLint activeUniformCount = 0;
+  gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
+  gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &activeUniformCount);
+  gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformNameLength);
 
-  mUniformBlocks.clear();
-  mDefaultUniformBlock.members.clear();
-  mUniformOpaques.clear();
+  numUniformBlocks++; // add block 0 for standalone UBO block
 
-  name = new char[maxLen];
+  mUniformBlocks.resize(numUniformBlocks);
+  mUniformOpaques.clear();
 
   mStandaloneUniformExtraInfos.clear();
 
-  for(int i = 0; i < numUniforms; ++i)
+  std::vector<GLuint> uniformIndices;
+  uniformIndices.reserve(activeUniformCount);
+  for(auto i = 0; i < activeUniformCount; ++i)
   {
-    int    elementCount;
-    GLenum type;
-    int    written;
-    gl->GetActiveUniform(glProgram, i, maxLen, &written, &elementCount, &type, name);
-
-    int location = gl->GetUniformLocation(glProgram, name);
+    uniformIndices.emplace_back(i);
+  }
 
-    Dali::Graphics::UniformInfo uniformInfo;
+  // Obtain all parameters for active uniforms
+  auto getActiveUniformParams = [gl, glProgram, uniformIndices](GLenum param) {
+    std::vector<GLint> params;
+    params.resize(uniformIndices.size());
+    gl->GetActiveUniformsiv(glProgram, uniformIndices.size(), uniformIndices.data(), param, params.data());
+    return params;
+  };
 
-    uniformInfo.name = name;
-    if(elementCount > 1)
-    {
-      // If we have an active uniform that refers to an array, only the first element
-      // is present in this list, and is referenced as "uniform[0]", but the element
-      // count is non-zero to indicate how many uniforms there are in the array.
+  auto activeUniformType       = getActiveUniformParams(GL_UNIFORM_TYPE);
+  auto activeUniformSize       = getActiveUniformParams(GL_UNIFORM_SIZE);
+  auto activeUniformNameLength = getActiveUniformParams(GL_UNIFORM_NAME_LENGTH);
+  auto activeUniformBlockIndex = getActiveUniformParams(GL_UNIFORM_BLOCK_INDEX);
+  auto activeUniformOffset     = getActiveUniformParams(GL_UNIFORM_OFFSET);
 
-      // Strip off the array, but store the element count
-      auto iter = std::string(uniformInfo.name).find("[", 0);
-      if(iter != std::string::npos)
-      {
-        uniformInfo.name         = std::string(name).substr(0, iter);
-        uniformInfo.elementCount = elementCount;
-      }
-    }
-    uniformInfo.uniformClass = IsSampler(type) ? Dali::Graphics::UniformClass::COMBINED_IMAGE_SAMPLER : Dali::Graphics::UniformClass::UNIFORM;
-    uniformInfo.location     = location; // GL doesn't guarantee that consecutive array elements have sequential locations. But, we only store location of first element.
-    uniformInfo.binding      = 0;
-    uniformInfo.bufferIndex  = 0;
-    uniformInfo.offset       = 0;
+  // Extract only uniform blocks and collect data
+  std::string uniformName;
 
-    if(IsSampler(type))
-    {
-      mUniformOpaques.push_back(uniformInfo);
-    }
-    else
-    {
-      mDefaultUniformBlock.members.push_back(uniformInfo);
-      mStandaloneUniformExtraInfos.emplace_back(location, GetGLDataTypeSize(type), uniformInfo.offset, elementCount, type);
-    }
-  }
+  // collect samplers into separate array
+  std::vector<UniformInfo> samplers;
 
-  // Re-order according to uniform locations.
+  name = new char[maxUniformNameLength + 1];
 
-  if(mDefaultUniformBlock.members.size() > 1)
+  for(auto i = 0u; i < activeUniformBlockIndex.size(); ++i)
   {
-    std::sort(mDefaultUniformBlock.members.begin(), mDefaultUniformBlock.members.end(), SortUniformInfoByLocation);
-    std::sort(mStandaloneUniformExtraInfos.begin(), mStandaloneUniformExtraInfos.end(), SortUniformExtraInfoByLocation);
-  }
+    GLenum type;
+    GLint  elementCount;
+    GLint  written;
+    gl->GetActiveUniform(glProgram, i, maxUniformNameLength, &written, &elementCount, &type, name);
 
-  if(mUniformOpaques.size() > 1)
-  {
-    SortOpaques();
-  }
+    auto location = gl->GetUniformLocation(glProgram, name);
+    uniformName   = name;
 
-  // Calculate the uniform offset
-  for(unsigned int i = 0; i < mDefaultUniformBlock.members.size(); ++i)
-  {
-    if(i == 0)
+    UniformInfo* uniformInfo{nullptr};
+    if(IsSampler(activeUniformType[i]))
     {
-      mDefaultUniformBlock.members[i].offset = 0;
+      samplers.emplace_back();
+      uniformInfo               = &samplers.back();
+      uniformInfo->uniformClass = UniformClass::COMBINED_IMAGE_SAMPLER;
     }
     else
     {
-      uint32_t previousUniformLocation = mDefaultUniformBlock.members[i - 1].location;
-      auto     previousUniform         = std::find_if(mStandaloneUniformExtraInfos.begin(), mStandaloneUniformExtraInfos.end(), [&previousUniformLocation](const UniformExtraInfo& iter) { return iter.location == previousUniformLocation; });
-      if(previousUniform != mStandaloneUniformExtraInfos.end())
+      auto  blockIndex = activeUniformBlockIndex[i] + 1;
+      auto& members    = mUniformBlocks[blockIndex].members;
+      members.emplace_back();
+      uniformInfo               = &members.back();
+      uniformInfo->uniformClass = UniformClass::UNIFORM;
+      uniformInfo->binding      = 0;
+      uniformInfo->bufferIndex  = blockIndex;
+      uniformInfo->binding      = blockIndex == 0 ? i : 0; // this will be reset later
+      uniformInfo->offset       = activeUniformOffset[i];
+    }
+
+    uniformInfo->location = location; // location must be set later and sorted by offset
+    uniformInfo->name     = name;
+    // Strip off array index from name, use element count instead
+    if(elementCount > 1)
+    {
+      auto iter = std::string(uniformName).find('[', 0);
+      if(iter != std::string::npos)
       {
-        mDefaultUniformBlock.members[i].offset = mDefaultUniformBlock.members[i - 1].offset + (previousUniform->size * previousUniform->arraySize);
-        mStandaloneUniformExtraInfos[i].offset = mDefaultUniformBlock.members[i].offset;
+        uniformInfo->name         = std::string(name).substr(0, iter);
+        uniformInfo->elementCount = elementCount;
       }
     }
   }
 
-  if(mDefaultUniformBlock.members.size() > 0)
+  // Sort by offset
+  uint32_t blockIndex = 0;
+  for(auto& ubo : mUniformBlocks)
   {
-    uint32_t lastUniformLocation = mDefaultUniformBlock.members.back().location;
-    auto     lastUniform         = std::find_if(mStandaloneUniformExtraInfos.begin(), mStandaloneUniformExtraInfos.end(), [&lastUniformLocation](const UniformExtraInfo& iter) { return iter.location == lastUniformLocation; });
-    if(lastUniform != mStandaloneUniformExtraInfos.end())
+    std::sort(ubo.members.begin(), ubo.members.end(), [](auto& lhs, auto& rhs) {
+      return lhs.offset < rhs.offset;
+    });
+
+    if(blockIndex > 0)
     {
-      mDefaultUniformBlock.size = mDefaultUniformBlock.members.back().offset + (lastUniform->size * lastUniform->arraySize);
-      mUniformBlocks.push_back(mDefaultUniformBlock);
+      GLint uboSize;
+      GLint blockNameLength;
+      gl->GetActiveUniformBlockiv(glProgram, blockIndex - 1, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize);
+      gl->GetActiveUniformBlockiv(glProgram, blockIndex - 1, GL_UNIFORM_BLOCK_NAME_LENGTH, &blockNameLength);
+      char* blockName = new char[blockNameLength];
+      gl->GetActiveUniformBlockName(glProgram, blockIndex - 1, blockNameLength, nullptr, blockName);
+      ubo.name = blockName;
+      ubo.size = uboSize;
+      delete[] blockName;
     }
-  }
-  else
-  {
-    mDefaultUniformBlock.size = 0;
+    else
+    {
+      ubo.name = "";
+      ubo.size = 0; // to compute later
+    }
+    ubo.binding       = 0;
+    ubo.descriptorSet = 0;
+    blockIndex++;
   }
 
-  delete[] name;
-}
-
-// TODO: Maybe this is not needed if uniform block is not support by dali shaders?
-void Reflection::BuildUniformBlockReflection()
-{
-  auto gl               = mController.GetGL();
-  auto glProgram        = mProgram.GetGlProgram();
-  int  numUniformBlocks = 0;
+  // count uniform size
+  auto& defaultUniformBlock = mUniformBlocks[0]; // Standalone block
+  defaultUniformBlock.size  = 0;
 
-  if(!gl)
+  mStandaloneUniformExtraInfos.reserve(defaultUniformBlock.members.size());
+  for(auto& member : defaultUniformBlock.members)
   {
-    // Do nothing during shutdown
-    return;
-  }
+    auto& type         = activeUniformType[member.binding];
+    auto  dataTypeSize = GetGLDataTypeSize(type);
+    member.offset      = defaultUniformBlock.size;
+    defaultUniformBlock.size += (dataTypeSize * activeUniformSize[member.binding]);
 
-  DALI_LOG_INFO(gGraphicsReflectionLogFilter, Debug::General, "Build uniform block reflection for glProgram : %u\n", glProgram);
-
-  gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
-
-  mUniformBlocks.clear();
-  mUniformBlocks.resize(numUniformBlocks);
-
-  int uniformBlockMaxLength = 0;
-  gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &uniformBlockMaxLength);
-
-  char* uniformBlockName = new char[uniformBlockMaxLength];
-  for(int i = 0; i < numUniformBlocks; i++)
-  {
-    int length;
-    int blockBinding;
-    int blockDataSize;
-    gl->GetActiveUniformBlockName(glProgram, i, uniformBlockMaxLength, &length, uniformBlockName);
-    gl->GetActiveUniformBlockiv(glProgram, i, GL_UNIFORM_BLOCK_BINDING, &blockBinding);
-    gl->GetActiveUniformBlockiv(glProgram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &blockDataSize);
-
-    Dali::Graphics::UniformBlockInfo uniformBlockInfo;
-    uniformBlockInfo.name    = uniformBlockName;
-    uniformBlockInfo.size    = blockDataSize;
-    uniformBlockInfo.binding = blockBinding;
-
-    int nUnis;
-    gl->GetActiveUniformBlockiv(glProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &nUnis);
-    int* unifIndexes = new GLint[nUnis];
-    gl->GetActiveUniformBlockiv(glProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, unifIndexes);
-    char* uniformName{};
-    int   maxUniLen;
-    gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniLen);
-
-    for(int unif = 0; unif < nUnis; ++unif)
-    {
-      int    uniIndex = unifIndexes[unif];
-      int    size;
-      GLenum type;
-
-      gl->GetActiveUniform(glProgram, uniIndex, maxUniLen, &length, &size, &type, uniformName);
-      int location = gl->GetUniformLocation(glProgram, uniformName);
-
-      Dali::Graphics::UniformInfo uniform;
-      uniform.name     = uniformName;
-      uniform.location = location;
-      uniformBlockInfo.members.push_back(uniform);
-    }
-
-    delete[] unifIndexes;
-
-    mUniformBlocks.push_back(uniformBlockInfo);
+    UniformExtraInfo extraInfo{};
+    extraInfo.location  = member.location;
+    extraInfo.size      = (dataTypeSize);
+    extraInfo.offset    = member.offset;
+    extraInfo.arraySize = activeUniformSize[member.binding];
+    extraInfo.type      = activeUniformType[member.binding];
+    member.binding      = 0;
+    mStandaloneUniformExtraInfos.emplace_back(extraInfo);
   }
-  delete[] uniformBlockName;
+
+  mUniformOpaques = samplers;
+  SortOpaques();
 }
 
 uint32_t Reflection::GetVertexAttributeLocation(const std::string& name) const
index d1bca95..6f6e961 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_GRAPHICS_GLES_REFLECTION_H
 
 /*
- * Copyright (c) 2022 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.
@@ -203,6 +203,7 @@ public:
    */
   struct UniformExtraInfo
   {
+    UniformExtraInfo() = default;
     UniformExtraInfo(uint32_t location, uint32_t size, uint32_t offset, uint32_t arraySize, GLenum type)
     : location(location),
       size(size),
@@ -260,9 +261,8 @@ private:
   };
 
   std::vector<AttributeInfo>              mVertexInputAttributes;       ///< List of vertex attributes
-  Graphics::UniformBlockInfo              mDefaultUniformBlock{};       ///< The emulated UBO containing all the standalone uniforms
   std::vector<Graphics::UniformInfo>      mUniformOpaques{};            ///< List of opaque uniforms (i.e. samplers)
-  std::vector<Graphics::UniformBlockInfo> mUniformBlocks{};             ///< List of uniform blocks
+  std::vector<Graphics::UniformBlockInfo> mUniformBlocks{};             ///< List of uniform blocks (First is for standalone uniforms)
   std::vector<UniformExtraInfo>           mStandaloneUniformExtraInfos; ///< List of extra information for standalone uniforms
 };
 
index 6541de3..6001274 100644 (file)
@@ -1145,10 +1145,12 @@ struct IndexBufferBindingDescriptor
  */
 struct UniformBufferBindingDescriptor
 {
-  const GLES::Buffer* buffer{nullptr};
-  uint32_t            binding{0u};
-  uint32_t            offset{0u};
-  bool                emulated{false}; ///<true if UBO is emulated for old gfx API
+  const GLES::Buffer* buffer;
+  uint32_t            binding;
+  uint32_t            offset;
+  uint32_t            dataSize;
+  uint32_t            blockIndex;
+  bool                emulated; ///<true if UBO is emulated for old gfx API
 };
 
 /**
index 102d5e1..9dd9f51 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.
@@ -62,10 +62,9 @@ void* Memory3::LockRegion(uint32_t offset, uint32_t size)
     }
     else
     {
-      // @TODO: trashing vertex binding, better find target that is rarely used
-      buffer->Bind(Graphics::BufferUsage::VERTEX_BUFFER);
+      gl->BindBuffer(GL_COPY_WRITE_BUFFER, buffer->GetGLBuffer());
       void* ptr      = nullptr;
-      ptr            = gl->MapBufferRange(GL_ARRAY_BUFFER, GLintptr(mMapBufferInfo.offset), GLsizeiptr(mMapBufferInfo.size), GL_MAP_WRITE_BIT);
+      ptr            = gl->MapBufferRange(GL_COPY_WRITE_BUFFER, GLintptr(mMapBufferInfo.offset), GLsizeiptr(mMapBufferInfo.size), GL_MAP_WRITE_BIT);
       mMappedPointer = ptr;
     }
     return mMappedPointer;
@@ -83,8 +82,8 @@ void Memory3::Unlock(bool flush)
     auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
     if(!buffer->IsCPUAllocated())
     {
-      buffer->Bind(Graphics::BufferUsage::VERTEX_BUFFER);
-      gl->UnmapBuffer(GL_ARRAY_BUFFER);
+      gl->BindBuffer(GL_COPY_WRITE_BUFFER, buffer->GetGLBuffer());
+      gl->UnmapBuffer(GL_COPY_WRITE_BUFFER);
     }
   }