Attribute reflection 97/253697/5
authorDavid Steele <david.steele@samsung.com>
Mon, 15 Feb 2021 13:02:14 +0000 (13:02 +0000)
committerDavid Steele <david.steele@samsung.com>
Tue, 23 Feb 2021 15:45:38 +0000 (15:45 +0000)
Added graphics-program.h to allow shader reflection to work
without pipeline.

Updated attribute setting to use basic reflection through
the graphics API.

Change-Id: I02681571bb04c4bdd8b0b75c611287a31be76be5

25 files changed:
automated-tests/src/dali-internal/CMakeLists.txt
automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/dali-test-suite-utils/mesh-builder.cpp
automated-tests/src/dali/dali-test-suite-utils/mesh-builder.h
automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h
automated-tests/src/dali/dali-test-suite-utils/test-graphics-pipeline.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-pipeline.h
automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-graphics-reflection.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-reflection.h
automated-tests/src/dali/dali-test-suite-utils/test-graphics-shader.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-graphics-shader.h [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Renderer.cpp
build/tizen/CMakeLists.txt
dali/graphics-api/file.list
dali/graphics-api/graphics-controller.h
dali/graphics-api/graphics-pipeline-create-info.h
dali/graphics-api/graphics-program-create-info.h [new file with mode: 0644]
dali/graphics-api/graphics-program.h [new file with mode: 0644]
dali/graphics-api/graphics-texture.h
dali/graphics-api/graphics-types.h
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h

index 3d61996..f385bd5 100644 (file)
@@ -36,9 +36,11 @@ LIST(APPEND TC_SOURCES
         ../dali/dali-test-suite-utils/test-graphics-command-buffer.cpp
         ../dali/dali-test-suite-utils/test-graphics-controller.cpp
         ../dali/dali-test-suite-utils/test-graphics-pipeline.cpp
+        ../dali/dali-test-suite-utils/test-graphics-program.cpp
         ../dali/dali-test-suite-utils/test-graphics-reflection.cpp
-        ../dali/dali-test-suite-utils/test-graphics-texture.cpp
         ../dali/dali-test-suite-utils/test-graphics-sampler.cpp
+        ../dali/dali-test-suite-utils/test-graphics-shader.cpp
+        ../dali/dali-test-suite-utils/test-graphics-texture.cpp
         ../dali/dali-test-suite-utils/test-native-image.cpp
         ../dali/dali-test-suite-utils/test-platform-abstraction.cpp
         ../dali/dali-test-suite-utils/test-render-controller.cpp
index c55b375..22c09cb 100644 (file)
@@ -116,7 +116,9 @@ 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-program.cpp
         dali-test-suite-utils/test-graphics-reflection.cpp
+        dali-test-suite-utils/test-graphics-shader.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 e678074..3a4e127 100644 (file)
@@ -72,4 +72,46 @@ Geometry CreateQuadGeometry(void)
   return geometry;
 }
 
+Property::Map CreateModelVertexFormat()
+{
+  Property::Map modelVF;
+  modelVF["aPosition"]       = Property::VECTOR3;
+  modelVF["aNormal"]         = Property::VECTOR3;
+  modelVF["aTexCoord1"]      = Property::VECTOR3;
+  modelVF["aTexCoord2"]      = Property::VECTOR3;
+  modelVF["aBoneIndex[0]"]   = Property::INTEGER;
+  modelVF["aBoneIndex[1]"]   = Property::INTEGER;
+  modelVF["aBoneIndex[2]"]   = Property::INTEGER;
+  modelVF["aBoneIndex[3]"]   = Property::INTEGER;
+  modelVF["aBoneWeights[0]"] = Property::FLOAT;
+  modelVF["aBoneWeights[1]"] = Property::FLOAT;
+  modelVF["aBoneWeights[2]"] = Property::FLOAT;
+  modelVF["aBoneWeights[3]"] = Property::FLOAT;
+  return modelVF;
+}
+
+Geometry CreateModelGeometry(Property::Map& vf)
+{
+  VertexBuffer vertexData = VertexBuffer::New(vf);
+
+  struct Vertex
+  {
+    Vector3 position;
+    Vector3 diffuseTexCoords;
+    Vector3 metalRoughTexCoords;
+    int     boneIndices[4];
+    float   boneWeights[4];
+  };
+
+  Vertex verts[30];
+  vertexData.SetData(verts, 30);
+  unsigned short indexData[40];
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer(vertexData);
+  geometry.SetIndexBuffer(indexData, sizeof(indexData) / sizeof(indexData[0]));
+
+  return geometry;
+}
+
 } // namespace Dali
index d5c61b0..adcf78e 100644 (file)
@@ -2,7 +2,7 @@
 #define MESH_BUILDER_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * 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.
 
 namespace Dali
 {
-Shader       CreateShader();
-TextureSet   CreateTextureSet();
-TextureSet   CreateTextureSet(Texture texture);
-Geometry     CreateQuadGeometry();
-VertexBuffer CreateVertexBuffer();
+Shader        CreateShader();
+TextureSet    CreateTextureSet();
+TextureSet    CreateTextureSet(Texture texture);
+Geometry      CreateQuadGeometry();
+Geometry      CreateModelGeometry(Property::Map& vf);
+VertexBuffer  CreateVertexBuffer();
+Property::Map CreateModelVertexFormat();
 
 } // namespace Dali
 
index 41d13c9..23f98ba 100644 (file)
@@ -20,6 +20,7 @@
 #include "test-graphics-command-buffer.h"
 #include "test-graphics-reflection.h"
 #include "test-graphics-sampler.h"
+#include "test-graphics-shader.h"
 #include "test-graphics-texture.h"
 
 #include <dali/integration-api/gl-defines.h>
@@ -444,7 +445,9 @@ void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& su
   namedParams["submitInfo"] << "cmdBuffer[" << submitInfo.cmdBuffer.size()
                             << "], flags:" << std::hex << submitInfo.flags;
 
