Shader Reflection 11/253511/14
authorRichard Huang <r.huang@samsung.com>
Fri, 12 Feb 2021 14:29:08 +0000 (14:29 +0000)
committerRichard Huang <r.huang@samsung.com>
Tue, 23 Feb 2021 16:04:31 +0000 (16:04 +0000)
Change-Id: I5f528748c5de1009a6911343d6a6a243be28b46b

17 files changed:
automated-tests/src/dali-adaptor-internal/CMakeLists.txt
automated-tests/src/dali-adaptor/CMakeLists.txt
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-reflection.cpp [new file with mode: 0644]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.h [new file with mode: 0644]
automated-tests/src/dali-graphics/CMakeLists.txt
automated-tests/src/dali-platform-abstraction/CMakeLists.txt
dali/internal/graphics/gles-impl/egl-graphics-controller.cpp
dali/internal/graphics/gles-impl/egl-graphics-controller.h
dali/internal/graphics/gles-impl/file.list
dali/internal/graphics/gles-impl/gles-graphics-pipeline.cpp
dali/internal/graphics/gles-impl/gles-graphics-pipeline.h
dali/internal/graphics/gles-impl/gles-graphics-reflection.cpp [new file with mode: 0644]
dali/internal/graphics/gles-impl/gles-graphics-reflection.h [new file with mode: 0644]
dali/internal/graphics/gles-impl/gles-graphics-shader.cpp
dali/internal/graphics/gles-impl/gles-graphics-shader.h