-  mCallStack.PushCall("Controller::SubmitCommandBuffers", "", namedParams);
+  mCallStack.PushCall("SubmitCommandBuffers", "", namedParams);
+
+  mSubmitStack.emplace_back(submitInfo);
 
   for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
   {
@@ -576,7 +579,7 @@ void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderT
 {
   TraceCallStack::NamedParams namedParams;
   namedParams["renderTarget"] << std::hex << renderTarget;
-  mCallStack.PushCall("Controller::PresentRenderTarget", "", namedParams);
+  mCallStack.PushCall("PresentRenderTarget", "", namedParams);
 }
 
 /**
@@ -584,7 +587,7 @@ void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderT
  */
 void TestGraphicsController::WaitIdle()
 {
-  mCallStack.PushCall("Controller::WaitIdle", "");
+  mCallStack.PushCall("WaitIdle", "");
 }
 
 /**
@@ -592,7 +595,7 @@ void TestGraphicsController::WaitIdle()
  */
 void TestGraphicsController::Pause()
 {
-  mCallStack.PushCall("Controller::Pause", "");
+  mCallStack.PushCall("Pause", "");
 }
 
 /**
@@ -600,7 +603,7 @@ void TestGraphicsController::Pause()
  */
 void TestGraphicsController::Resume()
 {
-  mCallStack.PushCall("Controller::Resume", "");
+  mCallStack.PushCall("Resume", "");
 }
 
 void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureUpdateInfo>&       updateInfoList,
@@ -610,7 +613,7 @@ void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureU
   namedParams["updateInfoList"] << "[" << updateInfoList.size() << "]:";
   namedParams["sourceList"] << "[" << sourceList.size() << "]:";
 
-  mCallStack.PushCall("Controller::UpdateTextures", "", namedParams);
+  mCallStack.PushCall("UpdateTextures", "", namedParams);
 
   // Call either TexImage2D or TexSubImage2D
   for(unsigned int i = 0; i < updateInfoList.size(); ++i)
@@ -629,7 +632,7 @@ bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool ena
   TraceCallStack::NamedParams namedParams;
   namedParams["enableDepth"] << (enableDepth ? "T" : "F");
   namedParams["enableStencil"] << (enableStencil ? "T" : "F");
-  mCallStack.PushCall("Controller::EnableDepthStencilBuffer", "", namedParams);
+  mCallStack.PushCall("EnableDepthStencilBuffer", "", namedParams);
   return false;
 }
 
@@ -637,17 +640,17 @@ void TestGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRendere
 {
   TraceCallStack::NamedParams namedParams;
   namedParams["numberOfDiscardedRenderers"] << numberOfDiscardedRenderers;
-  mCallStack.PushCall("Controller::RunGarbageCollector", "", namedParams);
+  mCallStack.PushCall("RunGarbageCollector", "", namedParams);
 }
 
 void TestGraphicsController::DiscardUnusedResources()
 {
-  mCallStack.PushCall("Controller::DiscardUnusedResources", "");
+  mCallStack.PushCall("DiscardUnusedResources", "");
 }
 
 bool TestGraphicsController::IsDiscardQueueEmpty()
 {
-  mCallStack.PushCall("Controller::IsDiscardQueueEmpty", "");
+  mCallStack.PushCall("IsDiscardQueueEmpty", "");
   return isDiscardQueueEmptyResult;
 }
 
@@ -658,7 +661,7 @@ bool TestGraphicsController::IsDiscardQueueEmpty()
  */
 bool TestGraphicsController::IsDrawOnResumeRequired()
 {
-  mCallStack.PushCall("Controller::IsDrawOnResumeRequired", "");
+  mCallStack.PushCall("IsDrawOnResumeRequired", "");
   return isDrawOnResumeRequiredResult;
 }
 
@@ -666,7 +669,7 @@ Graphics::UniquePtr<Graphics::Buffer> TestGraphicsController::CreateBuffer(const
 {
   std::ostringstream oss;
   oss << "bufferCreateInfo:" << createInfo;
-  mCallStack.PushCall("Controller::CreateBuffer", oss.str());
+  mCallStack.PushCall("CreateBuffer", oss.str());
   return Graphics::MakeUnique<TestGraphicsBuffer>(mCallStack, mGl, createInfo.size, createInfo.usage);
 }
 
@@ -674,13 +677,13 @@ Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateComma
 {
   std::ostringstream oss;
   oss << "commandBufferCreateInfo:" << commandBufferCreateInfo;
-  mCallStack.PushCall("Controller::CreateCommandBuffer", oss.str());
+  mCallStack.PushCall("CreateCommandBuffer", oss.str());
   return Graphics::MakeUnique<TestGraphicsCommandBuffer>(mCommandBufferCallStack, mGl);
 }
 
 Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
 {
-  mCallStack.PushCall("Controller::CreateRenderPass", "");
+  mCallStack.PushCall("CreateRenderPass", "");
   return nullptr;
 }
 
@@ -688,47 +691,53 @@ Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(con
 {
   TraceCallStack::NamedParams namedParams;
   namedParams["textureCreateInfo"] << textureCreateInfo;
-  mCallStack.PushCall("Controller::CreateTexture", namedParams.str(), namedParams);
+  mCallStack.PushCall("CreateTexture", namedParams.str(), namedParams);
 
   return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
 }
 
 Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(const Graphics::FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
 {
-  mCallStack.PushCall("Controller::CreateFramebuffer", "");
+  mCallStack.PushCall("CreateFramebuffer", "");
   return nullptr;
 }
 
 Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
 {
-  mCallStack.PushCall("Controller::CreatePipeline", "");
+  mCallStack.PushCall("CreatePipeline", "");
   return std::make_unique<TestGraphicsPipeline>(mGl, pipelineCreateInfo);
 }
 
+Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram)
+{
+  mCallStack.PushCall("CreateProgram", "");
+  return Graphics::MakeUnique<TestGraphicsProgram>(mGl, programCreateInfo, mVertexFormats);
+}
+
 Graphics::UniquePtr<Graphics::Shader> TestGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Graphics::Shader>&& oldShader)
 {
-  mCallStack.PushCall("Controller::CreateShader", "");
-  return nullptr;
+  mCallStack.PushCall("CreateShader", "");
+  return Graphics::MakeUnique<TestGraphicsShader>(mGl, shaderCreateInfo);
 }
 
 Graphics::UniquePtr<Graphics::Sampler> TestGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Graphics::Sampler>&& oldSampler)
 {
   TraceCallStack::NamedParams namedParams;
   namedParams["samplerCreateInfo"] << samplerCreateInfo;
-  mCallStack.PushCall("Controller::CreateSampler", namedParams.str(), namedParams);
+  mCallStack.PushCall("CreateSampler", namedParams.str(), namedParams);
 
   return Graphics::MakeUnique<TestGraphicsSampler>(mGl, samplerCreateInfo);
 }
 
 Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
 {
-  mCallStack.PushCall("Controller::CreateRenderTarget", "");
+  mCallStack.PushCall("CreateRenderTarget", "");
   return nullptr;
 }
 
 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
 {
-  mCallStack.PushCall("Controller::MapBufferRange", "");
+  mCallStack.PushCall("MapBufferRange", "");
 
   auto buffer = static_cast<TestGraphicsBuffer*>(mapInfo.buffer);
   buffer->memory.resize(mapInfo.offset + mapInfo.size); // For initial testing, allow writes past capacity
@@ -738,46 +747,45 @@ Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(con
 
 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapTextureRange(const Graphics::MapTextureInfo& mapInfo)
 {
-  mCallStack.PushCall("Controller::MapTextureRange", "");
+  mCallStack.PushCall("MapTextureRange", "");
   return nullptr;
 }
 
 void TestGraphicsController::UnmapMemory(Graphics::UniquePtr<Graphics::Memory> memory)
 {
-  mCallStack.PushCall("Controller::UnmapMemory", "");
+  mCallStack.PushCall("UnmapMemory", "");
 }
 
 Graphics::MemoryRequirements TestGraphicsController::GetTextureMemoryRequirements(Graphics::Texture& texture) const
 {
-  mCallStack.PushCall("Controller::GetTextureMemoryRequirements", "");
+  mCallStack.PushCall("GetTextureMemoryRequirements", "");
   return Graphics::MemoryRequirements{};
 }
 
 Graphics::MemoryRequirements TestGraphicsController::GetBufferMemoryRequirements(Graphics::Buffer& buffer) const
 {
-  mCallStack.PushCall("Controller::GetBufferMemoryRequirements", "");
+  mCallStack.PushCall("GetBufferMemoryRequirements", "");
   return Graphics::MemoryRequirements{};
 }
 
 const Graphics::TextureProperties& TestGraphicsController::GetTextureProperties(const Graphics::Texture& texture)
 {
   static Graphics::TextureProperties textureProperties{};
-  mCallStack.PushCall("Controller::GetTextureProperties", "");
+  mCallStack.PushCall("GetTextureProperties", "");
 
   return textureProperties;
 }
 
-const Graphics::Reflection& TestGraphicsController::GetPipelineReflection(const Graphics::Pipeline& pipeline)
+const Graphics::Reflection& TestGraphicsController::GetProgramReflection(const Graphics::Program& program)
 {
-  static TestGraphicsReflection reflection(mGl);
-  mCallStack.PushCall("Controller::GetPipelineReflection", "");
+  mCallStack.PushCall("GetProgramReflection", "");
 
-  return reflection;
+  return static_cast<const TestGraphicsProgram*>(&program)->GetReflection();
 }
 
 bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
 {
-  mCallStack.PushCall("Controller::PipelineEquals", "");
+  mCallStack.PushCall("PipelineEquals", "");
   return false;
 }
 
index bf2ba21..c235d29 100644 (file)
@@ -176,6 +176,14 @@ public:
   Graphics::UniquePtr<Graphics::Pipeline> CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline) override;
 
   /**
+   * @brief Creates new Program object
+   *
+   * @param[in] programCreateInfo The valid ProgramCreateInfo structure
+   * @return pointer to the Program object
+   */
+  Graphics::UniquePtr<Graphics::Program> CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram) override;
+
+  /**
    * @brief Creates new Shader object
    *
    * @param[in] shaderCreateInfo The valid ShaderCreateInfo structure
@@ -268,12 +276,12 @@ public:
   const Graphics::TextureProperties& GetTextureProperties(const Graphics::Texture& texture) override;
 
   /**
-   * @brief Returns the reflection of the given pipeline
+   * @brief Returns the reflection of the given program
    *
-   * @param[in] pipeline The pipeline
-   * @return The reflection of the pipeline
+   * @param[in] program The program
+   * @return The reflection of the program
    */
-  const Graphics::Reflection& GetPipelineReflection(const Graphics::Pipeline& pipeline) override;
+  const Graphics::Reflection& GetProgramReflection(const Graphics::Program& program) override;
 
   /**
    * @brief Tests whether two Pipelines are the same.
@@ -284,9 +292,21 @@ public:
    */
   bool PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const override;
 
+public: // Test Functions
+  void SetVertexFormats(Property::Array& vfs)
+  {
+    mVertexFormats = vfs;
+  }
+
+  void ClearSubmitStack()
+  {
+    mSubmitStack.clear();
+  }
+
 public:
-  mutable TraceCallStack mCallStack;
-  mutable TraceCallStack mCommandBufferCallStack;
+  mutable TraceCallStack                    mCallStack;
+  mutable TraceCallStack                    mCommandBufferCallStack;
+  mutable std::vector<Graphics::SubmitInfo> mSubmitStack;
 
   TestGlAbstraction              mGl;
   TestGlSyncAbstraction          mGlSyncAbstraction;
@@ -294,6 +314,8 @@ public:
 
   bool isDiscardQueueEmptyResult{true};
   bool isDrawOnResumeRequiredResult{true};
+
+  Property::Array mVertexFormats;
 };
 
 } // namespace Dali