index 2db9651..51f3cf7 100644 (file)
@@ -34,6 +34,7 @@ LIST(APPEND TC_SOURCES
     ../dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
+    ../dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-sampler.cpp
     ../dali-adaptor/dali-test-suite-utils/test-native-image.cpp
     ../dali-adaptor/dali-test-suite-utils/test-platform-abstraction.cpp
index 9fc9c20..b29d3ff 100644 (file)
@@ -32,6 +32,7 @@ LIST(APPEND TC_SOURCES
     dali-test-suite-utils/test-graphics-command-buffer.cpp
     dali-test-suite-utils/test-graphics-controller.cpp
     dali-test-suite-utils/test-graphics-pipeline.cpp
+    dali-test-suite-utils/test-graphics-reflection.cpp
     dali-test-suite-utils/test-graphics-texture.cpp
     dali-test-suite-utils/test-graphics-sampler.cpp
     dali-test-suite-utils/test-native-image.cpp
index a8357c1..41d13c9 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "test-graphics-buffer.h"
 #include "test-graphics-command-buffer.h"
+#include "test-graphics-reflection.h"
 #include "test-graphics-sampler.h"
 #include "test-graphics-texture.h"
 
@@ -766,6 +767,14 @@ const Graphics::TextureProperties& TestGraphicsController::GetTextureProperties(
   return textureProperties;
 }
 
+const Graphics::Reflection& TestGraphicsController::GetPipelineReflection(const Graphics::Pipeline& pipeline)
+{
+  static TestGraphicsReflection reflection(mGl);
+  mCallStack.PushCall("Controller::GetPipelineReflection", "");
+
+  return reflection;
+}
+
 bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
 {
   mCallStack.PushCall("Controller::PipelineEquals", "");
index e39c1a5..bf2ba21 100644 (file)
@@ -21,6 +21,7 @@
 #include "test-gl-abstraction.h"
 #include "test-gl-context-helper-abstraction.h"
 #include "test-gl-sync-abstraction.h"
+#include "test-graphics-reflection.h"
 
 namespace Dali
 {
@@ -267,6 +268,14 @@ public:
   const Graphics::TextureProperties& GetTextureProperties(const Graphics::Texture& texture) override;
 
   /**
+   * @brief Returns the reflection of the given pipeline
+   *
+   * @param[in] pipeline The pipeline
+   * @return The reflection of the pipeline
+   */
+  const Graphics::Reflection& GetPipelineReflection(const Graphics::Pipeline& pipeline) override;
+
+  /**
    * @brief Tests whether two Pipelines are the same.
    *
    * On the higher level, this function may help wit creating pipeline cache.
diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp
new file mode 100644 (file)
index 0000000..9bce79a
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test-graphics-reflection.h"
+
+namespace Dali
+{
+TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl)
+: mGl(gl)
+{
+}
+
+uint32_t TestGraphicsReflection::GetVertexAttributeLocation(const std::string& name) const
+{
+  return 0u;
+}
+
+Dali::Graphics::VertexInputAttributeFormat TestGraphicsReflection::GetVertexAttributeFormat(uint32_t location) const
+{
+  return Dali::Graphics::VertexInputAttributeFormat{};
+}
+
+std::string TestGraphicsReflection::GetVertexAttributeName(uint32_t location) const
+{
+  return 0u;
+}
+
+std::vector<uint32_t> TestGraphicsReflection::GetVertexAttributeLocations() const
+{
+  return std::vector<uint32_t>{};
+}
+
+uint32_t TestGraphicsReflection::GetUniformBlockCount() const
+{
+  return 0u;
+}
+
+uint32_t TestGraphicsReflection::GetUniformBlockBinding(uint32_t index) const
+{
+  return 0u;
+}
+
+uint32_t TestGraphicsReflection::GetUniformBlockSize(uint32_t index) const
+{
+  return 0u;
+}
+
+bool TestGraphicsReflection::GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const
+{
+  return true;
+}
+
+std::vector<uint32_t> TestGraphicsReflection::GetUniformBlockLocations() const
+{
+  return std::vector<uint32_t>{};
+}
+
+std::string TestGraphicsReflection::GetUniformBlockName(uint32_t blockIndex) const
+{
+  return std::string{};
+}
+
+uint32_t TestGraphicsReflection::GetUniformBlockMemberCount(uint32_t blockIndex) const
+{
+  return 0u;
+}
+
+std::string TestGraphicsReflection::GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const
+{
+  return std::string{};
+}
+
+uint32_t TestGraphicsReflection::GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const
+{
+  return 0u;
+}
+
+bool TestGraphicsReflection::GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const
+{
+  return true;
+}
+
+std::vector<Dali::Graphics::UniformInfo> TestGraphicsReflection::GetSamplers() const
+{
+  return std::vector<Dali::Graphics::UniformInfo>{};
+}
+
+Graphics::ShaderLanguage TestGraphicsReflection::GetLanguage() const
+{
+  return Graphics::ShaderLanguage::GLSL_3_1;
+}
+
+} // namespace Dali
diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.h
new file mode 100644 (file)
index 0000000..1c9f62b
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef DALI_TEST_GRAPHICS_REFLECTION_H
+#define DALI_TEST_GRAPHICS_REFLECTION_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/graphics-api/graphics-reflection.h>
+#include "test-gl-abstraction.h"
+
+namespace Dali
+{
+class TestGraphicsReflection : public Graphics::Reflection
+{
+public:
+  TestGraphicsReflection(TestGlAbstraction& gl);
+
+  uint32_t                                   GetVertexAttributeLocation(const std::string& name) const override;
+  Dali::Graphics::VertexInputAttributeFormat GetVertexAttributeFormat(uint32_t location) const override;
+  std::string                                GetVertexAttributeName(uint32_t location) const override;
+  std::vector<uint32_t>                      GetVertexAttributeLocations() const override;
+  uint32_t                                   GetUniformBlockCount() const override;
+  uint32_t                                   GetUniformBlockBinding(uint32_t index) const override;
+  uint32_t                                   GetUniformBlockSize(uint32_t index) const override;
+  bool                                       GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const override;
+  std::vector<uint32_t>                      GetUniformBlockLocations() const override;
+  std::string                                GetUniformBlockName(uint32_t blockIndex) const override;
+  uint32_t                                   GetUniformBlockMemberCount(uint32_t blockIndex) const override;
+  std::string                                GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const override;
+  uint32_t                                   GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const override;
+  bool                                       GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const override;
+  std::vector<Dali::Graphics::UniformInfo>   GetSamplers() const override;
+  Graphics::ShaderLanguage                   GetLanguage() const override;
+
+  TestGlAbstraction& mGl;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_REFLECTION_H
index 1d54fdd..e1c48a8 100644 (file)
@@ -20,6 +20,7 @@ LIST(APPEND TC_SOURCES
   ../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-sampler.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
+  ../dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp
   ../dali-adaptor/dali-test-suite-utils/test-native-image.cpp
   ../dali-adaptor/dali-test-suite-utils/test-platform-abstraction.cpp
   ../dali-adaptor/dali-test-suite-utils/test-render-controller.cpp
index b0d64b2..3fdc341 100644 (file)
@@ -23,6 +23,7 @@ LIST(APPEND TC_SOURCES
     ../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-sampler.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
+    ../dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp
     ../dali-adaptor/dali-test-suite-utils/test-native-image.cpp
     ../dali-adaptor/dali-test-suite-utils/test-platform-abstraction.cpp
     ../dali-adaptor/dali-test-suite-utils/test-render-controller.cpp
index 32cc491..ef507a7 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/integration-api/gl-defines.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
 #include <dali/public-api/common/dali-common.h>
@@ -151,6 +152,11 @@ EglGraphicsController::CreateBuffer(const BufferCreateInfo& bufferCreateInfo, Gr
   return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
 }
 
+Graphics::UniquePtr<Shader> EglGraphicsController::CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader)
+{
+  return NewObject<GLES::Shader>(shaderCreateInfo, *this, std::move(oldShader));
+}
+
 Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
 {
   // Create pipeline cache if needed
index 790b252..c7d85c0 100644 (file)
@@ -25,7 +25,9 @@
 #include "gles-context.h"
 #include "gles-graphics-buffer.h"
 #include "gles-graphics-memory.h"
+#include "gles-graphics-pipeline.h"
 #include "gles-graphics-pipeline-cache.h"
+#include "gles-graphics-reflection.h"
 #include "gles-graphics-texture.h"
 
 namespace Dali
@@ -196,10 +198,7 @@ public:
   /**
    * @copydoc Dali::Graphics::CreateShader()
    */
-  Graphics::UniquePtr<Shader> CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader) override
-  {
-    return nullptr;
-  }
+  Graphics::UniquePtr<Shader> CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader) override;
 
   /**
    * @copydoc Dali::Graphics::CreateSampler()
@@ -263,6 +262,15 @@ public:
   }
 
   /**
+   * @copydoc Dali::Graphics::Controller::GetPipelineReflection()
+   */
+  const Reflection& GetPipelineReflection(const Pipeline& pipeline) override
+  {
+    static GLES::Reflection dummy(*this);
+    return dummy;
+  }
+
+  /**
    * @copydoc Dali::Graphics::PipelineEquals()
    */
   [[nodiscard]] bool PipelineEquals(const Pipeline& pipeline0, const Pipeline& pipeline1) const override
index 6c30917..e251745 100644 (file)
@@ -8,6 +8,7 @@ SET( adaptor_graphics_gles_src_files ${adaptor_graphics_gles_src_files}
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-framebuffer.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-memory.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-pipeline.cpp
+    ${adaptor_graphics_dir}/gles-impl/gles-graphics-reflection.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-render-pass.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-render-target.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-sampler.cpp
index b747a19..dbebefb 100644 (file)
 #include "egl-graphics-controller.h"
 #include "gles-graphics-shader.h"
 
+namespace
+{
+struct LegacyProgram : Dali::Graphics::ExtensionCreateInfo
+{
+  uint32_t programId;
+};
+} // namespace
+
 namespace Dali::Graphics::GLES
 {
 /**
@@ -47,7 +55,8 @@ struct PipelineImpl::PipelineState
 };
 
 PipelineImpl::PipelineImpl(const Graphics::PipelineCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
-: mController(controller)
+: mController(controller),
+  mReflection(controller)
 {
   // the creation is deferred so it's needed to copy certain parts of the CreateInfo structure
   mPipelineState = std::make_unique<PipelineImpl::PipelineState>();
@@ -62,6 +71,26 @@ PipelineImpl::PipelineImpl(const Graphics::PipelineCreateInfo& createInfo, Graph
   CopyStateIfSet(createInfo.depthStencilState, mPipelineState->depthStencilState, &mCreateInfo.depthStencilState);
   CopyStateIfSet(createInfo.shaderState, mPipelineState->shaderState, &mCreateInfo.shaderState);
   CopyStateIfSet(createInfo.viewportState, mPipelineState->viewportState, &mCreateInfo.viewportState);
+
+  if(createInfo.nextExtension)
+  {
+    LegacyProgram* legacyProgram = static_cast<LegacyProgram*>(createInfo.nextExtension);
+    mGlProgram                   = legacyProgram->programId;
+    mReflection.SetGlProgram(mGlProgram);
+    printf("GLES::Pipeline: mProgramId: %u\n", mGlProgram);
+  }
+
+  const std::vector<Graphics::ShaderState>* shaderStates = mCreateInfo.shaderState;
+  if(shaderStates)
+  {
+    printf("GLES::Pipeline: shaderStates %p, shaderStates size: %lu\n", shaderStates, shaderStates->size());
+
+    std::for_each(shaderStates->begin(), shaderStates->end(), [](Graphics::ShaderState shaderState) {
+      const Graphics::Shader* shader        = shaderState.shader;
+      Graphics::PipelineStage pipelineStage = shaderState.pipelineStage;
+      printf("GLES::Pipeline: shader: %p, pipelineStage: %d\n", shader, static_cast<int>(pipelineStage));
+    });
+  }
 }
 
 const PipelineCreateInfo& PipelineImpl::GetCreateInfo() const
@@ -76,8 +105,8 @@ auto& PipelineImpl::GetController() const
 
 bool PipelineImpl::InitializeResource()
 {
-  auto& gl   = *GetController().GetGL();
-  mGlProgram = gl.CreateProgram();
+  auto& gl = *GetController().GetGL();
+  //  mGlProgram = gl.CreateProgram();
 
   for(auto& shader : mPipelineState->shaderState)
   {
@@ -191,4 +220,4 @@ EglGraphicsController& Pipeline::GetController() const
   return mPipeline.GetController();
 }
 
-} // namespace Dali::Graphics::GLES
\ No newline at end of file
+} // namespace Dali::Graphics::GLES
index 64dad5a..e8b734f 100644 (file)
@@ -24,6 +24,7 @@
 #include <string.h>
 
 // INTERNAL INCLUDES
+#include "gles-graphics-reflection.h"
 #include "gles-graphics-resource.h"
 
 namespace Dali::Graphics::GLES
@@ -114,6 +115,8 @@ public:
 
   [[nodiscard]] auto& GetController() const;
 
+  Graphics::GLES::Reflection& GetReflection();
+
 private:
   /**
    * @brief Helper function. Copies state if pointer is set
@@ -151,6 +154,8 @@ private:
   EglGraphicsController& mController;
   PipelineCreateInfo     mCreateInfo;
 
+  Graphics::GLES::Reflection mReflection;
+
   uint32_t mGlProgram{0u};
 
   uint32_t mRefCount{0u};
diff --git a/dali/internal/graphics/gles-impl/gles-graphics-reflection.cpp b/dali/internal/graphics/gles-impl/gles-graphics-reflection.cpp
new file mode 100644 (file)
index 0000000..4450557
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "gles-graphics-reflection.h"
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+
+#include <vector>
+#include "egl-graphics-controller.h"
+
+#include <GLES3/gl3.h>
+#include <GLES3/gl31.h>
+
+#include <iostream>
+
+namespace
+{
+Dali::Graphics::VertexInputAttributeFormat GetVertexAttributeTypeFormat(GLenum type)
+{
+  switch(type)
+  {
+    case GL_FLOAT:
+      return Dali::Graphics::VertexInputAttributeFormat::FLOAT;
+    case GL_FLOAT_VEC2:
+      return Dali::Graphics::VertexInputAttributeFormat::VEC2;
+    case GL_FLOAT_VEC3:
+      return Dali::Graphics::VertexInputAttributeFormat::VEC3;
+    case GL_FLOAT_VEC4:
+      return Dali::Graphics::VertexInputAttributeFormat::VEC4;
+    case GL_INT:
+      return Dali::Graphics::VertexInputAttributeFormat::INTEGER;
+    default:
+      return Dali::Graphics::VertexInputAttributeFormat::UNDEFINED;
+  }
+}
+
+int 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;
+  }
+}
+
+bool IsSampler(GLenum type)
+{
+  return type == GL_SAMPLER_2D || type == GL_SAMPLER_3D;
+}
+
+bool SortByLocation(Dali::Graphics::UniformInfo a, Dali::Graphics::UniformInfo b)
+{
+  return a.location < b.location;
+}
+
+} // namespace
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace GLES
+{
+Reflection::Reflection(Graphics::EglGraphicsController& controller)
+: Graphics::Reflection(),
+  mController(controller),
+  mGlProgram(0u)
+{
+}
+
+Reflection::~Reflection()
+{
+}
+
+void Reflection::BuildVertexAttributeReflection()
+{
+  int    written, size, location, maxLength, nAttribs;
+  GLenum type;
+  char*  name;
+
+  auto gl = mController.GetGL();
+
+  gl->GetProgramiv(mGlProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
+  gl->GetProgramiv(mGlProgram, GL_ACTIVE_ATTRIBUTES, &nAttribs);
+
+  mVertexInputAttributes.clear();
+  mVertexInputAttributes.resize(nAttribs);
+
+  name = new GLchar[maxLength];
+  for(int i = 0; i < nAttribs; i++)
+  {
+    gl->GetActiveAttrib(mGlProgram, i, maxLength, &written, &size, &type, name);
+    location = gl->GetAttribLocation(mGlProgram, name);
+
+    AttributeInfo attributeInfo;
+    attributeInfo.location = location;
+    attributeInfo.name     = name;
+    attributeInfo.format   = GetVertexAttributeTypeFormat(type);
+
+    mVertexInputAttributes.insert(mVertexInputAttributes.begin() + location, attributeInfo);
+  }
+  delete[] name;
+}
+
+void Reflection::BuildUniformReflection()
+{
+  int   maxLen;
+  char* name;
+
+  int numUniforms = 0;
+
+  auto gl = mController.GetGL();
+
+  gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
+  gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
+
+  mUniformBlocks.clear();
+  mDefaultUniformBlock.members.clear();
+  mUniformOpaques.clear();
+
+  name = new char[maxLen];
+
+  int maxUniformLocations;
+  gl->GetProgramiv(mGlProgram, GL_MAX_UNIFORM_LOCATIONS, &maxUniformLocations);
+
+  std::vector<int> uniformSize;
+  uniformSize.reserve(maxUniformLocations);
+
+  for(int i = 0; i < numUniforms; ++i)
+  {
+    int    size;
+    GLenum type;
+    int    written;
+    gl->GetActiveUniform(mGlProgram, i, maxLen, &written, &size, &type, name);
+    int location          = gl->GetUniformLocation(mGlProgram, name);
+    uniformSize[location] = GetGLDataTypeSize(type);
+
+    Dali::Graphics::UniformInfo uniformInfo;
+    uniformInfo.name         = name;
+    uniformInfo.uniformClass = IsSampler(type) ? Dali::Graphics::UniformClass::COMBINED_IMAGE_SAMPLER : Dali::Graphics::UniformClass::UNIFORM;
+    uniformInfo.location     = IsSampler(type) ? 0 : location;
+    uniformInfo.binding      = IsSampler(type) ? location : 0;
+    uniformInfo.bufferIndex  = 0;
+
+    if(IsSampler(type))
+    {
+      mUniformOpaques.push_back(uniformInfo);
+    }
+    else
+    {
+      mDefaultUniformBlock.members.push_back(uniformInfo);
+    }
+  }
+
+  // Re-order according to uniform locations.
+  if(mDefaultUniformBlock.members.size() > 1)
+  {
+    std::sort(mDefaultUniformBlock.members.begin(), mDefaultUniformBlock.members.end(), SortByLocation);
+  }
+
+  if(mUniformOpaques.size() > 1)
+  {
+    std::sort(mUniformOpaques.begin(), mUniformOpaques.end(), SortByLocation);
+  }
+
+  // Calculate the uniform offset
+  for(unsigned int i = 0; i < mDefaultUniformBlock.members.size(); ++i)
+  {
+    mDefaultUniformBlock.members[i].offset = i == 0 ? 0 : mDefaultUniformBlock.members[i - 1].offset + uniformSize[mDefaultUniformBlock.members[i - 1].location];
+  }
+
+  mDefaultUniformBlock.size = mDefaultUniformBlock.members.back().offset + uniformSize[mDefaultUniformBlock.members.back().location];
+
+  mUniformBlocks.push_back(mDefaultUniformBlock);
+
+  delete[] name;
+}
+
+// TODO: Maybe this is not needed if uniform block is not support by dali shaders?
+void Reflection::BuildUniformBlockReflection()
+{
+  auto gl = mController.GetGL();
+
+  int numUniformBlocks = 0;
+  gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
+
+  mUniformBlocks.clear();
+  mUniformBlocks.resize(numUniformBlocks);
+
+  int uniformBlockMaxLength = 0;
+  gl->GetProgramiv(mGlProgram, 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(mGlProgram, i, uniformBlockMaxLength, &length, uniformBlockName);
+    gl->GetActiveUniformBlockiv(mGlProgram, i, GL_UNIFORM_BLOCK_BINDING, &blockBinding);
+    gl->GetActiveUniformBlockiv(mGlProgram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &blockDataSize);
+
+    Dali::Graphics::UniformBlockInfo uniformBlockInfo;
+    uniformBlockInfo.name    = uniformBlockName;
+    uniformBlockInfo.size    = blockDataSize;
+    uniformBlockInfo.binding = blockBinding;
+
+    int nUnis;
+    gl->GetActiveUniformBlockiv(mGlProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &nUnis);
+    int* unifIndexes = new GLint[nUnis];
+    gl->GetActiveUniformBlockiv(mGlProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, unifIndexes);
+    char* uniformName{};
+    int   maxUniLen;
+    gl->GetProgramiv(mGlProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniLen);
+
+    for(int unif = 0; unif < nUnis; ++unif)
+    {
+      int    uniIndex = unifIndexes[unif];
+      int    size;
+      GLenum type;
+
+      gl->GetActiveUniform(mGlProgram, uniIndex, maxUniLen, &length, &size, &type, uniformName);
+      int location = gl->GetUniformLocation(mGlProgram, uniformName);
+
+      Dali::Graphics::UniformInfo uniform;
+      uniform.name     = uniformName;
+      uniform.location = location;
+      uniformBlockInfo.members.push_back(uniform);
+    }
+
+    delete[] unifIndexes;
+
+    mUniformBlocks.push_back(uniformBlockInfo);
+  }
+  delete[] uniformBlockName;
+}
+
+uint32_t Reflection::GetVertexAttributeLocation(const std::string& name) const
+{
+  for(auto&& attr : mVertexInputAttributes)
+  {
+    if(attr.name == name)
+    {
+      return attr.location;
+    }
+  }
+  return ERROR_ATTRIBUTE_NOT_FOUND;
+}
+
+Dali::Graphics::VertexInputAttributeFormat Reflection::GetVertexAttributeFormat(uint32_t location) const
+{
+  if(location >= mVertexInputAttributes.size())
+  {
+    return Dali::Graphics::VertexInputAttributeFormat::UNDEFINED;
+  }
+
+  return mVertexInputAttributes[location].format;
+}
+
+std::string Reflection::GetVertexAttributeName(uint32_t location) const
+{
+  if(location >= mVertexInputAttributes.size())
+  {
+    return std::string();
+  }
+
+  return mVertexInputAttributes[location].name;
+}
+
+std::vector<uint32_t> Reflection::GetVertexAttributeLocations() const
+{
+  std::vector<uint32_t> locations;
+  for(auto&& attr : mVertexInputAttributes)
+  {
+    if(attr.format != Dali::Graphics::VertexInputAttributeFormat::UNDEFINED)
+    {
+      locations.push_back(attr.location);
+    }
+  }
+
+  return locations;
+}
+
+uint32_t Reflection::GetUniformBlockCount() const
+{
+  return mUniformBlocks.size();
+}
+
+uint32_t Reflection::GetUniformBlockBinding(uint32_t index) const
+{
+  return index < mUniformBlocks.size() ? mUniformBlocks[index].binding : 0u;
+}
+
+uint32_t Reflection::GetUniformBlockSize(uint32_t index) const
+{
+  return index < mUniformBlocks.size() ? mUniformBlocks[index].size : 0u;
+}
+
+bool Reflection::GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const
+{
+  if(index >= mUniformBlocks.size())
+  {
+    return false;
+  }
+
+  const auto& block = mUniformBlocks[index];
+
+  out.name          = block.name;
+  out.binding       = block.binding;
+  out.descriptorSet = block.descriptorSet;
+  auto membersSize  = block.members.size();
+  out.members.resize(membersSize);
+  out.size = block.size;
+  for(auto i = 0u; i < out.members.size(); ++i)
+  {
+    const auto& memberUniform   = block.members[i];
+    out.members[i].name         = memberUniform.name;
+    out.members[i].binding      = block.binding;
+    out.members[i].uniformClass = Graphics::UniformClass::UNIFORM;
+    out.members[i].offset       = memberUniform.offset;
+    out.members[i].location     = memberUniform.location;
+  }
+
+  return true;
+}
+
+std::vector<uint32_t> Reflection::GetUniformBlockLocations() const
+{
+  std::vector<uint32_t> retval{};
+  for(auto&& ubo : mUniformBlocks)
+  {
+    retval.emplace_back(ubo.binding);
+  }
+  return retval;
+}
+
+std::string Reflection::GetUniformBlockName(uint32_t blockIndex) const
+{
+  if(blockIndex < mUniformBlocks.size())
+  {
+    return mUniformBlocks[blockIndex].name;
+  }
+  else
+  {
+    return std::string();
+  }
+}
+
+uint32_t Reflection::GetUniformBlockMemberCount(uint32_t blockIndex) const
+{
+  if(blockIndex < mUniformBlocks.size())
+  {
+    return static_cast<uint32_t>(mUniformBlocks[blockIndex].members.size());
+  }
+  else
+  {
+    return 0u;
+  }
+}
+
+std::string Reflection::GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const
+{
+  if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size())
+  {
+    return mUniformBlocks[blockIndex].members[memberLocation].name;
+  }
+  else
+  {
+    return std::string();
+  }
+}
+
+uint32_t Reflection::GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const
+{
+  if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size())
+  {
+    return mUniformBlocks[blockIndex].members[memberLocation].offset;
+  }
+  else
+  {
+    return 0u;
+  }
+}
+
+bool Reflection::GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const
+{
+  auto index = 0u;
+  for(auto&& ubo : mUniformBlocks)
+  {
+    for(auto&& member : ubo.members)
+    {
+      if(name == member.name || name == (ubo.name + "." + member.name))
+      {
+        out.name         = name;
+        out.location     = member.location;
+        out.binding      = ubo.binding;
+        out.bufferIndex  = index;
+        out.offset       = member.offset;
+        out.uniformClass = Graphics::UniformClass::UNIFORM;
+        return true;
+      }
+    }
+    index++;
+  }
+
+  // check samplers
+  for(auto&& uniform : mUniformOpaques)
+  {
+    if(uniform.name == name)
+    {
+      out.uniformClass = Graphics::UniformClass::COMBINED_IMAGE_SAMPLER;
+      out.binding      = uniform.binding;
+      out.name         = name;
+      out.offset       = 0;
+      out.location     = uniform.location;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+std::vector<Dali::Graphics::UniformInfo> Reflection::GetSamplers() const
+{
+  return mUniformOpaques;
+}
+
+Graphics::ShaderLanguage Reflection::GetLanguage() const
+{
+  auto gl = mController.GetGL();
+
+  int majorVersion, minorVersion;
+  gl->GetIntegerv(GL_MAJOR_VERSION, &majorVersion);
+  gl->GetIntegerv(GL_MINOR_VERSION, &minorVersion);
+  printf("GL Version (integer) : %d.%d\n", majorVersion, minorVersion);
+  printf("GLSL Version : %s\n", gl->GetString(GL_SHADING_LANGUAGE_VERSION));
+
+  // TODO: the language version is hardcoded for now, but we may use what we get
+  // from GL_SHADING_LANGUAGE_VERSION?
+  return Graphics::ShaderLanguage::GLSL_3_2;
+}
+
+void Reflection::SetGlProgram(uint32_t glProgram)
+{
+  mGlProgram = glProgram;
+
+  BuildVertexAttributeReflection();
+  BuildUniformReflection();
+}
+
+} // namespace GLES
+} // namespace Graphics
+} // namespace Dali
diff --git a/dali/internal/graphics/gles-impl/gles-graphics-reflection.h b/dali/internal/graphics/gles-impl/gles-graphics-reflection.h
new file mode 100644 (file)
index 0000000..1e07a01
--- /dev/null
@@ -0,0 +1,243 @@
+#ifndef DALI_GRAPHICS_GLES_REFLECTION_H
+#define DALI_GRAPHICS_GLES_REFLECTION_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/graphics-api/graphics-reflection.h>
+#include <dali/graphics-api/graphics-types.h>
+#include <dali/integration-api/gl-abstraction.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+class EglGraphicsController;
+
+namespace GLES
+{
+constexpr uint32_t ERROR_ATTRIBUTE_NOT_FOUND(-1u);
+
+/**
+ * Reflection object represents a single full graphics reflection state.
+ *
+ * The state involves compiled and linked shaders as well as state parameters
+ * like blending, stencil, scissors, viewport etc.
+ *
+ * Some of the parameters can be modified by issuing commands but
+ * the Reflection must mark those states
+ * as dynamic.
+ *
+ */
+class Reflection : public Dali::Graphics::Reflection
+{
+public:
+  Reflection(Graphics::EglGraphicsController& controller);
+  virtual ~Reflection();
+
+  // not copyable
+  Reflection(const Reflection&) = delete;
+  Reflection& operator=(const Reflection&) = delete;
+
+  /**
+   * @brief Gets the location of a vertex attribute.
+   *
+   * @param [in] name The name of vertex attribute
+   * @return The index of the vertex attribute in the shader
+   */
+  uint32_t GetVertexAttributeLocation(const std::string& name) const;
+
+  /**
+   * @brief Gets the format of a vertex attribute.
+   *
+   * @param [in] location The location of vertex attribute
+   * @return The format of a vertex attribute
+   */
+  Dali::Graphics::VertexInputAttributeFormat GetVertexAttributeFormat(uint32_t location) const;
+
+  /**
+   * @brief Gets the name of a vertex attribute.
+   *
+   * @param [in] location The location of vertex attribute
+   * @return The name of the vertex attribute
+   */
+  std::string GetVertexAttributeName(uint32_t location) const;
+
+  /**
+   * @brief Gets the locations of all the vertex attribute in the shader.
+   *
+   * @return A vector of the locations of all the vertex attributes in the shader
+   */
+  std::vector<uint32_t> GetVertexAttributeLocations() const;
+
+  // Uniform blocks
+
+  /**
+   * @brief Gets the number of uniform blocks in the shader
+   *
+   * @return The number of uniform blocks
+   */
+  uint32_t GetUniformBlockCount() const;
+
+  /**
+   * @brief Gets the binding point to which the uniform block with the given index is binded.
+   *
+   * @param [in] index The index of the uniform block
+   * @return The binding point
+   */
+  uint32_t GetUniformBlockBinding(uint32_t index) const;
+
+  /**
+   * @brief Gets the size of the uniform block with the given index.
+   *
+   * @param [in] index The index of the uniform block
+   * @return The size of the uniform block
+   */
+  uint32_t GetUniformBlockSize(uint32_t index) const;
+
+  /**
+   * @brief Retrieves the information of the uniform block with the given index.
+   *
+   * The information includes the name, binding point, size, uniforms inside the uniform block, etc.
+   *
+   * @param [in] index The index of the uniform block
+   * @param [out] out A structure that contains the information of the uniform block
+   * @return Whether the uniform block exists or not
+   */
+  bool GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const;
+
+  /**
+   * @brief Gets the binding points of all the uniform blocks in the shader.
+   *
+   * @return A vector of binding points
+   */
+  std::vector<uint32_t> GetUniformBlockLocations() const;
+
+  /**
+   * @brief Gets the name of uniform block with the given index.
+   *
+   * @param [in] blockIndex The index of the uniform block
+   * @return The name of the uniform block
+   */
+  std::string GetUniformBlockName(uint32_t blockIndex) const;
+
+  /**
+   * @brief Gets the number of uniforms in the uniform block with the given index.
+   *
+   * @param [in] blockIndex The index of the uniform block
+   * @return The number of uniforms in the uniform block
+   */
+  uint32_t GetUniformBlockMemberCount(uint32_t blockIndex) const;
+
+  /**
+   * @brief Gets the name of the uniform in the given location within the uniform block.
+   *
+   * @param [in] blockIndex The index of the uniform block
+   * @param [in] memberLocation The location of the uniform within the uniform block
+   * @return The name of the uniform
+   */
+  std::string GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const;
+
+  /**
+   * @brief Gets the byte offset of the uniform in the given location within the uniform block.
+   *
+   * @param [in] blockIndex The index of the uniform block
+   * @param [in] memberLocation The location of the uniform within the uniform block
+   * @return The byte offset of the uniform
+   */
+  uint32_t GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const;
+
+  // Named uniforms
+
+  /**
+   * @brief Gets the information of the uniform by its name.
+   *
+   * @param [in] name The name of the uniform
+   * @param [out] out The information of the uniform
+   * @return Whether the uniform exists or not
+   */
+  bool GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const;
+
+  // Sampler
+
+  /**
+   * @brief Gets all the sampler uniforms
+   *
+   * @return A vector of the sampler uniforms
+   */
+  std::vector<Dali::Graphics::UniformInfo> GetSamplers() const;
+
+  // Language
+
+  /**
+   * @brief Retrieves the language of the shader
+   *
+   * @return The language of the shader
+   */
+  Graphics::ShaderLanguage GetLanguage() const;
+
+  // Other
+
+  /**
+   * @brief Set the program object whose reflection to be built
+   *
+   * @param [in] glProgram The program object
+   */
+  void SetGlProgram(uint32_t glProgram);
+
+private:
+  /**
+   * @brief Build the reflection of vertex attributes
+   */
+  void BuildVertexAttributeReflection();
+
+  /**
+   * @brief Build the reflection of uniforms
+   */
+  void BuildUniformReflection();
+
+  /**
+   * @brief Build the reflection of uniform blocks
+   */
+  void BuildUniformBlockReflection();
+
+protected:
+  Reflection(Reflection&&) = default;
+  Reflection& operator=(Reflection&&) = default;
+
+private:
+  Graphics::EglGraphicsController& mController; ///< The Graphics controller
+  uint32_t                         mGlProgram;  ///< The GL program object
+
+  struct AttributeInfo
+  {
+    uint32_t                                   location{};
+    std::string                                name{};
+    Dali::Graphics::VertexInputAttributeFormat format{};
+  };
+
+  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
+};
+
+} // namespace GLES
+} // namespace Graphics
+} // namespace Dali
+
+#endif // DALI_GRAPHICS_GLES_REFLECTION_H
index 082766d..1bbfe92 100644 (file)
  *
  */
 
-// CLASS HEADER
 #include "gles-graphics-shader.h"
+#include <dali/integration-api/gl-abstraction.h>
+#include <vector>
+#include "egl-graphics-controller.h"
+
+#include <GLES3/gl3.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace GLES
+{
+Shader::Shader(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: ShaderResource(createInfo, controller)
+{
+  if(mCreateInfo.sourceData && mCreateInfo.sourceSize)
+  {
+    printf("GLES::Shader: stage: %d, sourceMode: %d, size: %u, source:\n\n%s\n", (int)mCreateInfo.pipelineStage, (int)mCreateInfo.sourceMode, mCreateInfo.sourceSize, static_cast<const char*>(mCreateInfo.sourceData));
+  }
+}
+
+} // namespace GLES
+} // namespace Graphics
+} // namespace Dali
index ece9c89..f5802af 100644 (file)
@@ -37,10 +37,7 @@ public:
    * @param[in] createInfo Valid createInfo structure
    * @param[in] controller Reference to the controller
    */
-  Shader(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
-  : ShaderResource(createInfo, controller)
-  {
-  }
+  Shader(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
 
   /**
    * @brief Destructor