index 0cc4194..d303d56 100644 (file)
@@ -26,8 +26,8 @@ TestGraphicsPipeline::TestGraphicsPipeline(TestGlAbstraction& gl, const Graphics
   if(createInfo.colorBlendState)
     colorBlendState = *createInfo.colorBlendState;
 
-  if(createInfo.shaderState)
-    shaderState = *createInfo.shaderState;
+  if(createInfo.programState)
+    programState = *createInfo.programState;
 
   if(createInfo.viewportState)
     viewportState = *createInfo.viewportState;
index 666e0d4..a748e71 100644 (file)
 #include <dali/graphics-api/graphics-pipeline-create-info.h>
 #include <dali/graphics-api/graphics-pipeline.h>
 #include "test-gl-abstraction.h"
+#include "test-graphics-program.h"
+#include "test-graphics-reflection.h"
 
 namespace Dali
 {
+class TestGraphicsReflection;
+
+template<typename T>
+T* Uncast(const Graphics::Program* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
 class TestGraphicsPipeline : public Graphics::Pipeline
 {
 public:
   TestGraphicsPipeline(TestGlAbstraction& gl, const Graphics::PipelineCreateInfo& createInfo);
 
+  const TestGraphicsReflection& GetReflection() const
+  {
+    return Uncast<TestGraphicsProgram>(programState.program)->GetReflection();
+  }
+
+public:
   TestGlAbstraction& mGl;
 
   Graphics::ColorBlendState          colorBlendState;
-  std::vector<Graphics::ShaderState> shaderState;
+  Graphics::ProgramState             programState;
   Graphics::ViewportState            viewportState;
   Graphics::FramebufferState         framebufferState;
   Graphics::Pipeline                 basePipeline;
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.cpp
new file mode 100644 (file)
index 0000000..db5a9f7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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-program.h"
+
+namespace Dali
+{
+TestGraphicsProgram::TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats)
+: mGl(gl),
+  mCreateInfo(createInfo),
+  mReflection(gl, vertexFormats)
+{
+}
+
+} // namespace Dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.h b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.h
new file mode 100644 (file)
index 0000000..2bd04de
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef DALI_TEST_GRAPHICS_PROGRAM_H
+#define DALI_TEST_GRAPHICS_PROGRAM_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-program-create-info.h>
+#include <dali/graphics-api/graphics-program.h>
+#include "test-gl-abstraction.h"
+#include "test-graphics-reflection.h"
+
+namespace Dali
+{
+class TestGraphicsProgram : public Graphics::Program
+{
+public:
+  TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats);
+
+  // For API
+  const TestGraphicsReflection& GetReflection() const
+  {
+    // Build a reflection
+    return mReflection;
+  }
+
+  // For tests
+  TestGraphicsReflection& GetProgamReflection()
+  {
+    return mReflection;
+  }
+
+public:
+  TestGlAbstraction&          mGl;
+  Graphics::ProgramCreateInfo mCreateInfo;
+  TestGraphicsReflection      mReflection;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_PROGRAM_H
index 9bce79a..c9ef2d0 100644 (file)
  */
 
 #include "test-graphics-reflection.h"
+#include <dali/public-api/object/property-map.h>
 
 namespace Dali
 {
-TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl)
+TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vfs)
 : mGl(gl)
 {
+  for(Property::Array::SizeType i = 0; i < vfs.Count(); ++i)
+  {
+    Property::Map* vertexFormat = vfs[i].GetMap();
+    if(vertexFormat)
+    {
+      for(Property::Map::SizeType j = 0; j < vertexFormat->Count(); ++j)
+      {
+        auto key = vertexFormat->GetKeyAt(j);
+        if(key.type == Property::Key::STRING)
+        {
+          mAttributes.push_back(key.stringKey);
+        }
+      }
+    }
+  }
 }
 
 uint32_t TestGraphicsReflection::GetVertexAttributeLocation(const std::string& name) const
 {
+  // Automatically assign locations to named attributes when requested
+  auto iter = std::find(mAttributes.begin(), mAttributes.end(), name);
+  if(iter != mAttributes.end())
+  {
+    return iter - mAttributes.begin();
+  }
+  else
+  {
+    uint32_t location = mAttributes.size();
+    mAttributes.push_back(name);
+    return location;
+  }
   return 0u;
 }
 
@@ -40,7 +68,12 @@ std::string TestGraphicsReflection::GetVertexAttributeName(uint32_t location) co
 
 std::vector<uint32_t> TestGraphicsReflection::GetVertexAttributeLocations() const
 {
-  return std::vector<uint32_t>{};
+  std::vector<uint32_t> locs;
+  for(uint32_t i = 0; i < mAttributes.size(); ++i)
+  {
+    locs.push_back(i);
+  }
+  return locs;
 }
 
 uint32_t TestGraphicsReflection::GetUniformBlockCount() const
index 1c9f62b..9311e07 100644 (file)
@@ -25,7 +25,7 @@ namespace Dali
 class TestGraphicsReflection : public Graphics::Reflection
 {
 public:
-  TestGraphicsReflection(TestGlAbstraction& gl);
+  TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vertexFormats);
 
   uint32_t                                   GetVertexAttributeLocation(const std::string& name) const override;
   Dali::Graphics::VertexInputAttributeFormat GetVertexAttributeFormat(uint32_t location) const override;
@@ -44,7 +44,19 @@ public:
   std::vector<Dali::Graphics::UniformInfo>   GetSamplers() const override;
   Graphics::ShaderLanguage                   GetLanguage() const override;
 
-  TestGlAbstraction& mGl;
+public: // Test methods
+  void SetAttributes(std::vector<std::string> locations)
+  {
+    mAttributes.clear();
+    mAttributes.resize(locations.size());
+    for(auto& location : locations)
+    {
+      mAttributes.push_back(location);
+    }
+  }
+
+  TestGlAbstraction&               mGl;
+  mutable std::vector<std::string> mAttributes;
 };
 
 } // namespace Dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-shader.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-shader.cpp
new file mode 100644 (file)
index 0000000..db2d1a2
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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-shader.h"
+
+namespace Dali
+{
+TestGraphicsShader::TestGraphicsShader(TestGlAbstraction& gl, const Graphics::ShaderCreateInfo& createInfo)
+: mGl(gl),
+  mCreateInfo(createInfo)
+{
+}
+
+} // namespace Dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-shader.h b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-shader.h
new file mode 100644 (file)
index 0000000..ad6f9c5
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef DALI_TEST_GRAPHICS_SHADER_H
+#define DALI_TEST_GRAPHICS_SHADER_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-shader-create-info.h>
+#include <dali/graphics-api/graphics-shader.h>
+#include "test-gl-abstraction.h"
+
+namespace Dali
+{
+class TestGraphicsShader : public Graphics::Shader
+{
+public:
+  TestGraphicsShader(TestGlAbstraction& gl, const Graphics::ShaderCreateInfo& createInfo);
+
+public:
+  TestGlAbstraction&         mGl;
+  Graphics::ShaderCreateInfo mCreateInfo;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_SHADER_H
index 6a1306c..3d09351 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali-test-suite-utils.h>
 #include <mesh-builder.h>
 #include <test-trace-call-stack.h>
+#include "test-graphics-command-buffer.h"
 
 using namespace Dali;
 
@@ -3599,3 +3600,68 @@ int UtcDaliRendererCheckTextureBindingP(void)
   DALI_TEST_CHECK(cmdBufCallstack.FindMethod("BindTextures"));
   END_TEST;
 }
+
+int UtcDaliRendererPreparePipeline(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that rendering an actor binds the attributes locs from the reflection");
+
+  Property::Map vf            = CreateModelVertexFormat();
+  Geometry      modelGeometry = CreateModelGeometry(vf);
+  Shader        shader        = Shader::New("vertexSrc", "fragmentSrc");
+  Renderer      renderer      = Renderer::New(modelGeometry, shader);
+  Actor         actor         = Actor::New();
+
+  // Change the order up to get a fair test
+  Property::Map modelVF;
+  modelVF["aBoneIndex[0]"]   = Property::INTEGER;
+  modelVF["aBoneIndex[1]"]   = Property::INTEGER;
+  modelVF["aBoneIndex[2]"]   = Property::INTEGER;
+  modelVF["aBoneIndex[3]"]   = Property::INTEGER;
+  modelVF["aBoneWeights[0]"] = Property::FLOAT;
+  modelVF["aBoneWeights[1]"] = Property::FLOAT;
+  modelVF["aBoneWeights[2]"] = Property::FLOAT;
+  modelVF["aBoneWeights[3]"] = Property::FLOAT;
+  modelVF["aPosition"]       = Property::VECTOR3;
+  modelVF["aNormal"]         = Property::VECTOR3;
+  modelVF["aTexCoord1"]      = Property::VECTOR3;
+  modelVF["aTexCoord2"]      = Property::VECTOR3;
+
+  Property::Array vfs;
+  vfs.PushBack(modelVF);
+  TestGraphicsController& graphics = application.GetGraphicsController();
+  graphics.SetVertexFormats(vfs);
+
+  actor.AddRenderer(renderer);
+  actor.SetProperty(Actor::Property::SIZE, Vector2(400.0f, 400.0f));
+  actor.SetProperty(Actor::Property::COLOR, Color::WHITE);
+  application.GetScene().Add(actor);
+
+  TraceCallStack& cmdBufCallstack   = graphics.mCommandBufferCallStack;
+  TraceCallStack& graphicsCallstack = graphics.mCallStack;
+  cmdBufCallstack.Enable(true);
+  graphicsCallstack.Enable(true);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(graphicsCallstack.FindMethod("SubmitCommandBuffers"));
+  std::vector<Graphics::SubmitInfo>& submissions = graphics.mSubmitStack;
+  DALI_TEST_EQUALS(submissions.size(), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS(submissions[0].cmdBuffer.size(), 1, TEST_LOCATION);
+  const TestGraphicsCommandBuffer* cmdBuf   = static_cast<TestGraphicsCommandBuffer*>((submissions[0].cmdBuffer[0]));
+  auto                             pipeline = cmdBuf->mPipeline;
+  if(pipeline)
+  {
+    DALI_TEST_EQUALS(pipeline->vertexInputState.attributes.size(), 12, TEST_LOCATION);
+    DALI_TEST_EQUALS(pipeline->vertexInputState.attributes[3].location, // 4th requested attr: aTexCoord2
+                     11,
+                     TEST_LOCATION);
+    DALI_TEST_EQUALS(pipeline->vertexInputState.attributes[3].format, // 4th requested attr: aTexCoord2
+                     Graphics::VertexInputFormat::FVECTOR3,
+                     TEST_LOCATION);
+  }
+
+  END_TEST;
+}
index 40f9a97..acded89 100644 (file)
@@ -370,6 +370,8 @@ IF( ENABLE_LINK_TEST )
     ${DALI_TEST_SUITE_DIR}/test-graphics-texture.cpp
     ${DALI_TEST_SUITE_DIR}/test-graphics-buffer.cpp
     ${DALI_TEST_SUITE_DIR}/test-graphics-pipeline.cpp
+    ${DALI_TEST_SUITE_DIR}/test-graphics-program.cpp
+    ${DALI_TEST_SUITE_DIR}/test-graphics-shader.cpp
     ${DALI_TEST_SUITE_DIR}/test-graphics-reflection.cpp
     ${DALI_TEST_SUITE_DIR}/test-graphics-command-buffer.cpp
     ${DALI_TEST_SUITE_DIR}/test-platform-abstraction.cpp
index 66dd62f..fe4f7d3 100644 (file)
@@ -12,8 +12,10 @@ SET( GRAPHICS_API_HEADERS ${GRAPHICS_API_HEADERS}
    ${graphics_src_dir}/graphics-framebuffer-create-info.h
    ${graphics_src_dir}/graphics-framebuffer.h
    ${graphics_src_dir}/graphics-memory.h
-   ${graphics_src_dir}/graphics-pipeline-create-info.h 
+   ${graphics_src_dir}/graphics-pipeline-create-info.h
    ${graphics_src_dir}/graphics-pipeline.h
+   ${graphics_src_dir}/graphics-program-create-info.h
+   ${graphics_src_dir}/graphics-program.h
    ${graphics_src_dir}/graphics-reflection.h
    ${graphics_src_dir}/graphics-render-pass-create-info.h
    ${graphics_src_dir}/graphics-render-pass.h
index 012302d..9732ab1 100644 (file)
@@ -28,6 +28,7 @@
 #include "graphics-framebuffer-create-info.h"
 #include "graphics-memory.h"
 #include "graphics-pipeline-create-info.h"
+#include "graphics-program-create-info.h"
 #include "graphics-reflection.h"
 #include "graphics-render-pass-create-info.h"
 #include "graphics-render-target-create-info.h"
@@ -220,6 +221,16 @@ public:
    * @return pointer to the Pipeline object
    */
   virtual UniquePtr<Pipeline> CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, UniquePtr<Pipeline>&& oldPipeline) = 0;
+
+  /**
+   * @brief Creates new Program object
+   *
+   * @param[in] ProgramCreateInfo The valid ProgramCreateInfo structure
+   * @param[in] oldProgram The valid pointer to the old object or nullptr. The object will be reused or destroyed.
+   * @return pointer to the Program object
+   */
+  virtual UniquePtr<Program> CreateProgram(const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram) = 0;
+
   /**
    * @brief Creates new Shader object
    *
@@ -315,12 +326,12 @@ public:
   virtual const TextureProperties& GetTextureProperties(const Texture& texture) = 0;
 
   /**
-   * @brief Returns the reflection of the given pipeline
+   * @brief Returns the reflection of the given program
    *
-   * @param[in] pipeline The pipeline
-   * @return The reflection of the pipeline
+   * @param[in] program The program
+   * @return The reflection of the program
    */
-  virtual const Reflection& GetPipelineReflection(const Pipeline& pipeline) = 0;
+  virtual const Reflection& GetProgramReflection(const Program& program) = 0;
 
   /**
    * @brief Tests whether two Pipelines are the same.
index 2e7d49a..d4b4014 100644 (file)
@@ -58,56 +58,32 @@ struct PipelineCreateInfo
   }
 
   /**
-   * @brief Sets the color blend state
-   * param[in] pointer to valid color blend state structure
-   * @return reference to this structure
+   * @brief Set the program
+   *
+   * @param[in] value
+   * @return a reference to this structure
    */
-  auto& SetColorBlendState(ColorBlendState* value)
+  auto& SetProgramState(ProgramState* value)
   {
-    colorBlendState = value;
+    programState = value;
     return *this;
   }
 
   /**
-   * @brief Sets the shader state for the pipeline
-   *
-   * The function takes an array of shader states in order to compile
-   * the pipeline. Each ShaderState structure determines the pipeline stage
-   * the shader should be executed on. The Shader object may be already created
-   * with a specific stage. Then the ShaderState::inheritPipelineStage must be
-   * set to true.
-   *
-   * Sample:
-   * SetShaderState( { ShaderState().SetShader( vertexShader)
-   *                                .SetPipelineStage( PipelineStage::VERTEX_SHADER ),
-   *                   ShaderState().SetShader( fragmentShader )
-   *                                .SetPipelineStage( PipelineStage::FRAGMENT_SHADER )
-   *                  } );
-   *
-   * In modern graphics API it is possible to attach more than one Shader to a single
-   * stage. For example, one Shader may be just a library of functions:
-   * SetShaderState( { ShaderState().SetShader( vertexShader)
-   *                                .SetPipelineStage( PipelineStage::VERTEX_SHADER ),
-   *                   ShaderState().SetShader( shaderCommons )
-   *                                .SetPipelineStage( PipelineStage::VERTEX_SHADER ),
-   *                   ShaderState().SetShader( fragmentShader )
-   *                                .SetPipelineStage( PipelineStage::FRAGMENT_SHADER )
-   *                  } );
-   *
-   * The Pipeline will compile and link all given shaders.
-   *
-   * param[in] value Valid array of shder states
+   * @brief Sets the color blend state
+   * @param[in] value pointer to valid color blend state structure
    * @return reference to this structure
    */
-  auto& SetShaderState(const std::vector<ShaderState>& value)
+  auto& SetColorBlendState(ColorBlendState* value)
   {
-    shaderState = &value;
+    colorBlendState = value;
     return *this;
   }
 
   /**
-   * @brief Sets the viewport state
-   * param[in] pointer to valid viewport state structure
+   * @brief Sets the viewport state.
+   *
+   * @param[in] value pointer to valid viewport state structure
    * @return reference to this structure
    */
   auto& SetViewportState(ViewportState* value)
@@ -117,8 +93,9 @@ struct PipelineCreateInfo
   }
 
   /**
-   * @brief Sets the framebuffer state
-   * param[in] pointer to valid framebuffer state structure
+   * @brief Sets the framebuffer state.
+   *
+   * @param[in] value pointer to valid framebuffer state structure
    * @return reference to this structure
    */
   auto& SetFramebufferState(FramebufferState* value)
@@ -128,13 +105,13 @@ struct PipelineCreateInfo
   }
 
   /**
-   * @brief Sets the base pipeline
+   * @brief Sets the base pipeline.
    *
    * Setting base pipeline allows inheriting that pipeline state
    * and build the new pipeline from it. The base pipeline
    * must stay valid until derived pipeline needs it.
    *
-   * param[in] pointer to valid pipeline object
+   * @param[in] value pointer to valid pipeline object
    * @return reference to this structure
    */
   auto& SetBasePipeline(Pipeline* value)
@@ -144,8 +121,9 @@ struct PipelineCreateInfo
   }
 
   /**
-   * @brief Sets the depth/stencil state
-   * param[in] pointer to valid depth/stencil state structure
+   * @brief Sets the depth/stencil state.
+   *
+   * @param[in] pointer to valid depth/stencil state structure
    * @return reference to this structure
    */
   auto& SetDepthStencilState(DepthStencilState* value)
@@ -155,8 +133,9 @@ struct PipelineCreateInfo
   }
 
   /**
-   * @brief Sets the rasterization state
-   * param[in] pointer to valid rasterization state structure
+   * @brief Sets the rasterization state.
+   *
+   * @param[in] pointer to valid rasterization state structure
    * @return reference to this structure
    */
   auto& SetRasterizationState(RasterizationState* value)
@@ -166,12 +145,12 @@ struct PipelineCreateInfo
   }
 
   /**
-   * @brief Sets the vertex input state
+   * @brief Sets the vertex input state.
    *
    * Vertex input state describes format of vertices and must
    * be compatible with attached shaders.
    *
-   * param[in] pointer to vertex input state structure
+   * @param[in] pointer to vertex input state structure
    * @return reference to this structure
    */
   auto& SetVertexInputState(VertexInputState* value)
@@ -181,11 +160,11 @@ struct PipelineCreateInfo
   }
 
   /**
-   * @brief Sets the input assembly state
+   * @brief Sets the input assembly state.
    *
    * This state describes the topology of the pipeline.
    *
-   * param[in] pointer to valid input assembly state structure
+   * @param[in] pointer to valid input assembly state structure
    * @return reference to this structure
    */
   auto& SetInputAssemblyState(InputAssemblyState* value)
@@ -195,13 +174,13 @@ struct PipelineCreateInfo
   }
 
   /**
-   * @brief Sets the dynamic state mask
+   * @brief Sets the dynamic state mask.
    *
    * Certain states can be modified on fly without a need of
    * creating new pipeline. The commands which modify particular
    * states may be issued later by executing command buffers.
    *
-   * param[in] pointer to valid color blend state structure
+   * @param[in] pointer to valid color blend state structure
    * @return reference to this structure
    */
   auto& SetDynamicStateMask(PipelineDynamicStateMask value)
@@ -226,16 +205,16 @@ struct PipelineCreateInfo
   GraphicsStructureType type{GraphicsStructureType::PIPELINE_CREATE_INFO_STRUCT};
   ExtensionCreateInfo*  nextExtension{nullptr};
 
-  ColorBlendState*                colorBlendState{nullptr};
-  const std::vector<ShaderState>* shaderState{nullptr};
-  ViewportState*                  viewportState{nullptr};
-  FramebufferState*               framebufferState{nullptr};
-  Pipeline*                       basePipeline{nullptr};
-  DepthStencilState*              depthStencilState{nullptr};
-  RasterizationState*             rasterizationState{nullptr};
-  VertexInputState*               vertexInputState{nullptr};
-  InputAssemblyState*             inputAssemblyState{nullptr};
-  PipelineDynamicStateMask        dynamicStateMask{0u};
+  ProgramState*            programState{nullptr};
+  ColorBlendState*         colorBlendState{nullptr};
+  ViewportState*           viewportState{nullptr};
+  FramebufferState*        framebufferState{nullptr};
+  Pipeline*                basePipeline{nullptr};
+  DepthStencilState*       depthStencilState{nullptr};
+  RasterizationState*      rasterizationState{nullptr};
+  VertexInputState*        vertexInputState{nullptr};
+  InputAssemblyState*      inputAssemblyState{nullptr};
+  PipelineDynamicStateMask dynamicStateMask{0u};
 
   const AllocationCallbacks* allocationCallbacks{nullptr};
 };
diff --git a/dali/graphics-api/graphics-program-create-info.h b/dali/graphics-api/graphics-program-create-info.h
new file mode 100644 (file)
index 0000000..229b336
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef DALI_GRAPHICS_PROGRAM_CREATE_INFO_H
+#define DALI_GRAPHICS_PROGRAM_CREATE_INFO_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 "graphics-program.h"
+#include "graphics-types.h"
+
+namespace Dali
+{
+namespace Graphics
+{
+/**
+ * This structure represents the information needed to generate a program.
+ */
+struct ProgramCreateInfo
+{
+  /**
+   * @brief Sets pointer to the extension
+   *
+   * The pointer to the extension must be set either to nullptr
+   * or to the valid structure. The structures may create
+   * a chain. The last structure in a chain must point at
+   * nullptr.
+   *
+   * @param[in] value pointer to the valid extension structure
+   * @return reference to this structure
+   */
+  auto& SetNextExtension(ExtensionCreateInfo* value)
+  {
+    nextExtension = value;
+    return *this;
+  }
+
+  /**
+   * @brief Set the allocation callbacks.
+   *
+   * @param[in] value set of allocation callbacks
+   * @return reference to this structure.
+   */
+  auto& SetAllocationCallbacks(const AllocationCallbacks& value)
+  {
+    allocationCallbacks = &value;
+    return *this;
+  }
+
+  /**
+   * @brief Sets the shader state for the program
+   *
+   * The function takes an array of shader states in order to compile
+   * the program. Each ShaderState structure determines the pipeline stage
+   * the shader should be executed on. The Shader object may be already created
+   * with a specific stage.
+   *
+   * Sample:
+   * SetShaderState( { ShaderState().SetShader( vertexShader)
+   *                                .SetPipelineStage( PipelineStage::VERTEX_SHADER ),
+   *                   ShaderState().SetShader( fragmentShader )
+   *                                .SetPipelineStage( PipelineStage::FRAGMENT_SHADER )
+   *                  } );
+   *
+   * In modern graphics API it is possible to attach more than one Shader to a single
+   * stage. For example, one Shader may be just a library of functions:
+   * SetShaderState( { ShaderState().SetShader( vertexShader)
+   *                                .SetPipelineStage( PipelineStage::VERTEX_SHADER ),
+   *                   ShaderState().SetShader( shaderCommons )
+   *                                .SetPipelineStage( PipelineStage::VERTEX_SHADER ),
+   *                   ShaderState().SetShader( fragmentShader )
+   *                                .SetPipelineStage( PipelineStage::FRAGMENT_SHADER )
+   *                  } );
+   *
+   * The Program will compile and link all given shaders.
+   *
+   * param[in] value Valid array of shder states
+   * @return reference to this structure
+   */
+  auto& SetShaderState(const std::vector<ShaderState>& value)
+  {
+    shaderState = &value;
+    return *this;
+  }
+
+  GraphicsStructureType type{GraphicsStructureType::PROGRAM_CREATE_INFO_STRUCT};
+  ExtensionCreateInfo*  nextExtension{nullptr};
+
+  const std::vector<ShaderState>* shaderState{nullptr};
+  const AllocationCallbacks*      allocationCallbacks{nullptr};
+};
+
+} // namespace Graphics
+
+} // namespace Dali
+
+#endif //DALI_GRAPHICS_PROGRAM_CREATE_INFO_H
diff --git a/dali/graphics-api/graphics-program.h b/dali/graphics-api/graphics-program.h
new file mode 100644 (file)
index 0000000..e094fd8
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef DALI_GRAPHICS_PROGRAM_H
+#define DALI_GRAPHICS_PROGRAM_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.
+ */
+
+namespace Dali
+{
+namespace Graphics
+{
+/**
+ * @brief The Program class represents a set of shaders that can
+ * be compiled into a complete program and attached to a Pipeline.
+ * It can be used to fetch a Reflection object to determine the
+ * structure of attributes, uniforms and samplers within the shaders.
+ */
+class Program
+{
+public:
+  Program()          = default;
+  virtual ~Program() = default;
+
+  // not copyable
+  Program(const Program&) = delete;
+  Program& operator=(const Program&) = delete;
+
+protected:
+  Program(Program&&) = default;
+  Program& operator=(Program&&) = default;
+};
+
+} // namespace Graphics
+
+} // namespace Dali
+
+#endif //DALI_GRAPHICS_PROGRAM_H
index 7fee16b..8c45a53 100644 (file)
@@ -46,4 +46,4 @@ protected:
 } // namespace Graphics
 } // namespace Dali
 
-#endif
\ No newline at end of file
+#endif
index c5ae0b8..d690478 100644 (file)
@@ -28,11 +28,12 @@ namespace Dali
 {
 namespace Graphics
 {
-class CommandBuffer;
-class Texture;
 class Buffer;
-class Shader;
+class CommandBuffer;
 class Framebuffer;
+class Program;
+class Shader;
+class Texture;
 
 /**
  * @brief Structure describes 2D offset
@@ -356,7 +357,21 @@ struct ColorBlendState
 };
 
 /**
- * @brief  Framebuffer state
+ * @brief Program State
+ */
+struct ProgramState
+{
+  const Program* program{nullptr};
+
+  auto& SetProgram(const Program& value)
+  {
+    program = &value;
+    return *this;
+  }
+};
+
+/**
+ * @brief  Framebuffer state.
  */
 struct FramebufferState
 {
@@ -1251,6 +1266,7 @@ enum class GraphicsStructureType : uint32_t
   BUFFER_CREATE_INFO_STRUCT,
   COMMAND_BUFFER_CREATE_INFO_STRUCT,
   FRAMEBUFFER_CREATE_INFO_STRUCT,
+  PROGRAM_CREATE_INFO_STRUCT,
   PIPELINE_CREATE_INFO_STRUCT,
   RENDERPASS_CREATE_INFO_STRUCT,
   SAMPLER_CREATE_INFO_STRUCT,
index 215d4bb..671accd 100644 (file)
@@ -19,6 +19,7 @@
 #include <dali/internal/render/renderers/render-renderer.h>
 
 // INTERNAL INCLUDES
+#include <dali/graphics-api/graphics-program.h>
 #include <dali/graphics-api/graphics-types.h>
 #include <dali/internal/common/image-sampler.h>
 #include <dali/internal/render/common/render-instruction.h>
@@ -759,15 +760,18 @@ void Renderer::Render(Context&                                             conte
     Graphics::PipelineStage::FRAGMENT_SHADER,
     shaderData->GetSourceMode());
 
-  mShaderStates.clear();
-  mShaderStates.push_back(Graphics::ShaderState().SetShader(vertexShader).SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER));
-  mShaderStates.push_back(Graphics::ShaderState().SetShader(fragmentShader).SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER));
+  std::vector<Graphics::ShaderState> shaderStates{
+    Graphics::ShaderState().SetShader(vertexShader).SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
+    Graphics::ShaderState().SetShader(fragmentShader).SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
+  auto createInfo = Graphics::ProgramCreateInfo();
+  createInfo.SetShaderState(shaderStates);
 
-  auto createInfo = Graphics::PipelineCreateInfo().SetShaderState(mShaderStates).SetNextExtension(&mLegacyProgram);
+  mGraphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
 
   // Temporarily create a pipeline here - this will be used for transporting
   // topology, vertex format, attrs, rasterization state
-  mGraphicsPipeline = std::move(PrepareGraphicsPipeline(*program, instruction, blend, createInfo)); // WRONG: @todo FIXME. Renderer can't own a pipeline.
+  mGraphicsPipeline = std::move(PrepareGraphicsPipeline(*program, instruction, blend));
+
   commandBuffer->BindPipeline(*mGraphicsPipeline.get());
 
   if(DALI_LIKELY(BindTextures(*program, *commandBuffer.get(), boundTextures)))
@@ -887,11 +891,11 @@ bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvid
 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
   Program&                                             program,
   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
-  bool                                                 blend,
-  Graphics::PipelineCreateInfo&                        createInfo)
+  bool                                                 blend)
 {
   Graphics::InputAssemblyState inputAssemblyState{};
   Graphics::VertexInputState   vertexInputState{};
+  Graphics::ProgramState       programState{};
   uint32_t                     bindingIndex{0u};
 
   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
@@ -900,6 +904,8 @@ Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
     mUpdateAttributeLocations = true;
   }
 
+  auto& reflection = mGraphicsController->GetProgramReflection(*mGraphicsProgram.get());
+
   /**
    * Bind Attributes
    */
@@ -916,9 +922,8 @@ Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
     {
       if(mUpdateAttributeLocations)
       {
-        auto     attributeName = vertexBuffer->GetAttributeName(i);
-        uint32_t index         = program.RegisterCustomAttribute(attributeName);
-        int32_t  pLocation     = program.GetCustomAttributeLocation(index);
+        auto    attributeName = vertexBuffer->GetAttributeName(i);
+        int32_t pLocation     = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
         if(-1 == pLocation)
         {
           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
@@ -941,6 +946,9 @@ Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
   // Get the topology
   inputAssemblyState.SetTopology(mGeometry->GetTopology());
 
+  // Get the program
+  programState.SetProgram(*mGraphicsProgram.get());
+
   Graphics::RasterizationState rasterizationState{};
 
   //Set cull face  mode
@@ -1042,11 +1050,13 @@ Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
 
   // Create a new pipeline
   return mGraphicsController->CreatePipeline(
-    createInfo
+    Graphics::PipelineCreateInfo()
       .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
       .SetVertexInputState(&vertexInputState)
       .SetRasterizationState(&rasterizationState)
-      .SetColorBlendState(&colorBlendState),
+      .SetColorBlendState(&colorBlendState)
+      .SetProgramState(&programState)
+      .SetNextExtension(&mLegacyProgram),
     nullptr);
 }
 
index 94171ec..10fe621 100644 (file)
@@ -453,8 +453,7 @@ private:
   Graphics::UniquePtr<Graphics::Pipeline> PrepareGraphicsPipeline(
     Program&                                             program,
     const Dali::Internal::SceneGraph::RenderInstruction& instruction,
-    bool                                                 blend,
-    Graphics::PipelineCreateInfo&                        createInfo);
+    bool                                                 blend);
 
 private:
   Graphics::Controller*                        mGraphicsController;
@@ -463,9 +462,11 @@ private:
   Context*          mContext;
   Render::Geometry* mGeometry;
 
-  ProgramCache*                           mProgramCache{};
-  Render::ShaderCache*                    mShaderCache{};
-  Graphics::UniquePtr<Graphics::Pipeline> mGraphicsPipeline{}; ///< The graphics pipeline. @todo MOVE TO RenderManager
+  ProgramCache*        mProgramCache{};
+  Render::ShaderCache* mShaderCache{};
+
+  Graphics::UniquePtr<Graphics::Program>  mGraphicsProgram{};  ///< The graphics program. (Cached implementation)
+  Graphics::UniquePtr<Graphics::Pipeline> mGraphicsPipeline{}; ///< The graphics pipeline. (Cached implementation)
   std::vector<Graphics::ShaderState>      mShaderStates{};
 
   struct UniformIndexMap