[Vulkan] graphics controller, multiple pipelines
authoradam.b <jsr184@gmail.com>
Wed, 25 Apr 2018 17:49:19 +0000 (18:49 +0100)
committerDavid Steele <david.steele@samsung.com>
Thu, 3 May 2018 13:19:16 +0000 (13:19 +0000)
- vulkan-graphics-controller cleaned up

- 'Blocks' demo works!

- Passes built-in uniforms to the render command
- Renders, just not exactly what it should ( under investigation )

- Texture binding to descriptor set works
- UBO writing into descriptors work
- Limitation:
  [1] Since DALi doesn't support UBOs, the "push constants"
      are written as UBOs by Graphics Vulkan backend.
  [2] Only one descriptor set allowed ( index = 0 )

- UBOs are being updated with data
- Created descriptor sets and pools per render command

- Added UBO manager and pools

- Graphics controller creates multiple pipelines depends on the state
- Render command has been extended to pass the list of textures
- Removed sampler-id hack from the code and the default shader
- Textures passed via Accessor
- Added buffer factory
- Using SPIRV reflection in order to map vertex input attributes

Limitation:

- Single texture passed per render item

Change-Id: Ib613d6cbc1ec481c2bd1fc7d504c58080c2f8cfa

59 files changed:
dali/graphics-api/graphics-api-buffer-factory.h [new file with mode: 0644]
dali/graphics-api/graphics-api-buffer.h
dali/graphics-api/graphics-api-controller.h
dali/graphics-api/graphics-api-framebuffer.h
dali/graphics-api/graphics-api-render-command.h
dali/graphics-api/graphics-api-shader-details.h
dali/graphics-api/graphics-api-shader.h
dali/graphics-api/utility/utility-memory-pool.h [new file with mode: 0644]
dali/graphics/file.list
dali/graphics/vulkan/api/internal/vulkan-ubo-manager.cpp [new file with mode: 0644]
dali/graphics/vulkan/api/internal/vulkan-ubo-manager.h [new file with mode: 0644]
dali/graphics/vulkan/api/internal/vulkan-ubo-pool.cpp [new file with mode: 0644]
dali/graphics/vulkan/api/internal/vulkan-ubo-pool.h [new file with mode: 0644]
dali/graphics/vulkan/api/vulkan-api-buffer-factory.cpp [new file with mode: 0644]
dali/graphics/vulkan/api/vulkan-api-buffer-factory.h [new file with mode: 0644]
dali/graphics/vulkan/api/vulkan-api-buffer.cpp [new file with mode: 0644]
dali/graphics/vulkan/api/vulkan-api-buffer.h [new file with mode: 0644]
dali/graphics/vulkan/api/vulkan-api-render-command.cpp [new file with mode: 0644]
dali/graphics/vulkan/api/vulkan-api-render-command.h [new file with mode: 0644]
dali/graphics/vulkan/api/vulkan-api-shader-factory.cpp
dali/graphics/vulkan/api/vulkan-api-shader.cpp
dali/graphics/vulkan/api/vulkan-api-shader.h
dali/graphics/vulkan/generated/spv-shaders-gen.cpp
dali/graphics/vulkan/generated/spv-shaders-gen.h
dali/graphics/vulkan/scripts/shader-gen.sh
dali/graphics/vulkan/shaders/basic-shader.frag
dali/graphics/vulkan/shaders/basic-shader.vert
dali/graphics/vulkan/shaders/image-visual-shader.frag [new file with mode: 0644]
dali/graphics/vulkan/shaders/image-visual-shader.vert [new file with mode: 0644]
dali/graphics/vulkan/spirv/vulkan-spirv.cpp
dali/graphics/vulkan/vulkan-command-buffer.cpp
dali/graphics/vulkan/vulkan-command-buffer.h
dali/graphics/vulkan/vulkan-command-pool.cpp
dali/graphics/vulkan/vulkan-descriptor-set.h
dali/graphics/vulkan/vulkan-framebuffer.cpp
dali/graphics/vulkan/vulkan-graphics-controller.cpp
dali/graphics/vulkan/vulkan-graphics-controller.h
dali/graphics/vulkan/vulkan-graphics.cpp
dali/graphics/vulkan/vulkan-graphics.h
dali/graphics/vulkan/vulkan-pipeline-cache.cpp [new file with mode: 0644]
dali/graphics/vulkan/vulkan-pipeline-cache.h [new file with mode: 0644]
dali/graphics/vulkan/vulkan-pipeline.cpp
dali/graphics/vulkan/vulkan-shader.cpp
dali/graphics/vulkan/vulkan-shader.h
dali/internal/event/common/property-buffer-impl.cpp
dali/internal/render/data-providers/render-data-provider.h
dali/internal/render/renderers/render-geometry.cpp
dali/internal/render/renderers/render-geometry.h
dali/internal/render/renderers/render-property-buffer.cpp
dali/internal/render/renderers/render-property-buffer.h
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h
dali/internal/render/shaders/scene-graph-shader.cpp
dali/internal/render/shaders/scene-graph-shader.h
dali/internal/update/graphics/graphics-algorithms.cpp
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/internal/update/rendering/scene-graph-renderer.h

diff --git a/dali/graphics-api/graphics-api-buffer-factory.h b/dali/graphics-api/graphics-api-buffer-factory.h
new file mode 100644 (file)
index 0000000..497b088
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef DALI_GRAPHICS_API_BUFFER_FACTORY_H
+#define DALI_GRAPHICS_API_BUFFER_FACTORY_H
+
+/*
+ * Copyright (c) 2018 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/graphics-api/graphics-api-base-factory.h>
+#include <dali/graphics-api/graphics-api-buffer.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace API
+{
+class BufferFactory : public API::BaseFactory<API::Buffer>
+{
+public:
+
+  // not copyable
+  BufferFactory(const BufferFactory&) = delete;
+  BufferFactory& operator=(const BufferFactory&) = delete;
+
+  virtual ~BufferFactory() = default;
+
+  /**
+   * Sets usage of the buffer
+   * @param usage
+   * @return
+   */
+  virtual BufferFactory& SetUsage( Buffer::UsageHint usage ) = 0;
+
+  /**
+   * Sets size of the buffer
+   * @param size
+   * @return
+   */
+  virtual BufferFactory& SetSize( uint32_t size ) = 0;
+
+protected:
+
+  /// @brief default constructor
+  BufferFactory() = default;
+
+  // derived types should not be moved directly to prevent slicing
+  BufferFactory(BufferFactory&&) = default;
+  BufferFactory& operator=(BufferFactory&&) = default;
+};
+
+}
+}
+}
+
+#endif //DALI_GRAPHICS_API_BUFFER_FACTORY_H
index 8885a15..8a3c9da 100644 (file)
@@ -18,6 +18,8 @@
  *
  */
 
+#include <cstdint>
+
 namespace Dali
 {
 namespace Graphics
@@ -49,12 +51,15 @@ public:
 
   virtual ~Buffer() = default;
 
- // TODO: @todo GetHints
-  size_t GetSize() const;
-  void* GetData();
+
+  virtual void* Map() = 0;
+
+  virtual void Unmap() = 0;
+
+  virtual void Write( void* src, uint32_t srcSize, uint32_t dstOffset ) = 0;
 
 protected:
-  // derived types should not be moved direcly to prevent slicing
+  // derived types should not be moved directly to prevent slicing
   Buffer(Buffer&&) = default;
   Buffer& operator=(Buffer&&) = default;
 
index cd06dd4..c996efb 100644 (file)
@@ -34,6 +34,8 @@
 #include <dali/graphics-api/graphics-api-texture-factory.h>
 #include <dali/graphics-api/graphics-api-texture-set.h>
 #include <dali/graphics-api/graphics-api-texture.h>
+#include <dali/graphics-api/graphics-api-buffer.h>
+#include <dali/graphics-api/graphics-api-buffer-factory.h>
 #include <dali/graphics-api/utility/utility-builder.h>
 
 namespace Dali
@@ -75,6 +77,11 @@ public:
   /**
    * @brief Create a new object
    */
+  virtual Accessor<Buffer> CreateBuffer( const BaseFactory<Buffer>& factory ) = 0;
+
+  /**
+   * @brief Create a new object
+   */
   virtual Accessor<StaticBuffer> CreateStaticBuffer( const BaseFactory<StaticBuffer>& factory ) = 0;
 
   /**
@@ -105,6 +112,12 @@ public:
   virtual ShaderFactory& GetShaderFactory() const = 0;
 
   /**
+ * @brief Returns shader factory
+ * @return
+ */
+  virtual BufferFactory& GetBufferFactory() const = 0;
+
+  /**
    * @brief Create a buffer
    */
   template<typename T>
@@ -116,6 +129,18 @@ public:
   virtual void SubmitCommand( API::RenderCommand&& command ) = 0;
 
   /**
+   * @brief alAllocates render command ( depends on implementation );
+   * @return
+   */
+  virtual std::unique_ptr<API::RenderCommand> AllocateRenderCommand() = 0;
+
+  /**
+   * @brief Submits a list of commands
+   * @param commands
+   */
+  virtual void SubmitCommands( std::vector<API::RenderCommand*> commands ) = 0;
+
+  /**
    * @brief Mark the beginning of a frame
    */
   virtual void BeginFrame() = 0;
index 1f710d0..520319b 100644 (file)
@@ -31,6 +31,19 @@ namespace API
 class Framebuffer
 {
 public:
+
+  struct ClearColor
+  {
+    float r, g, b, a;
+  };
+
+  struct DepthStencilClearColor
+  {
+    uint32_t  stencil;
+    float     depth;
+  };
+
+public:
   // not copyable
   Framebuffer(const Framebuffer&) = delete;
   Framebuffer& operator=(const Framebuffer&) = delete;
index d46dfc4..ab81c21 100644 (file)
@@ -29,6 +29,8 @@
 #include <dali/graphics-api/utility/utility-strong-type.h>
 #include <dali/graphics-api/graphics-api-shader-details.h>
 #include <dali/graphics-api/graphics-api-accessor.h>
+#include <dali/graphics-api/graphics-api-framebuffer.h>
+#include <dali/graphics-api/graphics-api-buffer.h>
 
 namespace Dali
 {
@@ -38,20 +40,334 @@ namespace API
 {
 class Shader;
 class Texture;
-using PrimitiveCount = Utility::StrongType<size_t, struct PrimitiveCountTag>;
-using BufferInfo     = std::unique_ptr<GenericBufferBase>;
-using BufferList     = Utility::StrongType<std::vector<BufferInfo>, struct BufferListTag>;
-using ShaderList     = std::vector<Accessor<Shader>>;
-using TextureList    = std::vector<Accessor<Texture>>;
+class Buffer;
+class Sampler;
 
 /**
  * @brief Interface class for RenderCommand types in the graphics API.
  */
-class RenderCommand final
+class RenderCommand
 {
 public:
-  RenderCommand( PrimitiveCount primitiveCount, BufferList&& bufferList )
-  : mPrimitiveCount{primitiveCount}, mBufferList{std::move( bufferList )}
+
+  static constexpr uint32_t BINDING_INDEX_DONT_CARE { 0xffffffff };
+
+  enum class InputAttributeRate
+  {
+    PER_VERTEX,
+    PER_INSTANCE
+  };
+
+  enum class IndexType
+  {
+    INDEX_TYPE_UINT16,
+    INDEX_TYPE_UINT32,
+  };
+
+  enum class DrawType
+  {
+    UNDEFINED_DRAW,
+    VERTEX_DRAW,
+    INDEXED_DRAW,
+  };
+
+  /**
+   * Describes buffer attribute binding
+   */
+  struct VertexAttributeBufferBinding
+  {
+    VertexAttributeBufferBinding() = default;
+
+    Accessor<Buffer> buffer{ nullptr };
+    uint32_t location { 0u };
+    uint32_t offset { 0u };
+    uint32_t stride { 0u };
+    InputAttributeRate rate { InputAttributeRate::PER_VERTEX };
+
+    uint32_t binding { 0u };
+    void*    pNext{ nullptr };
+
+    VertexAttributeBufferBinding& SetBuffer( Accessor<Buffer> value )
+    {
+      buffer = value;
+      return *this;
+    }
+    VertexAttributeBufferBinding& SetLocation( uint32_t value )
+    {
+      location = value;
+      return *this;
+    }
+    VertexAttributeBufferBinding& SetOffset( uint32_t value )
+    {
+      offset = value;
+      return *this;
+    }
+    VertexAttributeBufferBinding& SetStride( uint32_t value )
+    {
+      stride = value;
+      return *this;
+    }
+    VertexAttributeBufferBinding& SetBinding( uint32_t value )
+    {
+      binding = value;
+      return *this;
+    }
+    VertexAttributeBufferBinding& SetInputAttributeRate( InputAttributeRate value)
+    {
+      rate = value;
+      return *this;
+    }
+  };
+
+  /**
+   * Structure describes uniform buffer binding
+   */
+  struct UniformBufferBinding
+  {
+    UniformBufferBinding() :
+    buffer( nullptr ), offset( 0u ), dataSize( 0u ), binding( 0u ) {}
+    Accessor<Buffer> buffer;
+    uint32_t offset;
+    uint32_t dataSize;
+    uint32_t binding;
+    void*    pNext{ nullptr };
+
+    UniformBufferBinding& SetBuffer( Accessor<Buffer> value )
+    {
+      buffer = value;
+      return *this;
+    }
+    UniformBufferBinding& SetOffset( uint32_t value )
+    {
+      offset = value;
+      return *this;
+    }
+    UniformBufferBinding& SetDataSize( uint32_t value )
+    {
+      dataSize = value;
+      return *this;
+    }
+    UniformBufferBinding& SetBinding( uint32_t value )
+    {
+      binding = value;
+      return *this;
+    }
+  };
+
+  /**
+   *
+   */
+  struct TextureBinding
+  {
+    Accessor<Texture> texture;
+    Accessor<Sampler> sampler;
+    uint32_t binding;
+    void*    pNext{ nullptr };
+    TextureBinding() : texture(nullptr), sampler( nullptr ), binding( 0u ) {}
+
+    TextureBinding& SetTexture( Accessor<Texture> value )
+    {
+      texture = value;
+      return *this;
+    }
+    TextureBinding& SetSampler( Accessor<Sampler> value )
+    {
+      sampler = value;
+      return *this;
+    }
+    TextureBinding& SetBinding( uint32_t value )
+    {
+      binding = value;
+      return *this;
+    }
+  };
+
+  /**
+   *
+   */
+  struct SamplerBinding
+  {
+    Accessor<Sampler> sampler;
+    uint32_t binding;
+    void*    pNext{ nullptr };
+    SamplerBinding& SetSampler( Accessor<Sampler> value )
+    {
+      sampler = value;
+      return *this;
+    }
+    SamplerBinding& SetBinding( uint32_t value )
+    {
+      binding = value;
+      return *this;
+    }
+  };
+
+  /**
+   *
+   */
+  struct IndexBufferBinding
+  {
+    Accessor<Buffer> buffer { nullptr };
+    uint32_t offset { 0u };
+    IndexType type { IndexType::INDEX_TYPE_UINT16 };
+    void*    pNext{ nullptr };
+    IndexBufferBinding() = default;
+
+    IndexBufferBinding& SetBuffer( Accessor<Buffer> value )
+    {
+      buffer = value;
+      return *this;
+    }
+
+    IndexBufferBinding& SetOffset( uint32_t value )
+    {
+      offset = value;
+      return *this;
+    }
+
+    IndexBufferBinding& SetType( IndexType value )
+    {
+      type = value;
+      return *this;
+    }
+  };
+
+  struct RenderTargetBinding
+  {
+    Accessor<Framebuffer>                 framebuffer { nullptr };
+    std::vector<Framebuffer::ClearColor>  clearColors {};
+    Framebuffer::DepthStencilClearColor   dsClearColor {};
+    void*    pNext{ nullptr };
+    RenderTargetBinding() = default;
+
+    RenderTargetBinding& SetFramebuffer( Accessor<Framebuffer> value )
+    {
+      framebuffer = value;
+      return *this;
+    }
+
+    RenderTargetBinding& SetClearColors( std::vector<Framebuffer::ClearColor>&& value )
+    {
+      clearColors = value;
+      return *this;
+    }
+
+    RenderTargetBinding& SetFramebuffer( Framebuffer::DepthStencilClearColor value )
+    {
+      dsClearColor = value;
+      return *this;
+    }
+  };
+
+  struct DrawCommand
+  {
+    DrawCommand() :
+     drawType( DrawType::UNDEFINED_DRAW ){}
+    DrawType drawType;
+    union
+    {
+      uint32_t firstVertex;
+      uint32_t firstIndex;
+    };
+    union
+    {
+      uint32_t vertexCount;
+      uint32_t indicesCount;
+    };
+    uint32_t firstInstance;
+    uint32_t instanceCount;
+    void*    pNext{ nullptr };
+    DrawCommand& SetDrawType( DrawType value )
+    {
+      drawType = value;
+      return *this;
+    }
+    DrawCommand& SetFirstVertex( uint32_t value )
+    {
+      firstVertex = value;
+      return *this;
+    }
+    DrawCommand& SetFirstIndex( uint32_t value )
+    {
+      firstIndex = value;
+      return *this;
+    }
+    DrawCommand& SetVertexCount( uint32_t value )
+    {
+      vertexCount = value;
+      return *this;
+    }
+    DrawCommand& SetIndicesCount( uint32_t value )
+    {
+      indicesCount = value;
+      return *this;
+    }
+    DrawCommand& SetFirstInstance( uint32_t value )
+    {
+      firstInstance = value;
+      return *this;
+    }
+    DrawCommand& SetInstanceCount( uint32_t value )
+    {
+      instanceCount = value;
+      return *this;
+    }
+  };
+
+  /**
+   *
+   */
+  struct PushConstantsBinding
+  {
+    void*     data;
+    uint32_t  size;
+    uint32_t  binding;
+    void*    pNext{ nullptr };
+    PushConstantsBinding() = default;
+
+    PushConstantsBinding& SetData( void* value )
+    {
+      data = value;
+      return *this;
+    }
+    PushConstantsBinding& SetSize( uint32_t value )
+    {
+      size = value;
+      return *this;
+    }
+    PushConstantsBinding& SetBinding( uint32_t value )
+    {
+      binding = value;
+      return *this;
+    }
+  };
+
+  /**
+   *
+   */
+  struct RenderState
+  {
+    RenderState() = default;
+
+    Accessor<Shader> shader { nullptr };
+
+    RenderState& SetShader( Accessor<Shader> value )
+    {
+      shader = value;
+      return *this;
+    }
+    void*    pNext{ nullptr };
+  };
+
+  RenderCommand()
+  : mVertexBufferBindings(),
+    mUniformBufferBindings(),
+    mTextureBindings(),
+    mIndexBufferBinding(),
+    mRenderTargetBinding(),
+    mDrawCommand(),
+    mPushConstantsBindings(),
+    mRenderState()
   {
   }
 
@@ -63,67 +379,141 @@ public:
   RenderCommand( const RenderCommand& ) = delete;
   RenderCommand& operator=( const RenderCommand& ) = delete;
 
-  ~RenderCommand() = default;
+  virtual ~RenderCommand() = default;
 
-  PrimitiveCount GetPrimitiveCount() const
+  /**
+   * Resource binding API
+   */
+  RenderCommand& BindVertexBuffers( std::vector<VertexAttributeBufferBinding>&& bindings )
   {
-    return mPrimitiveCount;
+    mVertexBufferBindings = std::move( bindings );
+    return *this;
   }
 
-  const BufferList& GetBufferList() const
+  RenderCommand& BindUniformBuffers( std::vector<UniformBufferBinding>&& bindings )
   {
-    return mBufferList;
+    mUniformBufferBindings = std::move( bindings );
+    return *this;
   }
 
-  const auto& GetTextures() const
+  RenderCommand& BindTextures( std::vector<TextureBinding>&& bindings )
   {
-    return mTextureList;
+    mTextureBindings = std::move( bindings );
+    return *this;
   }
 
-  Accessor<Shader> GetShader( ShaderDetails::PipelineStage shaderStage ) const
+  RenderCommand& BindSamplers( std::vector<SamplerBinding>&& bindings )
   {
-    using ShaderDetails::PipelineStage;
+    mSamplerBindings = std::move( bindings );
+    return *this;
+  }
 
-    auto retval = Accessor<Shader>{nullptr};
+  RenderCommand& PushConstants( std::vector<PushConstantsBinding>&& bindings )
+  {
+    mPushConstantsBindings = bindings;
+    return *this;
+  }
 
-    size_t index = mShaders.size();
-    switch( shaderStage )
-    {
-      case PipelineStage::VERTEX:
-      {
-        index = 0;
-        break;
-      }
-      case PipelineStage::FRAGMENT:
-      {
-        index = 1;
-        break;
-      }
-      case PipelineStage::GEOMETRY:
-      case PipelineStage::COMPUTE:
-      case PipelineStage::TESSELATION_CONTROL:
-      case PipelineStage::TESSELATION_EVALUATION:
-      {
-        break;
-      }
-    }
-    if(index < mShaders.size())
-    {
-      retval = mShaders[index];
-    }
+  RenderCommand& BindRenderState( RenderState&& renderState )
+  {
+    mRenderState = renderState;
+    return *this;
+  }
+
+  RenderCommand& Draw( DrawCommand&& drawCommand )
+  {
+    mDrawCommand = drawCommand;
+    return *this;
+  }
+
+  static std::vector<VertexAttributeBufferBinding> NewVertexAttributeBufferBindings()
+  {
+    return std::vector<VertexAttributeBufferBinding>{};
+  }
+
+  /**
+   * Makes a copy ( or moves ) all bindings from the source array
+   * @param bindings
+   * @return
+   */
+  static std::vector<VertexAttributeBufferBinding> NewVertexAttributeBufferBindings( std::vector<VertexAttributeBufferBinding>&& bindings )
+  {
+    return std::vector<VertexAttributeBufferBinding>{ std::move(bindings) };
+  }
+
+  static std::vector<VertexAttributeBufferBinding> NewVertexAttributeBufferBindings( const std::vector<VertexAttributeBufferBinding>& bindings )
+  {
+    return std::vector<VertexAttributeBufferBinding>{ bindings };
+  }
+
+  static std::vector<TextureBinding> NewTextureBindings()
+  {
+    return std::vector<TextureBinding>{};
+  }
+
+  static std::vector<PushConstantsBinding> NewPushConstantsBindings( uint32_t count )
+  {
+    auto retval = std::vector<PushConstantsBinding>{};
+    retval.resize( count );
     return retval;
   }
 
+  // Getters
+  const std::vector<VertexAttributeBufferBinding>& GetVertexBufferBindings() const
+  {
+    return mVertexBufferBindings;
+  }
+
+  const auto& GetUniformBufferBindings() const
+  {
+    return mUniformBufferBindings;
+  }
+
+  const std::vector<TextureBinding>& GetTextureBindings() const
+  {
+    return mTextureBindings;
+  }
+
+  const auto& GetIndexBufferBinding() const
+  {
+    return mIndexBufferBinding;
+  }
+
+  const auto& GetRenderTargetBinding() const
+  {
+    return mRenderTargetBinding;
+  }
+
+  const DrawCommand& GetDrawCommand() const
+  {
+    return mDrawCommand;
+  }
+
+  const std::vector<PushConstantsBinding>& GetPushConstantsBindings() const
+  {
+    return mPushConstantsBindings;
+  }
+
+  const RenderState& GetRenderState() const
+  {
+    return mRenderState;
+  }
+
+protected:
 
+  std::vector<VertexAttributeBufferBinding> mVertexBufferBindings;
+  std::vector<UniformBufferBinding>         mUniformBufferBindings;
+  std::vector<TextureBinding>               mTextureBindings;
+  std::vector<SamplerBinding>               mSamplerBindings;
+  IndexBufferBinding                        mIndexBufferBinding;
+  RenderTargetBinding                       mRenderTargetBinding;
+  DrawCommand                               mDrawCommand;
+  std::vector<PushConstantsBinding>         mPushConstantsBindings;
+  RenderState                               mRenderState;
 
-private:
-  PrimitiveCount mPrimitiveCount;
-  BufferList     mBufferList;
-  TextureList    mTextureList;
-  ShaderList     mShaders;
 };
 
-using RenderCommandBuilder = Utility::Builder<RenderCommand, PrimitiveCount, BufferList>;
+using RenderCommandBuilder = Utility::Builder<RenderCommand>;
 
 } // namespace API
 } // namespace Graphics
index 984577a..7060fb6 100644 (file)
@@ -30,6 +30,8 @@ namespace API
 namespace ShaderDetails
 {
 
+constexpr uint32_t ERROR_VERTEX_INPUT_ATTRIBUTE_NOT_FOUND( -1u );
+
 enum class ShaderSourceType
 {
   STRING,
@@ -99,6 +101,19 @@ struct ShaderSource
     return true;
   }
 
+  bool operator==(const ShaderSource& rhs ) const
+  {
+    if( type == ShaderSourceType::BINARY )
+    {
+      return code == rhs.code;
+    }
+    else
+    {
+      return source == rhs.source;
+    }
+    return false;
+  }
+
   std::string       source;
   std::vector<char> code;
   ShaderSourceType type;
@@ -121,6 +136,44 @@ enum class PipelineStage {
   TESSELATION_EVALUATION,
 };
 
+enum class VertexInputAttributeFormat
+{
+  UNDEFINED,
+  FLOAT,
+  INTEGER,
+  VEC2,
+  VEC3,
+  VEC4
+};
+
+enum class UniformClass
+{
+  SAMPLER,
+  IMAGE,
+  COMBINED_IMAGE_SAMPLER,
+  UNIFORM_BUFFER,
+  UNDEFINED
+};
+
+struct UniformInfo
+{
+  std::string   name{""};
+  UniformClass  uniformClass{ UniformClass::UNDEFINED };
+  uint32_t      binding { 0u };
+  uint32_t      bufferIndex { 0u };
+  uint32_t      offset { 0u };
+  uint32_t      location { 0u };
+};
+
+struct UniformBlockInfo
+{
+  std::string name {""};
+  uint32_t    descriptorSet {0u};
+  uint32_t    binding {0u};
+  uint32_t    size {0u};
+  std::vector<UniformInfo> members {};
+};
+
 } // namespace TextureDetails
 } // namespace API
 } // namespace Graphics
index 5e93086..ccfbb2c 100644 (file)
  *
  */
 
+#include <dali/graphics-api/graphics-api-shader-details.h>
+
+#include <cstdint>
+#include <string>
+
 namespace Dali
 {
 namespace Graphics
@@ -32,11 +37,58 @@ class Shader
 {
 public:
   // not copyable
-  Shader(const Shader&) = delete;
-  Shader& operator=(const Shader&) = delete;
+  Shader(const Shader &) = delete;
+  Shader &operator=(const Shader &) = delete;
 
   virtual ~Shader() = default;
 
+  // Reflection, optional, may be not supported
+  virtual bool IsReflectionSupported() const = 0;
+
+  virtual uint32_t GetVertexAttributeLocation(const std::string &name) const
+  {
+    return 0;
+  }
+
+  virtual ShaderDetails::VertexInputAttributeFormat GetVertexAttributeFormat( uint32_t location ) const
+  {
+    return ShaderDetails::VertexInputAttributeFormat::UNDEFINED;
+  }
+
+  virtual std::string GetVertexAttributeName(uint32_t location) const
+  {
+    return {};
+  }
+
+  virtual std::vector<uint32_t> GetVertexAttributeLocations() const
+  {
+    return {};
+  }
+
+  virtual std::vector<ShaderDetails::UniformInfo> GetSamplers() const
+  {
+    return {};
+  }
+
+  virtual bool GetNamedUniform( const std::string& name, ShaderDetails::UniformInfo& out ) const
+  {
+    return false;
+  }
+
+  /**
+   * Returns number of uniform blocks from all the shaders
+   * @return
+   */
+  virtual uint32_t GetUniformBlockCount() const
+  {
+    return 0u;
+  }
+
+  virtual bool GetUniformBlock( uint32_t index, ShaderDetails::UniformBlockInfo& out ) const
+  {
+    return false;
+  }
+
 protected:
   // derived types should not be moved direcly to prevent slicing
   Shader(Shader&&) = default;
diff --git a/dali/graphics-api/utility/utility-memory-pool.h b/dali/graphics-api/utility/utility-memory-pool.h
new file mode 100644 (file)
index 0000000..2758cbd
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef DALI_VULKAN_161117_UTILITY_MEMORY_POOL_H
+#define DALI_VULKAN_161117_UTILITY_MEMORY_POOL_H
+
+#include <cstdint>
+#include <cstdlib>
+#include <vector>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Utility
+{
+class MemoryPool
+{
+public:
+  static const auto ALIGNMENT = 16u;
+
+  MemoryPool( uint32_t capacity, bool isFixed = false )
+  : mPageCapacity( capacity ),
+    mCapacity( 0 ),
+    mMarkedPageIndex( 0 ),
+    mMarkedOffset( 0 ),
+    mMarkedAllocationSize( 0 ),
+    mMarkedAllocationCount( 0 ),
+    mPageOffset( 0 ),
+    mPageIndex( 0 ),
+    mPages(),
+    mTotalPoolCapacity( 0 ),
+    mTotalPoolAllocationsSize( 0 ),
+    mTotalPoolAllocations( 0 ),
+    mIsFixed( isFixed )
+  {
+  }
+
+  ~MemoryPool()
+  {
+    if( !mPages.empty() )
+    {
+      mPages.clear();
+    }
+  }
+
+  void Mark()
+  {
+    mMarkedOffset          = mPageOffset;
+    mMarkedPageIndex       = mPageIndex;
+    mMarkedAllocationCount = mTotalPoolAllocations;
+    mMarkedAllocationSize  = mTotalPoolAllocationsSize;
+  }
+
+  void Rollback()
+  {
+    mPageOffset               = mMarkedOffset;
+    mPageIndex                = mMarkedPageIndex;
+    mTotalPoolAllocationsSize = mMarkedAllocationSize;
+    mTotalPoolAllocations     = mMarkedAllocationCount;
+  }
+
+  void RollbackAll()
+  {
+    mPageOffset               = 0;
+    mPageIndex                = 0;
+    mTotalPoolAllocationsSize = 0;
+    mTotalPoolAllocations     = 0;
+  }
+
+  void* Allocate( uint32_t size, uint32_t aligned = ALIGNMENT )
+  {
+    // if allocated size is more that page capacity, add a page of required size
+    if( size > mPageCapacity )
+    {
+      AddPage( size + ( aligned * 2 ) );
+    }
+    else if( mPageCapacity <= mPageOffset + size + aligned )
+    {
+      AddPage( mPageCapacity );
+    }
+
+    mPageOffset = ( ( mPageOffset + aligned ) / aligned ) * aligned;
+    auto retval = &mPages[mPageIndex].data[mPageOffset];
+    mPageOffset += size + aligned;
+
+    mTotalPoolAllocations++;
+    mTotalPoolAllocationsSize += size;
+
+    return retval;
+  }
+
+  template<class T, class... Args>
+  T* AllocateNew( Args... args )
+  {
+    return new( Allocate( sizeof( T ), ALIGNMENT ) ) T( args... );
+  }
+
+  template<class T>
+  T* Allocate( uint32_t elements )
+  {
+    return new( Allocate( sizeof( T ) * elements ) ) T[elements];
+  }
+
+  /**
+   * Trims unused memory
+   */
+  void Trim()
+  {
+    if( mPageIndex < mPages.size() - 1 )
+    {
+      mPages.resize( mPageIndex + 1 );
+    }
+  }
+
+private:
+  void AddPage( uint32_t pageCapacity )
+  {
+    mPages.emplace_back( pageCapacity );
+    mPageIndex  = uint32_t( mPages.size() - 1u );
+    mPageOffset = 0u;
+    mTotalPoolCapacity += pageCapacity;
+  }
+
+public:
+  //private:
+
+  struct Page
+  {
+    Page() = default;
+    Page( uint32_t _capacity ) : data( nullptr ), capacity( _capacity )
+    {
+    }
+
+    ~Page()
+    {
+      if( data )
+      {
+        free(data);
+      }
+    }
+    char*    data { nullptr };
+    uint32_t capacity { 0u };
+  };
+
+  uint32_t mPageCapacity;
+  uint32_t mCapacity;
+
+  uint32_t mMarkedPageIndex;
+  uint32_t mMarkedOffset;
+  uint32_t mMarkedAllocationSize;
+  uint32_t mMarkedAllocationCount;
+
+  uint32_t mPageOffset;
+  uint32_t mPageIndex;
+
+  std::vector<Page> mPages;
+
+  uint32_t mTotalPoolCapacity;
+  uint32_t mTotalPoolAllocationsSize;
+  uint32_t mTotalPoolAllocations;
+
+  bool mIsFixed;
+};
+} // namespace Utility
+} // namespace Graphics
+} // namespace Dali
+
+#endif //DALI_VULKAN_161117_UTILITY_MEMORY_POOL_H
index bd90075..6eb7ab6 100644 (file)
@@ -13,6 +13,7 @@ graphics_src_files = \
     $(graphics_src_dir)/vulkan/vulkan-image.cpp \
     $(graphics_src_dir)/vulkan/vulkan-command-buffer.cpp \
     $(graphics_src_dir)/vulkan/vulkan-pipeline.cpp \
+    $(graphics_src_dir)/vulkan/vulkan-pipeline-cache.cpp \
     $(graphics_src_dir)/vulkan/vulkan-buffer.cpp \
     $(graphics_src_dir)/vulkan/vulkan-graphics.cpp \
     $(graphics_src_dir)/vulkan/vulkan-shader.cpp \
@@ -22,8 +23,13 @@ graphics_src_files = \
     $(graphics_src_dir)/vulkan/vulkan-graphics-texture.cpp \
     $(graphics_src_dir)/vulkan/api/vulkan-api-shader.cpp \
     $(graphics_src_dir)/vulkan/api/vulkan-api-texture.cpp \
+    $(graphics_src_dir)/vulkan/api/vulkan-api-buffer.cpp \
+    $(graphics_src_dir)/vulkan/api/vulkan-api-buffer-factory.cpp \
     $(graphics_src_dir)/vulkan/api/vulkan-api-texture-factory.cpp \
     $(graphics_src_dir)/vulkan/api/vulkan-api-shader-factory.cpp \
+    $(graphics_src_dir)/vulkan/api/vulkan-api-render-command.cpp \
+    $(graphics_src_dir)/vulkan/api/internal/vulkan-ubo-manager.cpp \
+    $(graphics_src_dir)/vulkan/api/internal/vulkan-ubo-pool.cpp \
     $(graphics_src_dir)/vulkan/spirv/vulkan-spirv.cpp \
     $(graphics_src_dir)/graphics-controller.cpp
 
diff --git a/dali/graphics/vulkan/api/internal/vulkan-ubo-manager.cpp b/dali/graphics/vulkan/api/internal/vulkan-ubo-manager.cpp
new file mode 100644 (file)
index 0000000..fc4c698
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018 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/vulkan/api/internal/vulkan-ubo-manager.h>
+#include <dali/graphics/vulkan/api/internal/vulkan-ubo-pool.h>
+
+#include <unordered_map>
+
+#define debug( x ) std::cout << x << std::endl;
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace VulkanAPI
+{
+
+
+struct UboManager::Impl
+{
+  explicit Impl( UboManager& uboManager, Controller& controller )
+  : mUboManager( uboManager ),
+    mController( controller )
+  {
+    Initialise();
+  }
+
+  ~Impl() = default;
+
+  void Initialise()
+  {
+    // populate pools
+    mPools.emplace( 64, std::make_unique<UboPool>( mController, 64, 64 ) );
+    mPools.emplace( 128, std::make_unique<UboPool>( mController, 128, 64 ) );
+    mPools.emplace( 256, std::make_unique<UboPool>( mController, 256, 64 ) );
+    mPools.emplace( 512, std::make_unique<UboPool>( mController, 512, 64 ) );
+    mPools.emplace( 1024, std::make_unique<UboPool>( mController, 1024, 64 ) );
+  }
+
+  /**
+   * Allocates memory within pool space choosing proper allocation size
+   * @param uboSize
+   * @return
+   */
+  std::unique_ptr<Ubo> Allocate( uint32_t uboSize )
+  {
+    UboPool* uboPool { nullptr };
+    for( auto&& pool : mPools )
+    {
+      if( uboSize < pool.first )
+      {
+        uboPool = &*pool.second;
+        break;
+      }
+    }
+    if(!uboPool)
+    {
+      return nullptr;
+    }
+
+    return uboPool->Allocate( uboSize );
+  }
+
+  /**
+   * Maps all UBO buffers for writing
+   * @note this should happen when frame begins
+   */
+  void MapAllBuffers()
+  {
+    for( auto&& pool : mPools )
+    {
+      pool.second->Map();
+    }
+  }
+
+  /**
+   * Unmaps all buffers and flushes memory
+   * @note this should happen when frame ends
+   */
+  void UnmapAllBuffers()
+  {
+    for( auto&& pool : mPools )
+    {
+      pool.second->Unmap();
+    }
+  }
+
+
+  UboManager& mUboManager;
+  Controller& mController;
+
+  std::unordered_map<uint32_t, std::unique_ptr<UboPool>> mPools;
+};
+
+//
+
+UboManager::UboManager(Controller& controller)
+{
+  mImpl = std::make_unique<Impl>( *this, controller );
+}
+
+UboManager::~UboManager() = default;
+
+std::unique_ptr<Ubo> UboManager::Allocate( uint32_t size )
+{
+  return mImpl->Allocate( size );
+}
+
+void UboManager::MapAllBuffers()
+{
+  mImpl->MapAllBuffers();
+}
+
+void UboManager::UnmapAllBuffers()
+{
+  mImpl->UnmapAllBuffers();
+}
+
+
+}
+}
+}
+
diff --git a/dali/graphics/vulkan/api/internal/vulkan-ubo-manager.h b/dali/graphics/vulkan/api/internal/vulkan-ubo-manager.h
new file mode 100644 (file)
index 0000000..ad58277
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef DALI_VULKAN_API_VULKAN_UBO_MANAGER_H
+#define DALI_VULKAN_API_VULKAN_UBO_MANAGER_H
+
+/*
+ * Copyright (c) 2018 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 <memory>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class Controller;
+}
+namespace VulkanAPI
+{
+using Controller = Vulkan::Controller;
+class Ubo;
+
+
+class UboManager
+{
+public:
+
+  explicit UboManager( Controller& controller );
+  ~UboManager();
+
+  /** Allocates UBO of specified size
+   *
+   * @param size
+   * @return
+   */
+  std::unique_ptr<Ubo> Allocate( uint32_t size );
+
+  /**
+   * Maps all buffers within all pools
+   */
+  void MapAllBuffers();
+
+  /**
+   * Unmaps all buffers
+   */
+  void UnmapAllBuffers();
+
+private:
+
+  struct Impl;
+  std::unique_ptr<Impl> mImpl;
+};
+
+
+}
+}
+}
+#endif //DALI_VULKAN_API_VULKAN_UBO_MANAGER_H
\ No newline at end of file
diff --git a/dali/graphics/vulkan/api/internal/vulkan-ubo-pool.cpp b/dali/graphics/vulkan/api/internal/vulkan-ubo-pool.cpp
new file mode 100644 (file)
index 0000000..b147db5
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2018 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/vulkan/api/internal/vulkan-ubo-pool.h>
+#include <dali/graphics/vulkan/vulkan-graphics.h>
+#include <dali/graphics/vulkan/vulkan-buffer.h>
+#include <dali/graphics/vulkan/vulkan-graphics-controller.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-allocator.h>
+
+#include <deque>
+#include <iostream>
+
+#define debug( x ) std::cout << x << std::endl;
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace VulkanAPI
+{
+
+struct UboAllocationInfo
+{
+  uint32_t heapIndex;
+  uint32_t allocationIndex;
+  uint32_t allocationSize;
+  uint32_t allocationOffset;
+  uint32_t requestedSize;
+  uint32_t pageSize;
+};
+
+struct Ubo::Impl
+{
+  Impl( Ubo& ubo,
+        UboPool& pool,
+        UboAllocationInfo& allocationInfo
+  )
+    : mUbo( ubo ),
+      mPool( pool ),
+      mAllocationInfo( allocationInfo )
+  {
+  }
+
+  ~Impl()
+  {
+    mPool.Release(mUbo);
+  }
+
+  uint32_t Write( const void* data, uint32_t offset, uint32_t size )
+  {
+    bool alreadyMapped = mPool.IsMapped( mUbo );
+    void* ptr = mPool.Map( mUbo );
+    memcpy( ptr, reinterpret_cast<const char*>(data)+offset, size );
+
+    // cleanup
+    if( !alreadyMapped )
+    {
+      mPool.Unmap(mUbo);
+    }
+
+    return size;
+  }
+
+  uint32_t WriteKeepMapped( const void* data, uint32_t offset, uint32_t size )
+  {
+    void* ptr = mPool.Map( mUbo );
+    debug( "[UBO] Writing " << size << " bytes into: " << ptr );
+    memcpy( ptr, reinterpret_cast<const char*>(data)+offset, size );
+    return size;
+  }
+
+  Vulkan::BufferRef GetBuffer() const
+  {
+    return mPool.GetBuffer( mUbo );
+  }
+
+  uint32_t GetBindingOffset() const
+  {
+    return mAllocationInfo.allocationOffset;
+  }
+
+  uint32_t GetBindingSize() const
+  {
+    return mAllocationInfo.allocationSize;
+  }
+
+  Ubo&     mUbo;
+  UboPool& mPool;
+  UboAllocationInfo mAllocationInfo;
+
+};
+
+struct UboPool::Impl
+{
+  struct PoolBuffer
+  {
+    explicit PoolBuffer( Vulkan::BufferRef buf ) :
+    mappedPtr( nullptr ), buffer( buf ) {}
+    ~PoolBuffer() = default;
+
+    void* mappedPtr;
+    Vulkan::BufferRef buffer;
+  };
+
+  explicit Impl( UboPool& uboPool, Controller& controller, uint32_t blockSize, uint32_t initialCapacity )
+  : mUboPool( uboPool ),
+    mController( controller ),
+    mBlockSize( blockSize ),
+    mInitialCapacity( initialCapacity )
+  {
+
+  }
+
+  ~Impl() = default;
+
+  std::unique_ptr<Ubo> Allocate( uint32_t requestedSize )
+  {
+    if( mAllocationQueue.empty() )
+    {
+      NewUboBuffer();
+    }
+
+    uint32_t allocationIndex = mAllocationQueue.back();
+    mAllocationQueue.pop_back();
+    uint32_t heapIndex = allocationIndex / mInitialCapacity;
+
+    debug("[POOL] Allocated block size " << mBlockSize << ", index: " << allocationIndex);
+
+    auto allocationIndexInPage = uint32_t(allocationIndex % mInitialCapacity);
+
+    auto allocationInfo = UboAllocationInfo{};
+    allocationInfo.allocationIndex = allocationIndex;
+    allocationInfo.allocationOffset = allocationIndexInPage*mBlockSize;
+    allocationInfo.allocationSize = requestedSize;
+    allocationInfo.pageSize = mBlockSize;
+    allocationInfo.heapIndex = heapIndex;
+    return std::make_unique<Ubo>( mUboPool, allocationInfo );
+  }
+
+  void Release( Ubo& ubo )
+  {
+    auto& uboImpl = ubo.GetImplementation();
+    if( &uboImpl.mPool != &mUboPool )
+    {
+      return;
+    }
+
+    // return to pool
+    mAllocationQueue.push_back( uboImpl.mAllocationInfo.allocationIndex );
+  }
+
+  void NewUboBuffer()
+  {
+    debug("[POOL] Allocating new page of block size " << mBlockSize << ", capacity: " << mInitialCapacity);
+    // add new Vulkan Buffer object
+    auto& graphics = mController.GetGraphics();
+    mBuffers.emplace_back( Vulkan::Buffer::New( graphics, vk::BufferCreateInfo{}
+                                      .setUsage( vk::BufferUsageFlagBits::eUniformBuffer)
+                                      .setSharingMode( vk::SharingMode::eExclusive )
+                                      .setSize( mBlockSize * mInitialCapacity ) ) );
+    mBuffers.back().buffer->BindMemory(
+              graphics.GetDeviceMemoryManager().GetDefaultAllocator().Allocate( mBuffers.back().buffer, vk::MemoryPropertyFlagBits::eHostVisible )
+    );
+
+
+    auto startIndex = ((mBuffers.size()-1)*mInitialCapacity);
+    for( uint32_t i = 0u; i < mInitialCapacity; ++i )
+    {
+      mAllocationQueue.push_back( uint32_t(startIndex + i));
+    }
+  }
+
+  void* Map( Ubo& ubo )
+  {
+    auto& impl = ubo.GetImplementation();
+    auto bufferIndex = uint32_t(impl.mAllocationInfo.allocationIndex / mInitialCapacity);
+    auto allocationIndex = uint32_t(impl.mAllocationInfo.allocationIndex % mInitialCapacity);
+
+    debug("[POOL] Mapping UBO = alloc_index = " << impl.mAllocationInfo.allocationIndex);
+
+    return MapBuffer<char>( bufferIndex ) + (allocationIndex*mBlockSize);
+  }
+
+  template<class T>
+  T* MapBuffer( uint32_t bufferIndex )
+  {
+    if( !mBuffers[bufferIndex].mappedPtr )
+    {
+      debug("[POOL] Mapping PAGE = " << bufferIndex);
+      mBuffers[bufferIndex].mappedPtr = mBuffers[bufferIndex].buffer->GetMemoryHandle()->Map();
+    }
+
+    return reinterpret_cast<T*>(mBuffers[bufferIndex].mappedPtr);
+  }
+
+  void UnmapBuffer( uint32_t bufferIndex )
+  {
+    if( mBuffers[bufferIndex].mappedPtr )
+    {
+      debug("[POOL] Unmapping PAGE = " << bufferIndex);
+      mBuffers[bufferIndex].buffer->GetMemoryHandle()->Unmap();
+      mBuffers[bufferIndex].mappedPtr = nullptr;
+    }
+  }
+
+  void Unmap( Ubo& ubo )
+  {
+    auto& impl = ubo.GetImplementation();
+    debug("[POOL] Mapping UBO = alloc[" << impl.mAllocationInfo.allocationIndex);
+    auto bufferIndex = uint32_t(impl.mAllocationInfo.allocationIndex / mInitialCapacity);
+    UnmapBuffer( bufferIndex );
+  }
+
+  bool IsMapped( Ubo& ubo )
+  {
+    auto& impl = ubo.GetImplementation();
+    auto bufferIndex = uint32_t(impl.mAllocationInfo.allocationIndex / mInitialCapacity);
+    return (nullptr != mBuffers[bufferIndex].mappedPtr);
+  }
+
+  Vulkan::BufferRef GetBuffer( Ubo& ubo ) const
+  {
+    auto& impl = ubo.GetImplementation();
+    auto bufferIndex = uint32_t(impl.mAllocationInfo.allocationIndex / mInitialCapacity);
+    return mBuffers[bufferIndex].buffer;
+  }
+
+  UboPool& mUboPool;
+  Controller& mController;
+  uint32_t mBlockSize;
+  uint32_t mInitialCapacity;
+
+  std::vector<PoolBuffer>         mBuffers;
+  std::deque<uint32_t>            mAllocationQueue;
+
+};
+
+UboPool::UboPool(Controller &controller, uint32_t blockSize, uint32_t initialCapacity )
+{
+  mImpl = std::make_unique<Impl>( *this, controller, blockSize, initialCapacity );
+}
+
+UboPool::~UboPool() = default;
+
+std::unique_ptr<Ubo> UboPool::Allocate( uint32_t requestedSize )
+{
+  return mImpl->Allocate( requestedSize );
+}
+
+void UboPool::Release( Ubo& ubo )
+{
+  mImpl->Release( ubo );
+}
+
+bool UboPool::IsMapped( Ubo& ubo )
+{
+  return mImpl->IsMapped( ubo );
+}
+
+Vulkan::BufferRef UboPool::GetBuffer( Ubo& ubo ) const
+{
+  return mImpl->GetBuffer( ubo );
+}
+
+void* UboPool::Map( Ubo& ubo )
+{
+  return mImpl->Map( ubo );
+}
+
+void UboPool::Unmap( Ubo& ubo )
+{
+  mImpl->Unmap( ubo );
+}
+
+void* UboPool::MapPage( uint32_t bufferIndex )
+{
+  return mImpl->MapBuffer<char>( bufferIndex );
+}
+
+void UboPool::UnmapPage( uint32_t bufferIndex )
+{
+  mImpl->UnmapBuffer( bufferIndex );
+}
+
+void UboPool::Map()
+{
+  for( auto i = 0u; i < mImpl->mBuffers.size(); ++i )
+  {
+    mImpl->MapBuffer<char>( i );
+  }
+}
+
+void UboPool::Unmap()
+{
+  for( auto i = 0u; i < mImpl->mBuffers.size(); ++i )
+  {
+    mImpl->UnmapBuffer( i );
+  }
+}
+
+Ubo::Ubo( UboPool& pool, UboAllocationInfo& allocationInfo )
+{
+  mImpl = std::make_unique<Impl>( *this, pool, allocationInfo );
+}
+
+Ubo::~Ubo() = default;
+
+uint32_t Ubo::Write( const void* data, uint32_t offset, uint32_t size )
+{
+  return mImpl->Write( data, offset, size );
+}
+
+uint32_t Ubo::WriteKeepMapped( const void* data, uint32_t offset, uint32_t size )
+{
+  return mImpl->WriteKeepMapped( data, offset, size );
+}
+
+Vulkan::BufferRef Ubo::GetBuffer() const
+{
+  return mImpl->GetBuffer();
+}
+
+uint32_t Ubo::GetBindingOffset() const
+{
+  return mImpl->GetBindingOffset();
+}
+
+uint32_t Ubo::GetBindingSize() const
+{
+  return mImpl->GetBindingSize();
+}
+
+Ubo::Impl& Ubo::GetImplementation()
+{
+  return *mImpl;
+}
+
+}
+}
+}
+
diff --git a/dali/graphics/vulkan/api/internal/vulkan-ubo-pool.h b/dali/graphics/vulkan/api/internal/vulkan-ubo-pool.h
new file mode 100644 (file)
index 0000000..ccc6e73
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef DALI_VULKAN_INTERNAL_VULKAN_UBO_POOL_H
+#define DALI_VULKAN_INTERNAL_VULKAN_UBO_POOL_H
+
+/*
+ * Copyright (c) 2018 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 <cstdint>
+#include <memory>
+#include <dali/graphics/vulkan/vulkan-buffer.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class Controller;
+}
+namespace VulkanAPI
+{
+using Controller = Vulkan::Controller;
+class Ubo;
+class UboPool
+{
+public:
+
+  explicit UboPool(Controller &controller, uint32_t blockSize, uint32_t initialCapacity );
+
+  ~UboPool();
+
+  /**
+   * Allocates memory within pool space for new UBO
+   * @return unique pointer to the UBO object
+   */
+  std::unique_ptr<Ubo> Allocate( uint32_t requestedSize );
+
+  /**
+   * Releases allocated memory back to the pool
+   * @param ubo
+   */
+  void Release( Ubo& ubo );
+
+  /**
+   * Maps UBO buffer memory into the user space
+   * @param ubo
+   * @return
+   */
+  void* Map( Ubo& ubo );
+
+  /**
+   * Unmaps UBO memory
+   */
+  void Unmap( Ubo& ubo );
+
+  /**
+   * Maps a single page in the pool
+   * @param bufferIndex
+   * @return
+   */
+  void* MapPage( uint32_t bufferIndex );
+
+
+  /**
+   * Unmaps a single page in the pool
+   * @param bufferIndex
+   * @return
+   */
+  void UnmapPage( uint32_t bufferIndex );
+
+  /**
+   * Maps all pages
+   * @param bufferIndex
+   * @return
+   */
+  void Map();
+
+  /**
+   * Unmaps all pages
+   * @param bufferIndex
+   * @return
+   */
+  void Unmap();
+
+  /**
+   *
+   * @param ubo
+   * @return
+   */
+  bool IsMapped( Ubo& ubo );
+
+  /**
+   * Returns Vulkan buffer associated with the UBO
+   * @param ubo
+   * @return
+   */
+  Vulkan::BufferRef GetBuffer( Ubo& ubo ) const;
+
+private:
+
+  struct Impl;
+  std::unique_ptr<Impl> mImpl;
+};
+
+/**
+ * Ubo is an opaque object
+ */
+struct Ubo
+{
+  explicit Ubo( UboPool& pool, struct UboAllocationInfo& allocationInfo );
+  ~Ubo();
+
+  /**
+   * Writes into UBO object memory. Maps and unmaps buffer. Not very efficient.
+   * @param data
+   * @param offset
+   * @param size
+   * @return
+   */
+  uint32_t Write( const void* data, uint32_t offset, uint32_t size );
+
+  /**
+   * Writes into the buffer memory, keeps it mapped
+   * @param data
+   * @param offset
+   * @param size
+   * @return
+   */
+  uint32_t WriteKeepMapped( const void* data, uint32_t offset, uint32_t size );
+
+  /**
+   * Returns buffer associated with the UBO
+   * @return
+   */
+  Vulkan::BufferRef GetBuffer() const;
+
+  /**
+   * Returns binding offset within Vulkan buffer object
+   * @return
+   */
+  uint32_t GetBindingOffset() const;
+
+  /**
+   * Return binding size within Vulkan buffer object
+   * @return
+   */
+  uint32_t GetBindingSize() const;
+
+
+
+  struct Impl;
+  std::unique_ptr<Impl> mImpl;
+  Impl& GetImplementation();
+};
+
+
+}
+}
+}
+
+#endif //DALI_VULKAN_INTERNAL_VULKAN_UBO_POOL_H
diff --git a/dali/graphics/vulkan/api/vulkan-api-buffer-factory.cpp b/dali/graphics/vulkan/api/vulkan-api-buffer-factory.cpp
new file mode 100644 (file)
index 0000000..b8e80fd
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018 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/vulkan/api/vulkan-api-buffer-factory.h>
+#include <dali/graphics/vulkan/api/vulkan-api-buffer.h>
+#include <dali/graphics/vulkan/vulkan-graphics.h>
+#include <dali/graphics/vulkan/vulkan-buffer.h>
+#include <dali/graphics/vulkan/vulkan-graphics-controller.h>
+namespace Dali
+{
+namespace Graphics
+{
+namespace VulkanAPI
+{
+BufferFactory::BufferFactory( Vulkan::Controller& controller )
+: mController( controller ), mGraphics(controller.GetGraphics() )
+{
+
+}
+
+BufferFactory& BufferFactory::SetUsage( API::Buffer::UsageHint usage )
+{
+  mUsageHints = usage;
+  switch( usage )
+  {
+    case API::Buffer::UsageHint::ATTRIBUTES:
+    {
+      mUsage = vk::BufferUsageFlagBits::eVertexBuffer;
+      break;
+    }
+    case API::Buffer::UsageHint::FRAME_CONSTANTS:
+    {
+      mUsage = vk::BufferUsageFlagBits::eUniformBuffer;
+      break;
+    }
+    case API::Buffer::UsageHint::INDEX_BUFFER:
+    {
+      mUsage = vk::BufferUsageFlagBits::eIndexBuffer;
+      break;
+    }
+    case API::Buffer::UsageHint::INSTANCE:
+    {
+      mUsage = vk::BufferUsageFlagBits::eVertexBuffer;
+      break;
+    }
+    case API::Buffer::UsageHint::PRIMITIVE_UNIFORMS:
+    {
+      mUsage = vk::BufferUsageFlagBits::eUniformBuffer;
+      break;
+    }
+  }
+  return *this;
+}
+
+BufferFactory& BufferFactory::SetSize( uint32_t size )
+{
+  mSize = size;
+  return *this;
+}
+
+std::unique_ptr<API::Buffer> BufferFactory::Create() const
+{
+  auto retval = std::make_unique<VulkanAPI::Buffer>( mController, mUsage, mUsageHints, mSize );
+  if( retval->Initialise() )
+  {
+    return std::unique_ptr<API::Buffer>{ retval.release() };
+  }
+  return nullptr;
+}
+
+
+
+} // namespace VulkanAPI
+} // namespace Graphics
+} // namespace Dali
\ No newline at end of file
diff --git a/dali/graphics/vulkan/api/vulkan-api-buffer-factory.h b/dali/graphics/vulkan/api/vulkan-api-buffer-factory.h
new file mode 100644 (file)
index 0000000..22bfcaa
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef DALI_GRAPHICS_VULKAN_API_BUFFER_FACTORY_H
+#define DALI_GRAPHICS_VULKAN_API_BUFFER_FACTORY_H
+
+/*
+ * Copyright (c) 2018 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-api-buffer-factory.h>
+#include <dali/graphics-api/graphics-api-buffer.h>
+#include <dali/graphics/vulkan/vulkan-types.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class Graphics;
+class Controller;
+}
+namespace VulkanAPI
+{
+class BufferFactory : public Dali::Graphics::API::BufferFactory
+{
+public:
+
+  explicit BufferFactory( Vulkan::Controller& controller );
+
+  VulkanAPI::BufferFactory& SetUsage( API::Buffer::UsageHint usage ) override;
+
+  VulkanAPI::BufferFactory& SetSize( uint32_t size ) override;
+
+  PointerType Create() const override;
+
+private:
+
+  Vulkan::Controller&         mController;
+  Vulkan::Graphics&           mGraphics;
+  vk::BufferUsageFlagBits     mUsage;
+  API::Buffer::UsageHint      mUsageHints;
+  uint32_t                    mSize;
+};
+
+} // namespace VulkanAPI
+} // namespace Graphics
+} // namespace Dali
+
+#endif // DALI_GRAPHICS_VULKAN_API_BUFFER_FACTORY_H
diff --git a/dali/graphics/vulkan/api/vulkan-api-buffer.cpp b/dali/graphics/vulkan/api/vulkan-api-buffer.cpp
new file mode 100644 (file)
index 0000000..080316b
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018 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/vulkan/api/vulkan-api-buffer.h>
+#include <dali/graphics/vulkan/vulkan-graphics.h>
+#include <dali/graphics/vulkan/vulkan-buffer.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-allocator.h>
+#include <dali/graphics/vulkan/gpu-memory/vulkan-gpu-memory-manager.h>
+#include <dali/graphics/vulkan/vulkan-graphics-controller.h>
+#include <memory>
+namespace Dali
+{
+namespace Graphics
+{
+namespace VulkanAPI
+{
+
+Buffer::Buffer( Vulkan::Controller& controller, vk::BufferUsageFlagBits usage, API::Buffer::UsageHint usageHints, uint32_t size )
+: mController( controller ), mGraphics( controller.GetGraphics() ), mUsageHints( usageHints ), mSize( size )
+{
+
+}
+
+bool Buffer::Initialise()
+{
+  auto type = Vulkan::Buffer::Type{};
+  if( mUsage == vk::BufferUsageFlagBits::eUniformBuffer )
+  {
+    type = Vulkan::Buffer::Type::UNIFORM;
+  }
+  else if( mUsage == vk::BufferUsageFlagBits::eIndexBuffer )
+  {
+    type = Vulkan::Buffer::Type::INDEX;
+  }
+  else if( mUsage == vk::BufferUsageFlagBits::eVertexBuffer )
+  {
+    type = Vulkan::Buffer::Type::VERTEX;
+  }
+  else
+  {
+    // unsupported usage
+    return false;
+  }
+
+  // create buffer
+  mBufferRef = Vulkan::Buffer::New( mGraphics, mSize, type );
+
+  // allocate memory
+  auto memory =
+    mGraphics.GetDeviceMemoryManager().GetDefaultAllocator().Allocate( mBufferRef,
+                      vk::MemoryPropertyFlagBits::eHostVisible ); // todo: host visible should be only for dynamic buffers
+  mBufferRef->BindMemory( memory );
+
+  return true;
+}
+
+void* Buffer::Map()
+{
+  return mBufferRef->GetMemoryHandle()->Map();
+}
+
+void Buffer::Unmap()
+{
+  mBufferRef->GetMemoryHandle()->Unmap();
+}
+
+void Buffer::Write( void* src, uint32_t srcSize, uint32_t dstOffset )
+{
+  // depends whether the buffer is host visible or device local
+  // TODO: implement in-GPU copying, for now all buffers are host-visible
+  auto transfer = std::make_unique<VulkanAPI::BufferMemoryTransfer>();
+  auto tmp = new char[srcSize];
+  memcpy( tmp, src, srcSize );
+  transfer->srcPtr.reset( tmp );
+  transfer->dstBuffer = mBufferRef;
+  transfer->dstOffset = dstOffset;
+  transfer->srcSize = srcSize;
+  mController.ScheduleBufferMemoryTransfer( std::move(transfer) );
+}
+
+Vulkan::BufferRef Buffer::GetBufferRef() const
+{
+  return mBufferRef;
+}
+
+}
+}
+}
diff --git a/dali/graphics/vulkan/api/vulkan-api-buffer.h b/dali/graphics/vulkan/api/vulkan-api-buffer.h
new file mode 100644 (file)
index 0000000..6428331
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef DALI_GRAPHICS_VULKAN_API_BUFFER_H
+#define DALI_GRAPHICS_VULKAN_API_BUFFER_H
+
+/*
+ * Copyright (c) 2018 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-api-buffer.h>
+#include <dali/graphics/vulkan/vulkan-types.h>
+
+#include <memory>
+
+
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class Controller;
+}
+namespace VulkanAPI
+{
+
+
+/**
+ * Buffer represents a Buffer-type resource
+ */
+class Buffer : public Graphics::API::Buffer
+{
+public:
+
+  explicit Buffer( Vulkan::Controller& controller, vk::BufferUsageFlagBits usage, API::Buffer::UsageHint usageHints, uint32_t size );
+
+  bool Initialise();
+
+  /**
+   * Maps buffer only when host visible or nullptr when device local
+   * @return
+   */
+  void* Map() override;
+
+  /**
+   * Unmaps previously accessed buffer
+   */
+  void Unmap() override;
+
+  /**
+   * Writes into the buffer
+   * @param src
+   * @param srcSize
+   * @param dstOffset
+   */
+  void Write( void* src, uint32_t srcSize, uint32_t dstOffset ) override;
+
+  Vulkan::BufferRef GetBufferRef() const;
+
+private:
+
+  Vulkan::Controller& mController;
+  Vulkan::Graphics& mGraphics;
+  vk::BufferUsageFlagBits mUsage{ vk::BufferUsageFlagBits::eVertexBuffer};
+  API::Buffer::UsageHint mUsageHints;
+  uint32_t mSize;
+
+  Vulkan::BufferRef mBufferRef;
+};
+}
+} // namespace Graphics
+} // namespace Dali
+#endif // DALI_GRAPHICS_VULKAN_API_BUFFER_H
diff --git a/dali/graphics/vulkan/api/vulkan-api-render-command.cpp b/dali/graphics/vulkan/api/vulkan-api-render-command.cpp
new file mode 100644 (file)
index 0000000..dd898a5
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2018 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/utility/utility-memory-pool.h>
+#include <dali/graphics/vulkan/api/vulkan-api-render-command.h>
+#include <dali/graphics/vulkan/api/vulkan-api-shader.h>
+#include <dali/graphics/vulkan/api/vulkan-api-texture.h>
+#include <dali/graphics/vulkan/spirv/vulkan-spirv.h>
+#include <dali/graphics/vulkan/vulkan-command-buffer.h>
+#include <dali/graphics/vulkan/vulkan-command-pool.h>
+#include <dali/graphics/vulkan/vulkan-graphics.h>
+#include <dali/graphics/vulkan/vulkan-buffer.h>
+#include <dali/graphics/vulkan/vulkan-pipeline-cache.h>
+#include <dali/graphics/vulkan/vulkan-pipeline.h>
+#include <dali/graphics/vulkan/vulkan-sampler.h>
+#include <dali/graphics/vulkan/vulkan-image.h>
+#include <dali/graphics/vulkan/vulkan-framebuffer.h>
+#include <dali/graphics/vulkan/vulkan-descriptor-set.h>
+#include <dali/graphics/vulkan/vulkan-swapchain.h>
+
+#include <dali/graphics/vulkan/api/internal/vulkan-ubo-manager.h>
+#include <dali/graphics/vulkan/api/internal/vulkan-ubo-pool.h>
+#include <dali/graphics/vulkan/vulkan-graphics-controller.h>
+
+#include <iostream>
+#define debug( x ) std::cout << x << std::endl;
+
+namespace Dali
+{
+namespace Graphics
+{
+using Vulkan::VkAssert;
+
+namespace VulkanAPI
+{
+
+struct RenderCommand::VulkanPipelineState
+{
+  VulkanPipelineState() = default;
+  ~VulkanPipelineState() = default;
+
+  vk::PipelineColorBlendStateCreateInfo              colorBlend;
+  std::vector<vk::PipelineColorBlendAttachmentState> colorBlendAttachmentState;
+
+  vk::PipelineDepthStencilStateCreateInfo   depthStencil;
+  vk::PipelineInputAssemblyStateCreateInfo  inputAssembly;
+  vk::PipelineMultisampleStateCreateInfo    multisample;
+  vk::PipelineRasterizationStateCreateInfo  rasterization;
+  vk::PipelineTessellationStateCreateInfo   tesselation;
+  vk::PipelineVertexInputStateCreateInfo    vertexInput;
+
+  struct ViewportState
+  {
+    vk::PipelineViewportStateCreateInfo createInfo;
+    std::vector<vk::Viewport>           viewports;
+    std::vector<vk::Rect2D>             scissors;
+  } viewport;
+};
+
+RenderCommand::~RenderCommand() = default;
+
+RenderCommand::RenderCommand( VulkanAPI::Controller& controller, Vulkan::Graphics& graphics, Vulkan::PipelineCache& pipelineCache )
+: mController( controller ), mGraphics( graphics ), mPipelineCache( pipelineCache ), mCommandBuffer(), mPipeline(), mUpdateFlags( UPDATE_ALL )
+{
+}
+
+///@todo: needs pipeline factory rather than pipeline creation in place!!!
+bool RenderCommand::PreparePipeline()
+{
+  if( mUpdateFlags )
+  {
+    auto &pipelineCache = mGraphics.GetPipelineCache();
+
+    const auto &renderState = GetRenderState();
+    const auto &shader      = static_cast<const VulkanAPI::Shader &>( renderState.shader
+                                                                                 .Get());
+
+    auto vertexShader   = shader.GetShader(vk::ShaderStageFlagBits::eVertex);
+    auto fragmentShader = shader.GetShader(vk::ShaderStageFlagBits::eFragment);
+
+    auto pipelineRef = pipelineCache.GetPipeline({vertexShader, fragmentShader, {}});
+
+    if (!pipelineRef)
+    {
+      // retrieve input attributes descriptions
+      std::vector<Vulkan::SpirV::SPIRVVertexInputAttribute> attribs{};
+      vertexShader->GetSPIRVReflection()
+                  .GetVertexInputAttributes(attribs);
+      std::vector<vk::VertexInputAttributeDescription> attributeDescriptions{};
+
+      // prepare vertex buffer bindings
+      auto                                           bindingIndex{0u};
+      std::vector<vk::VertexInputBindingDescription> bindingDescriptions{};
+
+      uint32_t  currentBuffer{0xffffffff};
+      for (auto &&vb : GetVertexBufferBindings())
+      {
+        if (currentBuffer != vb.buffer
+                               .GetHandle())
+        {
+          bindingDescriptions.emplace_back(vk::VertexInputBindingDescription{}
+                                             .setBinding(bindingIndex)
+                                             .setInputRate(vb.rate == API::RenderCommand::InputAttributeRate::PER_VERTEX
+                                                           ? vk::VertexInputRate::eVertex
+                                                           : vk::VertexInputRate::eInstance)
+                                             .setStride(vb.stride));
+          bindingIndex++;
+          currentBuffer = Vulkan::U32(vb.buffer
+                                        .GetHandle());
+        }
+
+        attributeDescriptions.emplace_back(vk::VertexInputAttributeDescription{}
+                                             .setBinding(bindingDescriptions.back()
+                                                                            .binding)
+                                             .setFormat(attribs[vb.location].format)
+                                             .setOffset(vb.offset));
+      }
+
+      auto vertexInputState = vk::PipelineVertexInputStateCreateInfo{}
+        .setVertexBindingDescriptionCount(Vulkan::U32(bindingDescriptions.size()))
+        .setPVertexBindingDescriptions(bindingDescriptions.data())
+        .setVertexAttributeDescriptionCount(Vulkan::U32(attributeDescriptions.size()))
+        .setPVertexAttributeDescriptions(attributeDescriptions.data());
+
+      // descriptor set layout
+      auto vshDsLayouts = vertexShader->GetSPIRVReflection()
+                                      .GenerateDescriptorSetLayoutCreateInfo();
+      auto fshDsLayouts = fragmentShader->GetSPIRVReflection()
+                                        .GenerateDescriptorSetLayoutCreateInfo();
+
+      decltype(vshDsLayouts) layouts;
+      layouts.resize(std::max(vshDsLayouts.size(), fshDsLayouts.size()));
+
+      std::vector<vk::DescriptorSetLayout> dsLayouts;
+
+      for (auto i = 0u; i < layouts.size(); ++i)
+      {
+        std::vector<vk::DescriptorSetLayoutBinding> dsBindings;
+
+        // concatenate bindings per set
+        if (vshDsLayouts[i].bindingCount)
+        {
+          dsBindings.insert(
+            dsBindings.end(), vshDsLayouts[i].pBindings, vshDsLayouts[i].pBindings + vshDsLayouts[i].bindingCount);
+        }
+        if (fshDsLayouts[i].bindingCount)
+        {
+          dsBindings.insert(
+            dsBindings.end(), fshDsLayouts[i].pBindings, fshDsLayouts[i].pBindings + fshDsLayouts[i].bindingCount);
+        }
+
+        layouts[i].pBindings    = dsBindings.data();
+        layouts[i].bindingCount = Vulkan::U32(dsBindings.size());
+
+
+        dsLayouts.emplace_back(VkAssert(mGraphics.GetDevice()
+                                                 .createDescriptorSetLayout(layouts[i], mGraphics.GetAllocator())));
+
+      }
+
+      // create layout
+      auto pipelineLayoutCreateInfo = vk::PipelineLayoutCreateInfo{}
+        .setSetLayoutCount(Vulkan::U32(dsLayouts.size()))
+        .setPSetLayouts(dsLayouts.data())
+        .setPPushConstantRanges(nullptr)
+        .setPushConstantRangeCount(0);
+
+      auto pipelineLayout = VkAssert(mGraphics.GetDevice()
+                                              .createPipelineLayout(pipelineLayoutCreateInfo,
+                                                                    mGraphics.GetAllocator()));
+
+      std::vector<vk::PipelineShaderStageCreateInfo> shaderStages =
+                                                       {
+                                                         vk::PipelineShaderStageCreateInfo{}
+                                                           .setModule(vertexShader->GetVkShaderModule())
+                                                           .setStage(vk::ShaderStageFlagBits::eVertex)
+                                                           .setPName("main"),
+                                                         vk::PipelineShaderStageCreateInfo{}
+                                                           .setModule(fragmentShader->GetVkShaderModule())
+                                                           .setStage(vk::ShaderStageFlagBits::eFragment)
+                                                           .setPName("main")
+                                                       };
+
+      mVulkanPipelineState = std::make_unique<VulkanPipelineState>();
+
+      // @todo use RenderTarget
+      auto                           swapchain = mGraphics.GetSwapchainForFBID(0);
+      auto                           fb        = swapchain->GetCurrentFramebuffer();
+      vk::GraphicsPipelineCreateInfo pipelineInfo;
+      pipelineInfo
+        .setSubpass(0)
+        .setRenderPass(fb->GetVkRenderPass()) // based on render target
+        .setBasePipelineHandle(nullptr)
+        .setBasePipelineIndex(0)
+        .setLayout(pipelineLayout)
+        .setPColorBlendState(PrepareColorBlendStateCreateInfo())
+        .setPDepthStencilState(PrepareDepthStencilStateCreateInfo())
+        .setPDynamicState(nullptr)
+        .setPInputAssemblyState(PrepareInputAssemblyStateCreateInfo())
+        .setPMultisampleState(PrepareMultisampleStateCreateInfo())
+        .setPRasterizationState(PrepareRasterizationStateCreateInfo())
+        .setPTessellationState(PrepareTesselationStateCreateInfo())
+          //.setPVertexInputState(PrepareVertexInputStateCreateInfo())
+        .setPVertexInputState(&vertexInputState)
+        .setPViewportState(PrepareViewportStateCreateInfo())
+        .setPStages(shaderStages.data())
+        .setStageCount(Vulkan::U32(shaderStages.size()));
+
+      auto pipeline = Vulkan::Pipeline::New(mGraphics, pipelineInfo);
+
+      pipeline->Compile();
+
+      pipelineCache.AddPipeline(pipeline, Vulkan::PipelineDescription{vertexShader, fragmentShader, dsLayouts});
+
+      pipelineRef = pipeline;
+
+    }
+
+    mPipeline = pipelineRef;
+
+    mVkDescriptorSetLayouts.clear();
+
+    mVkDescriptorSetLayouts = pipelineCache.GetDescriptorSetLayouts(mPipeline);
+
+    // based on pipeline recreate descriptor pool
+    auto poolSizes = std::vector<vk::DescriptorPoolSize>{
+      vk::DescriptorPoolSize{}
+        .setDescriptorCount(10)
+        .setType(vk::DescriptorType::eUniformBuffer),
+      vk::DescriptorPoolSize{}
+        .setDescriptorCount(10)
+        .setType(vk::DescriptorType::eCombinedImageSampler),
+      vk::DescriptorPoolSize{}
+        .setDescriptorCount(10)
+        .setType(vk::DescriptorType::eSampledImage)
+    };
+
+    // create descriptor pool
+    mDescriptorPool = Vulkan::DescriptorPool::New(mGraphics, vk::DescriptorPoolCreateInfo{}
+      .setMaxSets(Vulkan::U32(mVkDescriptorSetLayouts.size() + 1))
+      .setPPoolSizes(poolSizes.data())
+      .setPoolSizeCount(Vulkan::U32(poolSizes.size())));
+
+    // allocate descriptor sets. we need a descriptors for each descriptorset
+    // in the shader
+    // allocate descriptor sets for given pipeline layout
+    mDescriptorSets = mDescriptorPool->AllocateDescriptorSets(
+      vk::DescriptorSetAllocateInfo{}
+        .setPSetLayouts(mVkDescriptorSetLayouts.data())
+        .setDescriptorPool(nullptr)
+        .setDescriptorSetCount(uint32_t(mVkDescriptorSetLayouts.size()))
+    );
+
+    AllocateUniformBufferMemory();
+
+    BindUniformBuffers();
+
+    BindTexturesAndSamplers();
+
+    mUpdateFlags = 0u;
+  }
+  return true;
+}
+
+void RenderCommand::UpdateUniformBuffers()
+{
+  uint32_t uboIndex = 0u;
+  for( auto&& pc : mPushConstantsBindings )
+  {
+    mUboBuffers[uboIndex++]->WriteKeepMapped( pc.data, 0, pc.size );
+  }
+}
+
+const vk::PipelineColorBlendStateCreateInfo* RenderCommand::PrepareColorBlendStateCreateInfo()
+{
+  //@todo support more attachments
+  //@todo use data from render state
+  auto blendAttachmentState = vk::PipelineColorBlendAttachmentState{}
+    .setBlendEnable( true )
+    .setColorWriteMask( vk::ColorComponentFlagBits::eR |
+                        vk::ColorComponentFlagBits::eG |
+                        vk::ColorComponentFlagBits::eB |
+                        vk::ColorComponentFlagBits::eA )
+    .setSrcColorBlendFactor( vk::BlendFactor::eSrcAlpha )
+    .setDstColorBlendFactor( vk::BlendFactor::eOneMinusSrc1Alpha )
+    .setSrcAlphaBlendFactor( vk::BlendFactor::eOne )
+    .setDstAlphaBlendFactor( vk::BlendFactor::eOneMinusSrc1Alpha )
+    .setColorBlendOp( vk::BlendOp::eAdd )
+    .setAlphaBlendOp( vk::BlendOp::eAdd );
+
+  mVulkanPipelineState->colorBlendAttachmentState.emplace_back( blendAttachmentState );
+
+  mVulkanPipelineState->colorBlend
+                      .setBlendConstants( { 1.0f, 1.0f, 1.0f, 1.0f })
+                      .setAttachmentCount( 1 )
+                      .setPAttachments( mVulkanPipelineState->colorBlendAttachmentState.data() );
+
+  return &mVulkanPipelineState->colorBlend;
+}
+
+const vk::PipelineDepthStencilStateCreateInfo* RenderCommand::PrepareDepthStencilStateCreateInfo()
+{
+  return &(mVulkanPipelineState->depthStencil
+          .setDepthBoundsTestEnable( false )
+          .setStencilTestEnable( false ));
+}
+
+const vk::PipelineInputAssemblyStateCreateInfo* RenderCommand::PrepareInputAssemblyStateCreateInfo()
+{
+  //@todo support topology and restart
+  return &(mVulkanPipelineState->inputAssembly
+  .setPrimitiveRestartEnable( true )
+  .setTopology( vk::PrimitiveTopology::eTriangleStrip ));
+}
+
+const vk::PipelineMultisampleStateCreateInfo* RenderCommand::PrepareMultisampleStateCreateInfo()
+{
+  return &(mVulkanPipelineState->multisample
+        .setSampleShadingEnable( false )
+        .setRasterizationSamples( vk::SampleCountFlagBits::e1)
+        .setAlphaToCoverageEnable( false )
+        .setMinSampleShading( 1.0f )
+        .setPSampleMask( nullptr ));
+}
+
+const vk::PipelineRasterizationStateCreateInfo* RenderCommand::PrepareRasterizationStateCreateInfo()
+{
+  return &(mVulkanPipelineState->rasterization
+    .setCullMode( vk::CullModeFlagBits::eNone )
+    .setDepthBiasClamp( 0.0f )
+    .setDepthBiasEnable( false )
+    .setDepthClampEnable( false )
+    .setFrontFace( vk::FrontFace::eCounterClockwise )
+    .setPolygonMode( vk::PolygonMode::eFill )
+    .setRasterizerDiscardEnable( false )
+    .setLineWidth( 1.0f ));
+}
+
+const vk::PipelineTessellationStateCreateInfo* RenderCommand::PrepareTesselationStateCreateInfo()
+{
+  return nullptr;
+}
+
+const vk::PipelineVertexInputStateCreateInfo* RenderCommand::PrepareVertexInputStateCreateInfo()
+{
+  /*
+  mBindingDesc.clear();
+  mAttrDesc.clear();
+  mVertexInputState = vk::PipelineVertexInputStateCreateInfo{};
+  mVertexInputState.setPVertexAttributeDescriptions( (mAttrDesc = attrDesc).data() );
+  mVertexInputState.setPVertexBindingDescriptions( (mBindingDesc = bindingDesc).data() );
+  mVertexInputState.setVertexAttributeDescriptionCount( U32(mAttrDesc.size()) );
+  mVertexInputState.setVertexBindingDescriptionCount( U32(mBindingDesc.size()) );
+  mInfo.setPVertexInputState( &mVertexInputState );
+   */
+  return nullptr;
+}
+
+const vk::PipelineViewportStateCreateInfo* RenderCommand::PrepareViewportStateCreateInfo()
+{
+  assert( !mPipeline && "Pipeline cannot be changed anymore!");
+
+  auto width = mGraphics.GetSwapchainForFBID(0)->GetCurrentFramebuffer()->GetWidth();
+  auto height = mGraphics.GetSwapchainForFBID(0)->GetCurrentFramebuffer()->GetHeight();
+
+  // viewports
+  mVulkanPipelineState->viewport.viewports.emplace_back( 0, 0, width, height );
+  mVulkanPipelineState->viewport.viewports[0].setMinDepth( 0.0f );
+  mVulkanPipelineState->viewport.viewports[0].setMaxDepth( 1.0f );
+
+  // scissors
+  mVulkanPipelineState->viewport.scissors.emplace_back( vk::Rect2D(
+                        { static_cast<int32_t>(0), static_cast<int32_t>(0) },
+                        { Vulkan::U32(width), Vulkan::U32(height) } )
+                      );
+
+  auto& viewState = mVulkanPipelineState->viewport;
+
+  return &(mVulkanPipelineState->viewport.createInfo.
+          setViewportCount( Vulkan::U32(viewState.viewports.size()) ).
+          setPViewports( viewState.viewports.data() ).
+          setPScissors( viewState.scissors.data() ).
+          setScissorCount( Vulkan::U32(viewState.scissors.size())) );
+}
+
+const Vulkan::CommandBufferRef& RenderCommand::GetCommandBuffer() const
+{
+  return mCommandBuffer;
+}
+
+const Vulkan::PipelineCache& RenderCommand::GetPipelineCache() const
+{
+  return mPipelineCache;
+}
+
+const Vulkan::PipelineRef& RenderCommand::GetPipeline() const
+{
+  return mPipeline;
+}
+
+void RenderCommand::AllocateUniformBufferMemory()
+{
+  // release any existing buffers
+  mUboBuffers.clear();
+
+  // based on pipeline allocate memory for each push constant and uniform buffer
+  // using given UBOManager
+  for( auto&& pc : mPushConstantsBindings )
+  {
+    mUboBuffers.emplace_back( mController.GetUboManager().Allocate( pc.size ) );
+  }
+
+}
+
+void RenderCommand::BindUniformBuffers()
+{
+  // if uniform buffers for some reason changed, then rewrite
+  // bind PCs
+  for( uint32_t i = 0; i < mPushConstantsBindings.size(); ++i )
+  {
+    auto& ubo = mUboBuffers[i];
+    auto& pc = mPushConstantsBindings[i];
+
+    auto offset = ubo->GetBindingOffset();
+    auto size = ubo->GetBindingSize();
+    std::cout << "offset: " << offset << ", size: " << size << std::endl;
+    debug("[RenderCommand] BindingUBO: binding = " << pc.binding);
+    mDescriptorSets[0]->WriteUniformBuffer( pc.binding, ubo->GetBuffer(), ubo->GetBindingOffset(), ubo->GetBindingSize() );
+  }
+}
+
+void RenderCommand::BindTexturesAndSamplers()
+{
+  // only if textures/samplers changed, rewrite
+  for( auto&& texture : mTextureBindings )
+  {
+    auto& image = static_cast<VulkanAPI::Texture&>( texture.texture.Get() );
+    debug("[RenderCommand] BindingTextureSampler: binding = " << texture.binding);
+    mDescriptorSets[0]->WriteCombinedImageSampler( texture.binding, image.GetTextureRef()->GetSampler(), image.GetTextureRef()->GetImageView() );
+  }
+}
+
+const std::vector<Vulkan::DescriptorSetRef>& RenderCommand::GetDescriptorSets() const
+{
+  return mDescriptorSets;
+}
+
+} // namespace VulkanAPI
+} // namespace Graphics
+} // namespace Dali
\ No newline at end of file
diff --git a/dali/graphics/vulkan/api/vulkan-api-render-command.h b/dali/graphics/vulkan/api/vulkan-api-render-command.h
new file mode 100644 (file)
index 0000000..8049f59
--- /dev/null
@@ -0,0 +1,167 @@
+#ifndef DALI_GRAPHICS_VULKAN_API_RENDER_COMMAND_H
+#define DALI_GRAPHICS_VULKAN_API_RENDER_COMMAND_H
+
+/*
+ * Copyright (c) 2018 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-api-render-command.h>
+#include <dali/graphics-api/graphics-api-shader-details.h>
+#include <dali/graphics/vulkan/vulkan-types.h>
+
+//#include <dali/graphics/vulkan/vulkan-command-buffer.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class PipelineCache;
+class Controller;
+}
+namespace VulkanAPI
+{
+
+using Controller = Vulkan::Controller;
+
+class Ubo;
+
+/**
+ * Render command stores internal command buffer per draw call
+ *
+ * For Vulkan:
+ *
+ * - RenderCommand stores all the relevant data
+ * - Changing pipeline determines recreating certain resources
+ * - Currently each RC has own DescriptorSetPool
+ * - Currently each RC has a handle to UBOs
+ * - UBOs are assigned upon pipeline creation/assignment
+ * - Descriptor sets are allocated upon pipeline creation
+ * - Note: need resource "versioning"
+ */
+class RenderCommand : public Graphics::API::RenderCommand
+{
+public:
+
+  constexpr static uint32_t UPDATE_ALL = 0xffffffff;
+
+  RenderCommand( VulkanAPI::Controller& controller,
+                 Vulkan::Graphics& graphics,
+                 Vulkan::PipelineCache& pipelineCache );
+
+  ~RenderCommand() override;
+
+  /**
+   * Forces pipeline compilation whenever something changed and
+   * updates cache
+   * @return
+   */
+  bool PreparePipeline();
+
+  /**
+   * Updates uniform buffers
+   */
+  void UpdateUniformBuffers();
+
+  /**
+   * Writes uniform buffers into descriptor set
+   */
+  void BindUniformBuffers();
+
+  /**
+   * Writes texture/sample combo into descriptor set
+   */
+  void BindTexturesAndSamplers();
+
+  /**
+   * Returns an array of updated descriptor sets
+   * @return
+   */
+  const std::vector<Vulkan::DescriptorSetRef>& GetDescriptorSets() const;
+
+  /**
+   * Returns associated Vulkan command buffer
+   * @return
+   */
+  const Vulkan::CommandBufferRef& GetCommandBuffer() const;
+
+  /**
+   * Returns pipeline cache
+   * @return
+   */
+  const Vulkan::PipelineCache& GetPipelineCache() const;
+
+  /**
+   * Returns pipeline
+   * @return
+   */
+  const Vulkan::PipelineRef& GetPipeline() const;
+
+
+private:
+
+  const vk::PipelineColorBlendStateCreateInfo*      PrepareColorBlendStateCreateInfo();
+
+  const vk::PipelineDepthStencilStateCreateInfo*    PrepareDepthStencilStateCreateInfo();
+
+  const vk::PipelineInputAssemblyStateCreateInfo*   PrepareInputAssemblyStateCreateInfo();
+
+  const vk::PipelineMultisampleStateCreateInfo*     PrepareMultisampleStateCreateInfo();
+
+  const vk::PipelineRasterizationStateCreateInfo*   PrepareRasterizationStateCreateInfo();
+
+  const vk::PipelineTessellationStateCreateInfo*    PrepareTesselationStateCreateInfo();
+
+  const vk::PipelineVertexInputStateCreateInfo*     PrepareVertexInputStateCreateInfo();
+
+  const vk::PipelineViewportStateCreateInfo*        PrepareViewportStateCreateInfo();
+
+  /**
+   * Allocates UBO memory based on the pipeline. Executed only
+   * once per pipeline
+   */
+  void AllocateUniformBufferMemory();
+
+private:
+
+  /**
+   * Describes assigned UBO buffers
+   */
+
+  struct VulkanPipelineState;
+  std::unique_ptr<VulkanPipelineState>  mVulkanPipelineState;
+
+  VulkanAPI::Controller&                mController;
+  Vulkan::Graphics&                     mGraphics;
+  Vulkan::PipelineCache&                mPipelineCache;
+  Vulkan::CommandBufferRef              mCommandBuffer;
+  Vulkan::PipelineRef                   mPipeline;
+  Vulkan::DescriptorPoolRef             mDescriptorPool;
+
+  std::vector<vk::DescriptorSetLayout>  mVkDescriptorSetLayouts;
+
+  std::vector<Vulkan::DescriptorSetRef> mDescriptorSets;
+
+  std::vector<std::unique_ptr<Ubo>>     mUboBuffers;
+
+  uint32_t mUpdateFlags;
+};
+
+}
+}
+}
+#endif //DALI_GRAPHICS_VULKAN_API_RENDER_COMMAND_H
index c97548a..e103ca0 100644 (file)
@@ -26,6 +26,7 @@ namespace Graphics
 {
 namespace VulkanAPI
 {
+
 ShaderFactory::ShaderFactory( Vulkan::Graphics& graphics ) :
 mGraphics( graphics )
 {
index 160b17e..22fdab5 100644 (file)
@@ -111,18 +111,238 @@ bool Shader::AddShaderModule( Dali::Graphics::API::ShaderDetails::PipelineStage
   if(pipelineStage == ShaderPipelineStage::VERTEX )
   {
     mVertexShader = shaderRef;
-    return true;
+    mVertexShader->SetExplicitShaderStage( vk::ShaderStageFlagBits::eVertex );
+    // update input attributes
+    mVertexShader->GetSPIRVReflection().GetVertexInputAttributes( mVertexInputAttributes );
   }
   else if(pipelineStage == ShaderPipelineStage::FRAGMENT )
   {
     mFragmentShader = shaderRef;
-    return true;
+    mVertexShader->SetExplicitShaderStage( vk::ShaderStageFlagBits::eFragment );
   }
 
-  // possibly unsupported pipeline stage
+  mUniformBlocks.clear();
+  mUniformOpaques.clear();
+
+  // recreate reflection
+  if( mVertexShader )
+  {
+    auto& ubo = mVertexShader->GetSPIRVReflection().GetUniformBlocks();
+    mUniformBlocks.insert(mUniformBlocks.end(), ubo.begin(), ubo.end() );
+
+    auto& uniforms = mVertexShader->GetSPIRVReflection().GetOpaqueUniforms();
+    mUniformOpaques.insert(mUniformOpaques.end(), uniforms.begin(), uniforms.end() );
+  }
+  if( mFragmentShader )
+  {
+    auto& ubo = mFragmentShader->GetSPIRVReflection().GetUniformBlocks();
+    mUniformBlocks.insert(mUniformBlocks.end(), ubo.begin(), ubo.end() );
+
+    auto& uniforms = mFragmentShader->GetSPIRVReflection().GetOpaqueUniforms();
+    mUniformOpaques.insert(mUniformOpaques.end(), uniforms.begin(), uniforms.end() );
+  }
+
+  // verify bindings and descriptor sets ( must be no overlaps, or if there are, only one binding will be used )
+  return true;
+}
+
+bool Shader::IsReflectionSupported() const
+{
+  return true;
+}
+
+uint32_t Shader::GetVertexAttributeLocation(const std::string& name) const
+{
+  if( !mVertexShader )
+  {
+    return API::ShaderDetails::ERROR_VERTEX_INPUT_ATTRIBUTE_NOT_FOUND;
+  }
+
+  for( auto&& attr : mVertexInputAttributes )
+  {
+    if( attr.name == name )
+    {
+      return attr.location;
+    }
+  }
+  return API::ShaderDetails::ERROR_VERTEX_INPUT_ATTRIBUTE_NOT_FOUND;
+}
+
+API::ShaderDetails::VertexInputAttributeFormat Shader::GetVertexAttributeFormat( uint32_t location ) const
+{
+  if( !mVertexShader || mVertexInputAttributes.size() <= location )
+  {
+    return API::ShaderDetails::VertexInputAttributeFormat::UNDEFINED;
+  }
+
+  const auto& attr = mVertexInputAttributes[location];
+
+  if( attr.format == vk::Format::eR32Sfloat )
+  {
+    return API::ShaderDetails::VertexInputAttributeFormat::FLOAT;
+  }
+  if( attr.format == vk::Format::eR32Sint )
+  {
+    return API::ShaderDetails::VertexInputAttributeFormat::INTEGER;
+  }
+  if( attr.format == vk::Format::eR32G32Sfloat )
+  {
+    return API::ShaderDetails::VertexInputAttributeFormat::VEC2;
+  }
+  if( attr.format == vk::Format::eR32G32B32Sfloat )
+  {
+    return API::ShaderDetails::VertexInputAttributeFormat::VEC3;
+  }
+  if( attr.format == vk::Format::eR32G32B32A32Sfloat )
+  {
+    return API::ShaderDetails::VertexInputAttributeFormat::VEC4;
+  }
+  return API::ShaderDetails::VertexInputAttributeFormat::UNDEFINED;
+}
+
+std::string Shader::GetVertexAttributeName(uint32_t location) const
+{
+  if( !mVertexShader || mVertexInputAttributes.size() <= location )
+  {
+    return "";
+  }
+
+  return mVertexInputAttributes[location].name;
+}
+
+std::vector<uint32_t> Shader::GetVertexAttributeLocations() const
+{
+  std::vector<uint32_t> locations;
+  for( auto&& attr : mVertexInputAttributes )
+  {
+    if( attr.format != vk::Format::eUndefined )
+    {
+      locations.push_back( attr.location );
+    }
+  }
+
+  return locations;
+}
+
+std::vector<uint32_t> Shader::GetUniformBlockLocations() const
+{
+  std::vector<uint32_t> retval{};
+  for( auto&& ubo : mUniformBlocks )
+  {
+    retval.emplace_back( ubo.binding );
+  }
+  return retval;
+}
+
+std::string Shader::GetUniformBlockName( uint32_t blockIndex ) const
+{
+  return mUniformBlocks[blockIndex].name;
+}
+
+uint32_t Shader::GetUniformBlockMemberCount( uint32_t blockIndex ) const
+{
+  return U32(mUniformBlocks[blockIndex].members.size());
+}
+
+std::string Shader::GetUniformBlockMemberName( uint32_t blockIndex, uint32_t memberLocation ) const
+{
+  return mUniformBlocks[blockIndex].members[memberLocation].name;
+}
+
+uint32_t Shader::GetUniformBlockMemberOffset( uint32_t blockIndex, uint32_t memberLocation ) const
+{
+  return mUniformBlocks[blockIndex].members[memberLocation].offset;
+}
+
+bool Shader::GetNamedUniform( const std::string& name, API::ShaderDetails::UniformInfo& out ) const
+{
+  // check uniform blocks first
+  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 = ShaderDetails::UniformClass::UNIFORM_BUFFER;
+        return true;
+      }
+    }
+    index++;
+  }
+
+  // check samplers
+  for( auto&& uniform : mUniformOpaques )
+  {
+    if( uniform.name == name )
+    {
+      out.uniformClass = ShaderDetails::UniformClass::COMBINED_IMAGE_SAMPLER;
+      out.binding = uniform.binding;
+      out.name = name;
+      out.offset = 0;
+      out.location = 0;
+      return true;
+    }
+  }
   return false;
 }
 
+std::vector<API::ShaderDetails::UniformInfo> Shader::GetSamplers() const
+{
+  std::vector<API::ShaderDetails::UniformInfo> retval;
+  for( auto&& uniform : mUniformOpaques )
+  {
+    if(uniform.type == vk::DescriptorType::eCombinedImageSampler )
+    {
+      API::ShaderDetails::UniformInfo info;
+      info.location = 0u;
+      info.binding = uniform.binding;
+      info.offset = 0;
+      info.name = uniform.name;
+      info.uniformClass = API::ShaderDetails::UniformClass::COMBINED_IMAGE_SAMPLER;
+      retval.emplace_back( info );
+    }
+  }
+  return retval;
+}
+
+uint32_t Shader::GetUniformBlockCount() const
+{
+  return U32(mUniformBlocks.size());
+}
+
+bool Shader::GetUniformBlock( uint32_t index, API::ShaderDetails::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 = API::ShaderDetails::UniformClass::UNIFORM_BUFFER;
+    out.members[i].offset = memberUniform.offset;
+    out.members[i].location = memberUniform.location;
+  }
+
+  return true;
+}
 
 
 } // namespace VulkanAPI
index f566228..3c4d94a 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef DALI_VULKAN_161117_VULKAN_API_SHADER_H
-#define DALI_VULKAN_161117_VULKAN_API_SHADER_H
+#ifndef DALI_GRAPHICS_VULKAN_API_SHADER_H
+#define DALI_GRAPHICS_VULKAN_API_SHADER_H
 
 /*
  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
@@ -21,6 +21,7 @@
 #include <dali/graphics-api/graphics-api-shader.h>
 #include <dali/graphics-api/graphics-api-shader-details.h>
 #include <dali/graphics/vulkan/vulkan-types.h>
+#include <dali/graphics/vulkan/spirv/vulkan-spirv.h>
 
 namespace Dali
 {
@@ -52,6 +53,42 @@ public:
 
   Vulkan::ShaderRef GetShaderRef( vk::ShaderStageFlagBits shaderStage ) const;
 
+
+  // REFLECTION
+
+  // Vertex attributes
+  bool IsReflectionSupported() const override;
+
+  uint32_t GetVertexAttributeLocation(const std::string &name) const override;
+
+  API::ShaderDetails::VertexInputAttributeFormat GetVertexAttributeFormat( uint32_t location ) const override;
+
+  std::string GetVertexAttributeName(uint32_t location) const override;
+
+  std::vector<uint32_t> GetVertexAttributeLocations() const override;
+
+  /**
+   * Uniforms
+   */
+
+  std::vector<uint32_t> GetUniformBlockLocations() const;
+
+  std::string GetUniformBlockName( uint32_t blockIndex) const;
+
+  uint32_t GetUniformBlockMemberCount( uint32_t blockIndex ) const;
+
+  std::string GetUniformBlockMemberName( uint32_t blockIndex, uint32_t memberLocation ) const;
+
+  uint32_t GetUniformBlockMemberOffset( uint32_t blockIndex, uint32_t memberLocation ) const;
+
+  bool GetNamedUniform( const std::string& name, API::ShaderDetails::UniformInfo& out ) const override;
+
+  std::vector<API::ShaderDetails::UniformInfo> GetSamplers() const override;
+
+  uint32_t GetUniformBlockCount() const override;
+
+  bool GetUniformBlock( uint32_t index, API::ShaderDetails::UniformBlockInfo& out ) const override;
+
 protected:
   // derived types should not be moved direcly to prevent slicing
   Shader( Shader&& ) = default;
@@ -65,10 +102,12 @@ private:
   Vulkan::ShaderRef mVertexShader;
   Vulkan::ShaderRef mFragmentShader;
 
-
+  std::vector<Vulkan::SpirV::SPIRVVertexInputAttribute> mVertexInputAttributes;
+  std::vector<Vulkan::SpirV::SPIRVUniformBlock> mUniformBlocks;
+  std::vector<Vulkan::SpirV::SPIRVUniformOpaque> mUniformOpaques;
 };
 
 } // namespace Vulkan
 } // namespace Graphics
 } // namespace Dali
-#endif //DALI_VULKAN_161117_VULKAN_API_SHADER_H
+#endif //DALI_GRAPHICS_VULKAN_API_SHADER_H
index 3adbd5e..02bdfd6 100644 (file)
@@ -32,39 +32,35 @@ std::vector<uint8_t> VSH_CODE = {
   0x6d, 0x76, 0x70, 0x00, 0x06, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00,
   0x06, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x73, 0x61, 0x6d, 0x70,
-  0x6c, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x03, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x05, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x61, 0x50, 0x6f, 0x73,
-  0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x75, 0x76, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x73,
-  0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x36, 0x00, 0x00, 0x00,
-  0x74, 0x72, 0x69, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00,
-  0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
-  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x47, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x48, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
+  0x1f, 0x00, 0x00, 0x00, 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+  0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x75, 0x76, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x05, 0x00, 0x36, 0x00, 0x00, 0x00, 0x74, 0x72, 0x69, 0x43,
+  0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
   0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
-  0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
-  0x13, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-  0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x23, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
-  0x50, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
   0x47, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
   0x47, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00,
@@ -95,73 +91,73 @@ std::vector<uint8_t> VSH_CODE = {
   0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
   0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
   0x17, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00,
   0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
-  0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x20, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x17, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00,
-  0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
-  0x0e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x20, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x17, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x20, 0x00, 0x04, 0x00,
-  0x2c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-  0x17, 0x00, 0x04, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2f, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
-  0x2f, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3f, 0x2c, 0x00, 0x05, 0x00, 0x2e, 0x00, 0x00, 0x00,
-  0x34, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
-  0x3b, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
-  0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
-  0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-  0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
-  0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
-  0x15, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
-  0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
-  0x1b, 0x00, 0x00, 0x00, 0x92, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
-  0x1d, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
-  0x3d, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-  0x1f, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00,
-  0x23, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
-  0x3d, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
-  0x23, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x17, 0x00, 0x00, 0x00,
-  0x25, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
-  0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
-  0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x29, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
-  0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
-  0x26, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
-  0x2b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
-  0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
-  0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
-  0x2d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
-  0x17, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
-  0x4f, 0x00, 0x07, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
-  0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x2e, 0x00, 0x00, 0x00,
-  0x35, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
-  0x3e, 0x00, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
-  0x41, 0x00, 0x05, 0x00, 0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
-  0x1a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
-  0x3e, 0x00, 0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
-  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+  0x20, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x20, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x2f, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x2c, 0x00, 0x05, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0x92, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x85, 0x00, 0x05, 0x00, 0x17, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
+  0x91, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
+  0x1d, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x2d, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x31, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+  0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x81, 0x00, 0x05, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
+  0x32, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x37, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+  0x36, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
+  0x38, 0x00, 0x01, 0x00
 };
 std::vector<uint8_t> FSH_CODE = {
   0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
   0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
   0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -173,48 +169,491 @@ std::vector<uint8_t> FSH_CODE = {
   0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
   0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
   0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x75, 0x54, 0x65, 0x78,
+  0x05, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x54, 0x65, 0x78,
   0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
   0x11, 0x00, 0x00, 0x00, 0x75, 0x76, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x73,
   0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
   0x74, 0x72, 0x69, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00,
-  0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x73, 0x54, 0x65, 0x78,
+  0x74, 0x75, 0x72, 0x65, 0x32, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00,
   0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
-  0x0d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
-  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-  0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x15, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+std::vector<uint8_t> VSH_IMAGE_VISUAL_CODE = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00,
+  0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x35, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xae, 0x01, 0x00, 0x00,
+  0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+  0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x56, 0x65, 0x72, 0x74, 0x65,
+  0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x00, 0x00,
+  0x05, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x76, 0x69, 0x73, 0x75,
+  0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x76, 0x65, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61,
+  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x75, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x4d, 0x61,
+  0x74, 0x72, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x75, 0x56, 0x69, 0x65,
+  0x77, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x00, 0x06, 0x00, 0x06, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x75, 0x50, 0x72, 0x6f,
+  0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x06, 0x00, 0x05, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x75, 0x53, 0x69, 0x7a,
+  0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x41, 0x72, 0x65,
+  0x61, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x75, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x41, 0x6c,
+  0x69, 0x67, 0x6e, 0x65, 0x64, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x66, 0x73,
+  0x65, 0x74, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x07, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x4d, 0x6f,
+  0x64, 0x65, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x00, 0x00,
+  0x06, 0x00, 0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x00,
+  0x05, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0x76, 0x69, 0x73, 0x75,
+  0x61, 0x6c, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x05, 0x00, 0x35, 0x00, 0x00, 0x00, 0x61, 0x50, 0x6f, 0x73,
+  0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
+  0x4f, 0x00, 0x00, 0x00, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x50, 0x6f,
+  0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00,
+  0x5a, 0x00, 0x00, 0x00, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56,
+  0x65, 0x72, 0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+  0x6e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x6e, 0x00, 0x00, 0x00,
+  0x76, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50,
+  0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00,
+  0x06, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65,
+  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43, 0x6c, 0x69, 0x70, 0x44,
+  0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x05, 0x00, 0x03, 0x00,
+  0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0xc0, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0xe8, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x10, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00,
+  0x47, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x35, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x7f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x0d, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x20, 0x00, 0x04, 0x00, 0x4e, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x6d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x6f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x2c, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+  0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
+  0x7c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7e, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00,
+  0x7f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x7e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x83, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x4e, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x52, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
+  0x52, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x55, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
+  0x55, 0x00, 0x00, 0x00, 0x92, 0x00, 0x05, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x57, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
+  0x39, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x59, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
+  0x4f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5a, 0x00, 0x00, 0x00,
+  0x5b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x5c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+  0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00,
+  0x5a, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x09, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5a, 0x00, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x62, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00,
+  0x62, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x64, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
+  0x69, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
+  0x69, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x6b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
+  0x64, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
+  0x91, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+  0x63, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+  0x4f, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+  0x21, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x6f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x71, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
+  0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
+  0x4f, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00,
+  0x74, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x76, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
+  0x78, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x7a, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00,
+  0x81, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00,
+  0x72, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+  0x6e, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+  0x81, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+  0x84, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
+  0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0xf8, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x2a, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
+  0x2a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
+  0x32, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x26, 0x00, 0x00, 0x00,
+  0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x36, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x37, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x39, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
+  0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x42, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+  0x42, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x44, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
+  0x44, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x46, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
+  0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
+  0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x4b, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00,
+  0x4b, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+std::vector<uint8_t> FSH_IMAGE_VISUAL_CODE = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x27, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0xae, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x76, 0x69, 0x73, 0x75,
+  0x61, 0x6c, 0x4d, 0x69, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x00,
+  0x05, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x66, 0x72, 0x61, 0x67,
+  0x44, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x43, 0x6f, 0x6c,
+  0x6f, 0x72, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x6d, 0x69, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x00,
+  0x06, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x70, 0x72, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65,
+  0x64, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
+  0x27, 0x00, 0x00, 0x00, 0x66, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f,
+  0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x00, 0x00,
+  0x73, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x76, 0x54, 0x65, 0x78,
+  0x43, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x2b, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x2b, 0x00, 0x04, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x26, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x28, 0x00, 0x00, 0x00,
   0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00,
-  0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
-  0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
-  0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x04, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2e, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x33, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
   0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
-  0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-  0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00,
-  0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-  0x12, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
-  0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
-  0x16, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
-  0x17, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+  0x3d, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x2d, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x33, 0x00, 0x00, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x36, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
+  0x39, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x27, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00
 };
 #pragma GCC diagnostic pop
index 656a8a8..83e389a 100644 (file)
@@ -16,7 +16,6 @@ layout( set = 0, binding = 0, std140 ) uniform world
     mat4 mvp;
     vec4 color;
     vec3 size;
-    uint samplerIndex;
 };
 
 layout( set = 0, binding = 1, std140 ) uniform clipUniform
@@ -25,11 +24,11 @@ layout( set = 0, binding = 1, std140 ) uniform clipUniform
 };
 
 layout( location = 0 ) out vec4 triColor;
-
 layout( location = 1 ) out vec2 uvCoords;
 
 void main()
 {
+
     gl_Position = clip * mvp * vec4( aPosition* size, 1.0 );
     uvCoords = aPosition.xy + vec2( 0.5, 0.5 );
     triColor = color;
@@ -44,14 +43,88 @@ layout( location = 0 ) in vec4 triColor;
 layout( location = 1 ) in vec2 uvCoords;
 layout( location = 0 ) out vec4 outColor;
 
-layout( set = 0, binding = 2 ) uniform sampler2D uTexture;
+layout( set = 0, binding = 4 ) uniform sampler2D sTexture;
+layout( set = 0, binding = 2 ) uniform sampler2D sTexture2;
 
 void main()
 {
-    outColor = texture( uTexture, uvCoords) * triColor;
+    outColor = texture( sTexture, uvCoords) * triColor;
 }*/
 
 
+extern std::vector<uint8_t> VSH_IMAGE_VISUAL_CODE;
+/*
+#version 430
+
+layout( location = 0 ) in vec2 aPosition;
+
+layout( set = 0, binding = 0, std140 ) uniform vertData
+{
+    mat4 uModelMatrix;  // 0
+    mat4 uViewMatrix;   // 64
+    mat4 uProjection;   // 128
+    vec3 uSize;         // 192
+    vec4 pixelArea;     // 204
+    float uPixelAligned; // 220
+
+    //Visual size and offset
+    vec2 offset; // 224
+    vec2 size; // 232
+    vec4 offsetSizeMode; // 240
+    vec2 origin; // 256
+    vec2 anchorPoint; // 264
+    // 272
+};
+
+layout( location = 0 ) out vec2 vTexCoord;
+
+vec4 ComputeVertexPosition()
+{
+    vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
+    vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
+    return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+}
+
+void main()
+{
+    vec4 vertexPosition = uViewMatrix * uModelMatrix * ComputeVertexPosition();
+    vec4 alignedVertexPosition = vertexPosition;
+    alignedVertexPosition.xy = floor ( vertexPosition.xy ); // Pixel alignment
+    vertexPosition = uProjection * mix( vertexPosition, alignedVertexPosition, uPixelAligned );
+    vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );
+    gl_Position = vertexPosition;
+}*/
+
+
+extern std::vector<uint8_t> FSH_IMAGE_VISUAL_CODE;
+/*
+#version 430
+
+layout( location = 0 ) in vec2 vTexCoord;
+
+layout( set = 0, binding = 1, std140 ) uniform fragData
+{
+    vec4 uColor;
+    vec3 mixColor;
+    float opacity;
+    float preMultipliedAlpha;
+};
+
+layout( set = 0, binding = 2 ) uniform sampler2D sTexture;
+
+layout( location = 0 ) out vec4 fragColor;
+
+vec4 visualMixColor()
+{
+    return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );
+}
+void main()
+{
+    fragColor = texture( sTexture, vTexCoord ) * uColor * visualMixColor();
+}
+*/
+
+
 #endif // SPV_GENERATED_HEADER
 
 
index 4f06d16..caf1945 100755 (executable)
@@ -8,7 +8,9 @@ generated_dir=./dali-core/dali/graphics/vulkan/generated
 
 shaders="
 ${shaders_dir}/basic-shader.vert|VSH_CODE|vert
-${shaders_dir}/basic-shader.frag|FSH_CODE|frag"
+${shaders_dir}/basic-shader.frag|FSH_CODE|frag
+${shaders_dir}/image-visual-shader.vert|VSH_IMAGE_VISUAL_CODE|vert
+${shaders_dir}/image-visual-shader.frag|FSH_IMAGE_VISUAL_CODE|frag"
 
 echo "// Autogenerated" > ${generated_dir}/spv-shaders-gen.h
 echo -e "#ifndef SPV_GENERATED_HEADER
index 4e087ac..e72f695 100644 (file)
@@ -4,9 +4,10 @@ layout( location = 0 ) in vec4 triColor;
 layout( location = 1 ) in vec2 uvCoords;
 layout( location = 0 ) out vec4 outColor;
 
-layout( set = 0, binding = 2 ) uniform sampler2D uTexture;
+layout( set = 0, binding = 4 ) uniform sampler2D sTexture;
+layout( set = 0, binding = 2 ) uniform sampler2D sTexture2;
 
 void main()
 {
-    outColor = texture( uTexture, uvCoords) * triColor;
+    outColor = texture( sTexture, uvCoords) * triColor;
 }
\ No newline at end of file
index 8742031..2eb6f27 100644 (file)
@@ -7,7 +7,6 @@ layout( set = 0, binding = 0, std140 ) uniform world
     mat4 mvp;
     vec4 color;
     vec3 size;
-    uint samplerIndex;
 };
 
 layout( set = 0, binding = 1, std140 ) uniform clipUniform
@@ -16,11 +15,11 @@ layout( set = 0, binding = 1, std140 ) uniform clipUniform
 };
 
 layout( location = 0 ) out vec4 triColor;
-
 layout( location = 1 ) out vec2 uvCoords;
 
 void main()
 {
+
     gl_Position = clip * mvp * vec4( aPosition* size, 1.0 );
     uvCoords = aPosition.xy + vec2( 0.5, 0.5 );
     triColor = color;
diff --git a/dali/graphics/vulkan/shaders/image-visual-shader.frag b/dali/graphics/vulkan/shaders/image-visual-shader.frag
new file mode 100644 (file)
index 0000000..c7fde44
--- /dev/null
@@ -0,0 +1,24 @@
+#version 430
+
+layout( location = 0 ) in vec2 vTexCoord;
+
+layout( set = 0, binding = 1, std140 ) uniform fragData
+{
+    vec4 uColor;
+    vec3 mixColor;
+    float opacity;
+    float preMultipliedAlpha;
+};
+
+layout( set = 0, binding = 2 ) uniform sampler2D sTexture;
+
+layout( location = 0 ) out vec4 fragColor;
+
+vec4 visualMixColor()
+{
+    return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );
+}
+void main()
+{
+    fragColor = texture( sTexture, vTexCoord ) * uColor * visualMixColor();
+}
diff --git a/dali/graphics/vulkan/shaders/image-visual-shader.vert b/dali/graphics/vulkan/shaders/image-visual-shader.vert
new file mode 100644 (file)
index 0000000..d7b3824
--- /dev/null
@@ -0,0 +1,40 @@
+#version 430
+
+layout( location = 0 ) in vec2 aPosition;
+
+layout( set = 0, binding = 0, std140 ) uniform vertData
+{
+    mat4 uModelMatrix;  // 0
+    mat4 uViewMatrix;   // 64
+    mat4 uProjection;   // 128
+    vec3 uSize;         // 192
+    vec4 pixelArea;     // 204
+    float uPixelAligned; // 220
+
+    //Visual size and offset
+    vec2 offset; // 224
+    vec2 size; // 232
+    vec4 offsetSizeMode; // 240
+    vec2 origin; // 256
+    vec2 anchorPoint; // 264
+    // 272
+};
+
+layout( location = 0 ) out vec2 vTexCoord;
+
+vec4 ComputeVertexPosition()
+{
+    vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
+    vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
+    return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+}
+
+void main()
+{
+    vec4 vertexPosition = uViewMatrix * uModelMatrix * ComputeVertexPosition();
+    vec4 alignedVertexPosition = vertexPosition;
+    alignedVertexPosition.xy = floor ( vertexPosition.xy ); // Pixel alignment
+    vertexPosition = uProjection * mix( vertexPosition, alignedVertexPosition, uPixelAligned );
+    vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );
+    gl_Position = vertexPosition;
+}
\ No newline at end of file
index 3dcaacf..6d981e5 100644 (file)
@@ -933,7 +933,7 @@ struct SPIRVShader::Impl
 
   bool GetVertexInputAttributes( std::vector<SPIRVVertexInputAttribute>& out, bool canOverlap = false )
   {
-    for( auto& i :  reflectionData )
+    for( auto&& i : reflectionData )
     {
       if( i.second.storage == SpvStorageClassInput )
       {
@@ -941,7 +941,9 @@ struct SPIRVShader::Impl
         attr.name = i.second.name;
         attr.location = MapContains( i.second.decorations, SpvDecorationLocation ) ?
                         i.second.decorations[SpvDecorationLocation]->GetParameterU32(2) : 0u;
-        attr.format = GetTypeInfo( GetReferencedOpCode( *i.second.op, 0 ) ).vkFormat;
+        attr.format = GetTypeInfo(
+          GetReferencedOpCode( GetReferencedOpCode( *i.second.op, 0 ), 2)
+        ).vkFormat;
         out.emplace_back( attr );
       }
     }
index d03aa2c..ff64a71 100644 (file)
@@ -446,7 +446,7 @@ void CommandBuffer::BindIndexBuffer( BufferRef buffer, uint32_t offset, vk::Inde
 }
 
 void CommandBuffer::BindVertexBuffer( uint32_t                               binding,
-                                      Dali::Graphics::Vulkan::Handle<Buffer> buffer,
+                                      const Dali::Graphics::Vulkan::Handle<Buffer>& buffer,
                                       vk::DeviceSize                         offset )
 {
   mImpl->BindVertexBuffers( binding, 1, std::vector<Handle<Buffer>>( {buffer} ), &offset );
index 1503f12..1b4c489 100644 (file)
@@ -120,7 +120,7 @@ public:
    * @param buffer
    * @param offset
    */
-  void BindVertexBuffer(uint32_t binding, Dali::Graphics::Vulkan::Handle<Buffer> buffer, vk::DeviceSize offset );
+  void BindVertexBuffer(uint32_t binding, const Dali::Graphics::Vulkan::Handle<Buffer>& buffer, vk::DeviceSize offset );
 
   /**
    * Binds graphics pipeline
index 371eaee..fe7bcd3 100644 (file)
@@ -204,6 +204,7 @@ struct CommandPool::Impl
 
   bool Initialise()
   {
+    mCreateInfo.setFlags( vk::CommandPoolCreateFlagBits::eResetCommandBuffer );
     mCommandPool = VkAssert(mGraphics.GetDevice().createCommandPool(mCreateInfo, mGraphics.GetAllocator()));
     mInternalPoolPrimary = std::make_unique<CommandBufferPool>( mInterface, mGraphics, 0, 32, true );
     mInternalPoolSecondary = std::make_unique<CommandBufferPool>( mInterface, mGraphics, 0, 32, false );
index 4bdf880..f76978a 100644 (file)
@@ -93,7 +93,7 @@ class DescriptorPool : public VkManaged
 {
 public:
 
-  static Handle<DescriptorPool> New( Graphics& graphics, const vk::DescriptorPoolCreateInfo& createInfo );
+  static DescriptorPoolRef New( Graphics& graphics, const vk::DescriptorPoolCreateInfo& createInfo );
 
   ~DescriptorPool() override;
 
index f3ab656..8f8f4e7 100644 (file)
@@ -59,7 +59,7 @@ struct Framebuffer::Impl
 
       vk::AttachmentDescription attDesc{};
       attDesc.setSamples( vk::SampleCountFlagBits::e1 )
-        .setInitialLayout( vk::ImageLayout::eColorAttachmentOptimal )
+        .setInitialLayout( vk::ImageLayout::eUndefined )
         .setFormat( colorAttachment->GetImage()->GetVkFormat() )
         .setStencilStoreOp( vk::AttachmentStoreOp::eDontCare )
         .setStencilLoadOp( vk::AttachmentLoadOp::eDontCare )
@@ -88,7 +88,7 @@ struct Framebuffer::Impl
 
       vk::AttachmentDescription attDesc{};
       attDesc.setSamples( vk::SampleCountFlagBits::e1 )
-             .setInitialLayout( vk::ImageLayout::eDepthStencilAttachmentOptimal )
+             .setInitialLayout( vk::ImageLayout::eUndefined )
              .setFormat( mDepthStencilImageViewAttachment->GetImage()->GetVkFormat() )
              .setStencilStoreOp( vk::AttachmentStoreOp::eDontCare )
              .setStencilLoadOp( vk::AttachmentLoadOp::eDontCare )
index 78fa886..9507c34 100644 (file)
@@ -15,6 +15,7 @@
 #include <dali/graphics/vulkan/vulkan-graphics-controller.h>
 #include <dali/graphics/vulkan/vulkan-graphics.h>
 #include <dali/graphics/vulkan/vulkan-pipeline.h>
+#include <dali/graphics/vulkan/vulkan-pipeline-cache.h>
 #include <dali/graphics/vulkan/vulkan-shader.h>
 #include <dali/graphics/vulkan/vulkan-framebuffer.h>
 #include <dali/graphics/vulkan/vulkan-surface.h>
 #include <dali/graphics-api/graphics-api-render-command.h>
 #include <dali/graphics/graphics-object-owner.h>
 
+
 // API
 #include <dali/graphics/vulkan/api/vulkan-api-shader.h>
 #include <dali/graphics/vulkan/api/vulkan-api-texture.h>
+#include <dali/graphics/vulkan/api/vulkan-api-buffer.h>
 #include <dali/graphics/vulkan/api/vulkan-api-texture-factory.h>
 #include <dali/graphics/vulkan/api/vulkan-api-shader-factory.h>
+#include <dali/graphics/vulkan/api/vulkan-api-buffer-factory.h>
+#include <dali/graphics/vulkan/api/vulkan-api-render-command.h>
+
+#include <dali/graphics/vulkan/api/internal/vulkan-ubo-manager.h>
+
+#include <iostream>
+#include <dali/graphics-api/utility/utility-memory-pool.h>
 
 using namespace glm;
 
@@ -41,120 +51,8 @@ namespace Vulkan
 static const mat4 CLIP_MATRIX(
   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f );
 
-/**
- * Graphics pipeline state describes single batch-draw call state
- */
-struct GraphicsPipelineState
-{
-  /**
-   * Internal Data structure collects only POD state
-   * details that are relevant to us
-   */
-  struct Info
-  {
-    // blending
-    vk::Bool32      blendEnabled;
-    vk::BlendFactor srcColor, srcAlpha;
-    vk::BlendFactor dstColor, dstAlpha;
-
-    // vertex input data
-    std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescription;
-    std::vector<vk::VertexInputBindingDescription>   vertexInputBindingDescripton;
-
-    // viewport size
-    vk::Rect2D viewport;
-
-    // topology
-    vk::PrimitiveTopology topology;
-
-    // depth/stencil
-    vk::Bool32 depthTestEnabled;
-    vk::Bool32 stencilTestEnabled;
-
-    // shaders
-    ShaderRef vertexShader;
-    ShaderRef fragmentShader;
-
-    bool operator==( const Info& src ) const
-    {
-      return false; // TODO
-    }
-
-  } info;
-
-  GraphicsPipelineState( GraphicsPipelineState& src )
-  {
-    info = src.info;
-  }
-
-  bool operator==( const GraphicsPipelineState::Info& _info )
-  {
-    return (info == _info);
-  }
-
-  // Resets state
-  void Reset()
-  {
-    pipeline.Reset();
-  }
-
-  void Initialise()
-  {
-
-  }
-
-  // Compiles state
-  static std::unique_ptr<GraphicsPipelineState> Compile(const GraphicsPipelineState::Info& info)
-  {
-    return nullptr;
-  }
-
-  // state, created when compiled, immutable
-  // renders particular set of objects
-  PipelineRef pipeline;
-};
-
-struct GraphicsDrawCommand
-{
-  GraphicsPipelineState& pipelineState;
-
-  // command buffer/pool
-  CommandPoolRef commandPool;
-  CommandBufferRef commandBuffer;
-  FenceRef fence;
-
-  // resources
-  std::vector<BufferRef>    buffers;
-  std::vector<ImageRef>     images;
-  std::vector<SamplerRef>   samplers;
-  std::vector<ImageViewRef> imageViews;
-
-  // descriptor sets and pool
-  std::vector<DescriptorSetRef> descriptorSets;
-  DescriptorPoolRef             descriptorPool;
-};
-
 struct Controller::Impl
 {
-
-
-  struct State
-  {
-    ShaderRef                     vertexShader;
-    ShaderRef                     fragmentShader;
-    DescriptorPoolRef             descriptorPool;
-    PipelineRef                   pipeline;
-    BufferRef                     vertexBuffer;
-    BufferRef                     uniformBuffer0;
-    BufferRef                     uniformBuffer1; // clip matrix
-    std::vector<DescriptorSetRef> descriptorSets;
-    CommandPoolRef                commandPool;
-    CommandBufferRef              drawCommand;
-
-    std::vector<CommandBufferRef> drawCommandPool; // max 1024 secondary buffers
-    uint32_t                      drawPoolIndex{0u};
-  };
-
   Impl( Controller& owner, Dali::Graphics::Vulkan::Graphics& graphics )
   : mGraphics( graphics ),
     mOwner( owner ),
@@ -168,180 +66,20 @@ struct Controller::Impl
 
   // TODO: @todo this function initialises basic buffers, shaders and pipeline
   // for the prototype ONLY
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-larger-than="
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wframe-larger-than="
   bool Initialise()
   {
     // Create factories
     mShaderFactory = std::make_unique<VulkanAPI::ShaderFactory>( mGraphics );
     mTextureFactory = std::make_unique<VulkanAPI::TextureFactory>( mGraphics );
+    mBufferFactory = std::make_unique<VulkanAPI::BufferFactory>( mOwner );
 
-    mDebugPipelineState.vertexShader = Shader::New( mGraphics, VSH_CODE.data(), VSH_CODE.size() );
-
-    mDebugPipelineState.fragmentShader = Shader::New( mGraphics, FSH_CODE.data(), FSH_CODE.size() );
-
-    mDebugPipelineState.descriptorPool = CreateDescriptorPool();
-
-    const float halfWidth  = 0.5f;
-    const float halfHeight = 0.5f;
-    //#if 0
-    const vec3 VERTICES[4] = {
-      {halfWidth, halfHeight, 0.0f},
-      {halfWidth, -halfHeight, 0.0f},
-      {-halfWidth, halfHeight, 0.0f},
-      {-halfWidth, -halfHeight, 0.0f},
-    };
-
-    mDebugPipelineState.vertexBuffer = Buffer::New( mGraphics, sizeof( VERTICES[0] ) * 4, Buffer::Type::VERTEX );
-    auto& defaultAllocator           = mGraphics.GetDeviceMemoryManager().GetDefaultAllocator();
-    mDebugPipelineState.vertexBuffer->BindMemory(
-      defaultAllocator.Allocate( mDebugPipelineState.vertexBuffer, vk::MemoryPropertyFlagBits::eHostVisible ) );
-
-    auto ptr = mDebugPipelineState.vertexBuffer->GetMemoryHandle()->MapTyped<vec3>();
-    std::copy( VERTICES, VERTICES + 4, ptr );
-    mDebugPipelineState.vertexBuffer->GetMemoryHandle()->Unmap();
-
-    // create command pool
-    mDebugPipelineState.commandPool = CommandPool::New( mGraphics );
-
-    CreatePipeline( mDebugPipelineState );
-
-    // allocated descriptor pool ( 1024 sets, 1024 uniform buffers )
-    auto size = vk::DescriptorPoolSize{}.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
-    mDebugPipelineState.descriptorPool = DescriptorPool::New(
-      mGraphics, vk::DescriptorPoolCreateInfo{}.setPoolSizeCount( 1 ).setPPoolSizes( &size ).setMaxSets( 1024 ) );
-
-    mDebugPipelineState.uniformBuffer1 = Buffer::New( mGraphics, sizeof( CLIP_MATRIX ), Buffer::Type::UNIFORM );
-    mDebugPipelineState.uniformBuffer1->BindMemory(
-      mDefaultAllocator.Allocate( mDebugPipelineState.uniformBuffer1, vk::MemoryPropertyFlagBits::eHostVisible ) );
-
-    auto clipPtr = mDebugPipelineState.uniformBuffer1->GetMemoryHandle()->MapTyped<mat4>();
-    std::copy( &CLIP_MATRIX, &CLIP_MATRIX + 1, clipPtr );
-    mDebugPipelineState.uniformBuffer1->GetMemoryHandle()->Unmap();
+    mUboManager = std::make_unique<VulkanAPI::UboManager>( mOwner );
 
     return true;
   }
 
-  PipelineRef CreatePipeline( State& state )
-  {
-    auto pipeline = Pipeline::New( mGraphics );
-
-    pipeline->SetShader( state.vertexShader, Shader::Type::VERTEX );
-    pipeline->SetShader( state.fragmentShader, Shader::Type::FRAGMENT );
-
-    auto size = mGraphics.GetSurface( 0u )->GetSize();
-    pipeline->SetViewport( 0, 0, static_cast<float>( size.width ), static_cast<float>( size.height ) );
-
-    pipeline->SetVertexInputState(
-      std::vector<vk::VertexInputAttributeDescription>{
-        vk::VertexInputAttributeDescription{}.setBinding( 0 ).setOffset( 0 ).setLocation( 0 ).setFormat(
-          vk::Format::eR32G32B32Sfloat )},
-      std::vector<vk::VertexInputBindingDescription>{vk::VertexInputBindingDescription{}
-                                                       .setBinding( 0 )
-                                                       .setStride( sizeof( vec3 ) )
-                                                       .setInputRate( vk::VertexInputRate::eVertex )} );
-    pipeline->SetInputAssemblyState( vk::PrimitiveTopology::eTriangleStrip, false );
-
-
-
-    if( !pipeline->Compile() )
-    {
-      pipeline.Reset();
-    }
-
-    state.pipeline = pipeline;
-    return pipeline;
-  }
-
-  void SubmitCommand( Dali::Graphics::API::RenderCommand&& command )
-  {
-    auto& state = mDebugPipelineState;
-
-    const auto& bufferList = command.GetBufferList();
-    auto        drawcalls  = command.GetPrimitiveCount();
-
-    // create pool of commands to be re-recorded
-    if( state.drawCommandPool.empty() )
-    {
-      for( auto i = 0u; i < 1024; ++i )
-      {
-        state.drawCommandPool.push_back( state.commandPool->NewCommandBuffer( false ) );
-      }
-    }
-
-    uint32_t                      stride = sizeof( mat4 ) + sizeof( vec4 ) + sizeof( vec3 );
-    std::vector<CommandBufferRef> executeCommands;
-    for( auto&& buf : bufferList.Get() )
-    {
-      // TODO: @todo implement minimum offset!
-      const uint32_t sizeOfUniformBuffer      = U32( ( buf->GetSize() / drawcalls.Get() ) );
-      const uint32_t uniformBlockOffsetStride = ( ( sizeOfUniformBuffer / 256 ) + 1 ) * 256;
-      const uint32_t uniformBlockMemoryNeeded = U32( uniformBlockOffsetStride * drawcalls.Get() );
-
-      // create buffer if doesn't exist
-      if( !state.uniformBuffer0 )
-      {
-        state.uniformBuffer0 = Buffer::New( mGraphics, uniformBlockMemoryNeeded, Buffer::Type::UNIFORM );
-      }
-      if( state.uniformBuffer0->GetSize() < uniformBlockMemoryNeeded || !state.uniformBuffer0->GetMemoryHandle() )
-      {
-        // allocate and bind memory if needed ( buffer increased size or buffer hasn't been bound yet )
-        state.uniformBuffer0->BindMemory(
-          mDefaultAllocator.Allocate( state.uniformBuffer0, vk::MemoryPropertyFlagBits::eHostVisible ) );
-      }
-
-      // fill memory
-
-      struct UB
-      {
-        mat4 mvp;
-        vec4 color;
-        vec3 size;
-        uint samplerId;
-      } __attribute__( ( aligned( 16 ) ) );
-
-      auto memory = state.uniformBuffer0->GetMemoryHandle();
-      auto outPtr = memory->MapTyped<char>();
-      for( auto i = 0u; i < drawcalls.Get(); ++i )
-      {
-        // copy chunk of data
-        UB* inputData  = ( reinterpret_cast<UB*>( buf->GetDataBase() ) ) + i;
-        UB* outputData = ( reinterpret_cast<UB*>( outPtr + ( i * uniformBlockOffsetStride ) ) );
-        *outputData    = *inputData;
-
-        auto descriptorSets = state.descriptorPool->AllocateDescriptorSets(
-          vk::DescriptorSetAllocateInfo{}.setDescriptorSetCount( 1 ).setPSetLayouts(
-            state.pipeline->GetVkDescriptorSetLayouts().data() ) );
-
-        descriptorSets[0]->WriteUniformBuffer( 0, state.uniformBuffer0, i * uniformBlockOffsetStride, stride );
-        descriptorSets[0]->WriteUniformBuffer( 1, state.uniformBuffer1, 0, state.uniformBuffer1->GetSize() );
-        //if(inputData->samplerId >= 0)
-        {
-          descriptorSets[0]->WriteCombinedImageSampler(2, mTextures[inputData->samplerId]->GetSampler(),
-                                                       mTextures[inputData->samplerId]->GetImageView());
-        }
-
-        // record draw call
-        auto cmdbuf = state.commandPool->NewCommandBuffer( false );
-        cmdbuf->Begin( vk::CommandBufferUsageFlagBits::eRenderPassContinue );
-        cmdbuf->BindVertexBuffer( 0, state.vertexBuffer, 0 );
-        cmdbuf->BindGraphicsPipeline( state.pipeline );
-        cmdbuf->BindDescriptorSets( descriptorSets, 0 );
-        cmdbuf->Draw( 4, 1, 0, 0 );
-        cmdbuf->End();
-
-        executeCommands.push_back( cmdbuf );
-      }
-
-      memory->Unmap();
-
-      // execute buffer
-      mGraphics.GetSwapchainForFBID( 0u )->GetPrimaryCommandBuffer()->ExecuteCommands( executeCommands );
-
-      // break, one pass only
-      break;
-    }
-  }
 #pragma GCC diagnostic pop
   void BeginFrame()
   {
@@ -349,11 +87,6 @@ struct Controller::Impl
 
     auto swapchain = mGraphics.GetSwapchainForFBID( 0u );
     swapchain->AcquireNextFramebuffer();
-
-    // rewind pools
-    mDebugPipelineState.drawPoolIndex = 0u;
-    mDebugPipelineState.descriptorPool->Reset();
-    mDebugPipelineState.commandPool->Reset( true );
   }
 
   void EndFrame()
@@ -362,17 +95,6 @@ struct Controller::Impl
     swapchain->Present();
   }
 
-  DescriptorPoolRef CreateDescriptorPool()
-  {
-    vk::DescriptorPoolSize size;
-    size.setDescriptorCount( 1024 ).setType( vk::DescriptorType::eUniformBuffer );
-
-    // TODO: how to organize this???
-    auto pool = DescriptorPool::New(
-      mGraphics, vk::DescriptorPoolCreateInfo{}.setMaxSets( 1024 ).setPoolSizeCount( 1 ).setPPoolSizes( &size ) );
-    return pool;
-  }
-
   API::TextureFactory& GetTextureFactory() const
   {
     return *(mTextureFactory.get());
@@ -383,75 +105,125 @@ struct Controller::Impl
     return *(mShaderFactory.get());
   }
 
-  // resources
-  std::vector<TextureRef> mTextures;
-  std::vector<ShaderRef>  mShaders;
-
-  // owner objects
-  ObjectOwner<API::Texture>   mTexturesOwner;
-  ObjectOwner<API::Shader>    mShadersOwner;
-
-
-  Graphics&           mGraphics;
-  Controller&         mOwner;
-  GpuMemoryAllocator& mDefaultAllocator;
-
-  State mDebugPipelineState;
-
-  std::unique_ptr<VulkanAPI::TextureFactory> mTextureFactory;
-  std::unique_ptr<VulkanAPI::ShaderFactory> mShaderFactory;
+  API::BufferFactory& GetBufferFactory() const
+  {
+    return *(mBufferFactory.get());
+  }
 
   /**
    * NEW IMPLEMENTACIONE
    */
 
-  void SubmitDraw( const Dali::Graphics::API::BufferInfo& buffer )
+  std::unique_ptr<API::RenderCommand> AllocateRenderCommand()
   {
-    // find pipeline state for this batch
-    auto info = GraphicsPipelineState::Info{};
-
-    //info.vertexShader =
+    return std::make_unique<VulkanAPI::RenderCommand>( mOwner, mGraphics, *(mPipelineCache.get()) );
   }
 
-  void SubmitCommandV2( Dali::Graphics::API::RenderCommand&& command )
+  /**
+   * Submits number of commands in one go ( simiar to vkCmdExecuteCommands )
+   * @param commands
+   */
+  void SubmitCommands( std::vector<Dali::Graphics::API::RenderCommand*> commands )
   {
+    // if there are any scheduled writes
+    if(!mBufferTransferRequests.empty())
+    {
+      for(auto&& req : mBufferTransferRequests )
+      {
+        void* dst = req->dstBuffer->GetMemoryHandle()->Map();
+        memcpy( dst, &*req->srcPtr, req->srcSize );
+        req->dstBuffer->GetMemoryHandle()->Unmap();
+      }
+      mBufferTransferRequests.clear();
+    }
 
-    auto vertexShader = command.GetShader( Dali::Graphics::API::ShaderDetails::PipelineStage::VERTEX );
-    auto fragmentShader = command.GetShader( Dali::Graphics::API::ShaderDetails::PipelineStage::FRAGMENT );
+    std::vector<CommandBufferRef> cmdBufRefs{};
 
-    // get shaders from backend
-    ShaderRef vsh, fsh;
-    if(vertexShader)
+    // Prepare pipelines
+    for( auto&& command : commands )
     {
-      vsh = VulkanAPI::Shader::DownCast( vertexShader.Get() ).GetShader( vk::ShaderStageFlagBits::eVertex );
+      // prepare pipelines
+      auto apiCommand = static_cast<VulkanAPI::RenderCommand*>(command);
+      apiCommand->PreparePipeline();
     }
 
-    if(fragmentShader)
+    // Update uniform buffers
+    for( auto&& command : commands )
     {
-      fsh = VulkanAPI::Shader::DownCast( vertexShader.Get() ).GetShader( vk::ShaderStageFlagBits::eFragment );
+      // prepare pipelines
+      auto apiCommand = static_cast<VulkanAPI::RenderCommand*>(command);
+      apiCommand->UpdateUniformBuffers();
     }
 
-#if 0
-    const auto& bufferList = command.GetBufferList();
-    const auto& bufferVector = bufferList.Get();
+    mUboManager->UnmapAllBuffers();
 
-    for(const auto& bufferInfo : bufferVector )
+    // set up writes
+    for( auto&& command : commands )
     {
-      /*
-      const auto ptr = bufferInfo->GetDataBase();
-      const auto size = bufferInfo->GetSize();
+      //const auto& vertexBufferBindings = command->GetVertexBufferBindings();
+      auto apiCommand = static_cast<VulkanAPI::RenderCommand*>(command);
+
+      //apiCommand->PreparePipeline();
+
+      if( !mCommandPool )
+      {
+        mCommandPool = Vulkan::CommandPool::New( mGraphics );
+      }
+      // start new command buffer
+      auto cmdbuf = mCommandPool->NewCommandBuffer( false );
+      cmdbuf->Reset();
+      cmdbuf->Begin( vk::CommandBufferUsageFlagBits::eRenderPassContinue );
+      cmdbuf->BindGraphicsPipeline( apiCommand->GetPipeline() );
+
+      // bind vertex buffers
+      auto binding = 0u;
+      for( auto&& vb : apiCommand->GetVertexBufferBindings() )
+      {
+        cmdbuf->BindVertexBuffer( binding++, static_cast<const VulkanAPI::Buffer&>(vb.buffer.Get()).GetBufferRef(), vb.offset );
+      }
 
-      SubmitDraw( bufferInfo );
-      */
-      // new render state
+      // note: starting set = 0
+      cmdbuf->BindDescriptorSets( apiCommand->GetDescriptorSets(), 0 );
 
+      // draw
+      const auto& drawCommand = apiCommand->GetDrawCommand();
+      cmdbuf->Draw( drawCommand.vertexCount, drawCommand.instanceCount, drawCommand.firstVertex, drawCommand.firstInstance );
+      cmdbuf->End();
+      cmdBufRefs.emplace_back( cmdbuf );
     }
-#endif
+
+    // execute as secondary buffers
+    mGraphics.GetSwapchainForFBID(0)->GetPrimaryCommandBuffer()
+      ->ExecuteCommands( cmdBufRefs );
+
   }
 
+  // resources
+  std::vector<TextureRef> mTextures;
+  std::vector<ShaderRef>  mShaders;
+  std::vector<BufferRef>  mBuffers;
 
+  // owner objects
+  ObjectOwner<API::Texture>   mTexturesOwner;
+  ObjectOwner<API::Shader>    mShadersOwner;
+  ObjectOwner<API::Buffer>    mBuffersOwner;
 
-  std::vector<GraphicsPipelineState> mStatePerBatchCache;
+  Graphics&           mGraphics;
+  Controller&         mOwner;
+  GpuMemoryAllocator& mDefaultAllocator;
+
+  std::unique_ptr<VulkanAPI::TextureFactory> mTextureFactory;
+  std::unique_ptr<VulkanAPI::ShaderFactory> mShaderFactory;
+  std::unique_ptr<VulkanAPI::BufferFactory> mBufferFactory;
+
+  // todo: should be per thread
+  CommandPoolRef mCommandPool;
+
+  std::vector<std::unique_ptr<VulkanAPI::BufferMemoryTransfer>> mBufferTransferRequests;
+
+  std::unique_ptr<PipelineCache> mPipelineCache;
+
+  std::unique_ptr<VulkanAPI::UboManager> mUboManager;
 
 };
 
@@ -479,12 +251,21 @@ API::Accessor<API::Texture> Controller::CreateTexture( const API::BaseFactory<AP
 
 API::Accessor<API::TextureSet> Controller::CreateTextureSet( const API::BaseFactory<API::TextureSet>& factory )
 {
+
 }
 
 API::Accessor<API::DynamicBuffer> Controller::CreateDynamicBuffer( const API::BaseFactory<API::DynamicBuffer>& factory )
 {
 }
 
+API::Accessor<API::Buffer> Controller::CreateBuffer( const API::BaseFactory<API::Buffer>& factory )
+{
+  auto handle = mImpl->mBuffersOwner.CreateObject( factory );
+  auto bufferRef = static_cast<VulkanAPI::Buffer&>(mImpl->mBuffersOwner[handle]).GetBufferRef();
+  mImpl->mBuffers.push_back( bufferRef );
+  return API::Accessor<API::Buffer>( mImpl->mBuffersOwner, handle);
+}
+
 API::Accessor<API::StaticBuffer> Controller::CreateStaticBuffer( const API::BaseFactory<API::StaticBuffer>& factory )
 {
 }
@@ -524,8 +305,7 @@ void Controller::GetRenderItemList()
 
 void Controller::SubmitCommand( Dali::Graphics::API::RenderCommand&& command )
 {
-  mImpl->SubmitCommand( std::move( command ) );
-  //SubmitCommandTest( std::move( command ) );
+  // not in use
 }
 
 void Controller::BeginFrame()
@@ -548,6 +328,37 @@ API::ShaderFactory& Controller::GetShaderFactory() const
   return mImpl->GetShaderFactory();
 }
 
+API::BufferFactory& Controller::GetBufferFactory() const
+{
+  return mImpl->GetBufferFactory();
+}
+
+Vulkan::Graphics& Controller::GetGraphics() const
+{
+  return mImpl->mGraphics;
+}
+
+void Controller::ScheduleBufferMemoryTransfer( std::unique_ptr<VulkanAPI::BufferMemoryTransfer> transferRequest )
+{
+  mImpl->mBufferTransferRequests.emplace_back( std::move(transferRequest) );
+}
+
+VulkanAPI::UboManager& Controller::GetUboManager()
+{
+  return *mImpl->mUboManager;
+}
+
+void Controller::SubmitCommands( std::vector<API::RenderCommand*> commands )
+{
+  mImpl->SubmitCommands( std::move(commands) );
+}
+
+std::unique_ptr<API::RenderCommand> Controller::AllocateRenderCommand()
+{
+  return mImpl->AllocateRenderCommand();
+}
+
+
 } // namespace Vulkan
 } // namespace Graphics
 } // namespace Dali
index 7b8d4e4..87a5f48 100644 (file)
@@ -25,6 +25,28 @@ namespace Dali
 {
 namespace Graphics
 {
+namespace VulkanAPI
+{
+class UboManager;
+/**
+ * Structure describes deferred memory transfer
+ * Source memory is owned by the buffer and will be discarded
+ * when transfer is completed
+ */
+struct BufferMemoryTransfer
+{
+  BufferMemoryTransfer() = default;
+  ~BufferMemoryTransfer() = default;
+
+  std::unique_ptr<char> srcPtr{ nullptr };
+  uint32_t srcSize{ 0u };
+
+  Vulkan::BufferRef dstBuffer {};
+  uint32_t          dstOffset { 0u };
+};
+
+}
+
 namespace Vulkan
 {
 class Graphics;
@@ -66,6 +88,11 @@ public:
   API::Accessor<API::DynamicBuffer> CreateDynamicBuffer( const API::BaseFactory<API::DynamicBuffer>& factory ) override;
 
   /**
+ * @brief Create a new object
+ */
+  API::Accessor<API::Buffer> CreateBuffer( const API::BaseFactory<API::Buffer>& factory ) override;
+
+  /**
    * @brief Create a new object
    */
   API::Accessor<API::StaticBuffer> CreateStaticBuffer( const API::BaseFactory<API::StaticBuffer>& factory ) override;
@@ -82,6 +109,10 @@ public:
 
   std::unique_ptr<char> CreateBuffer( size_t numberOfElements, size_t elementSize ) override;
 
+  void SubmitCommands( std::vector<API::RenderCommand*> commands ) override;
+
+  std::unique_ptr<API::RenderCommand> AllocateRenderCommand() override;
+
   /**
    * @brief Get a render list
    */
@@ -93,12 +124,25 @@ public:
 
   void EndFrame() override;
 
+
+  // VULKAN only
+
+public:
+
+  Vulkan::Graphics& GetGraphics() const;
+
+  void ScheduleBufferMemoryTransfer( std::unique_ptr<VulkanAPI::BufferMemoryTransfer> transferRequest );
+
+  VulkanAPI::UboManager& GetUboManager();
+
 public:
 
   API::TextureFactory& GetTextureFactory() const override;
 
   API::ShaderFactory& GetShaderFactory() const override;
 
+  API::BufferFactory& GetBufferFactory() const override;
+
 public:
   // not copyable
   Controller( const Controller& ) = delete;
index b4e7bb3..dd3758f 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali/graphics/vulkan/vulkan-descriptor-set.h>
 #include <dali/graphics/vulkan/vulkan-framebuffer.h>
 #include <dali/graphics/vulkan/vulkan-graphics-controller.h>
+#include <dali/graphics/vulkan/vulkan-pipeline-cache.h>
 
 #include <dali/graphics-api/graphics-api-controller.h>
 
@@ -479,6 +480,8 @@ void Graphics::CreateDevice()
       // todo: present queue
     }
   }
+
+  mPipelineDatabase = std::make_unique<PipelineCache>( *this );
 }
 #pragma GCC diagnostic pop
 
index 7230b58..b713d84 100644 (file)
@@ -57,6 +57,7 @@ class CommandPool;
 class DescriptorPool;
 class GpuMemoryManager;
 class Controller;
+class PipelineCache;
 
 struct SwapchainSurfacePair
 {
@@ -191,6 +192,15 @@ private:
 
 private:
   std::unique_ptr<Dali::Graphics::Vulkan::Controller>           mGfxController;
+
+  // TODO: rename
+  std::unique_ptr<PipelineCache>        mPipelineDatabase;
+
+public:
+  PipelineCache& GetPipelineCache()
+  {
+    return *mPipelineDatabase.get();
+  }
 };
 
 } // namespace Vulkan
diff --git a/dali/graphics/vulkan/vulkan-pipeline-cache.cpp b/dali/graphics/vulkan/vulkan-pipeline-cache.cpp
new file mode 100644 (file)
index 0000000..d02b615
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/graphics/vulkan/vulkan-pipeline-cache.h>
+#include <dali/graphics/vulkan/vulkan-graphics.h>
+#include <dali/graphics/vulkan/vulkan-pipeline.h>
+#include <dali/graphics/vulkan/vulkan-shader.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+
+struct PipelineCache::Impl
+{
+  struct PipelineCacheItem
+  {
+
+    PipelineCacheItem( PipelineRef _pipeline, const PipelineDescription& _description )
+      : pipeline(_pipeline), description(_description)
+    {
+
+    }
+    PipelineRef                           pipeline;
+    PipelineDescription                   description;
+  };
+
+  Impl( PipelineCache& pipelineCache, Graphics& graphics )
+  : mPipelineCache( pipelineCache ),
+    mGraphics( graphics )
+  {
+
+  }
+
+
+  /**
+   * Finds suitable cached pipeline based on pipelineInfo
+   * @param pipelineInfo
+   * @return
+   */
+  PipelineRef GetPipeline( const PipelineDescription& description )
+  {
+    for( auto&& item : mPipelines )
+    {
+      if( item.description == description )
+      {
+        return item.pipeline;
+      }
+    }
+    return PipelineRef();
+  }
+
+
+  bool AddPipeline( PipelineRef pipeline, const PipelineDescription& description )
+  {
+    mPipelines.emplace_back( pipeline, description );
+    return true;
+  }
+
+  std::vector<vk::DescriptorSetLayout> GetDescriptorSetLayouts( const PipelineRef& pipeline ) const
+  {
+    auto retval = std::vector<vk::DescriptorSetLayout>{};
+    for( auto&& item : mPipelines )
+    {
+      if( item.pipeline == pipeline )
+      {
+        return item.description.descriptorSetLayouts;
+      }
+    }
+    return retval;
+  }
+
+  ~Impl() = default;
+
+  PipelineCache&  mPipelineCache;
+  Graphics&       mGraphics;
+
+  std::vector<PipelineCacheItem> mPipelines;
+};
+
+PipelineCache::PipelineCache( Graphics& graphics )
+{
+  mImpl = std::make_unique<Impl>( *this, graphics );
+}
+
+PipelineCache::~PipelineCache() = default;
+
+PipelineRef PipelineCache::GetPipeline( const PipelineDescription& desc ) const
+{
+  return mImpl->GetPipeline( desc );
+}
+
+bool PipelineCache::AddPipeline( PipelineRef pipeline, const PipelineDescription& desc )
+{
+  return mImpl->AddPipeline( pipeline,desc );
+}
+
+std::vector<vk::DescriptorSetLayout> PipelineCache::GetDescriptorSetLayouts( const PipelineRef& pipeline ) const
+{
+  return mImpl->GetDescriptorSetLayouts( pipeline );
+}
+
+} // namespace Vulkan
+} // namespace Graphics
+} // namespace Dali
+
diff --git a/dali/graphics/vulkan/vulkan-pipeline-cache.h b/dali/graphics/vulkan/vulkan-pipeline-cache.h
new file mode 100644 (file)
index 0000000..a8bba0b
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef DALI_GRAPHICS_VULKAN_PIPELINE_CACHE_H
+#define DALI_GRAPHICS_VULKAN_PIPELINE_CACHE_H
+
+/*
+ * Copyright (c) 2018 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/graphics/vulkan/vulkan-types.h>
+
+namespace Dali
+{
+namespace Graphics
+{
+namespace Vulkan
+{
+class Graphics;
+
+struct PipelineDescription
+{
+  ShaderRef vertexShader;
+  ShaderRef fragmentShader;
+
+  bool operator==(const PipelineDescription& description) const
+  {
+    return (vertexShader == description.vertexShader) &&
+           (fragmentShader == description.fragmentShader);
+  }
+
+  std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
+};
+
+class PipelineCache
+{
+public:
+  PipelineCache() = default;
+
+  PipelineCache( Graphics& graphics );
+
+  ~PipelineCache();
+
+  PipelineRef GetPipeline( const PipelineDescription& desc ) const;
+
+  bool AddPipeline( PipelineRef pipeline, const PipelineDescription& desc );
+
+  std::vector<vk::DescriptorSetLayout> GetDescriptorSetLayouts( const PipelineRef& pipeline ) const;
+
+private:
+  struct Impl;
+  std::unique_ptr<Impl> mImpl;
+};
+} // namespace Vulkan
+} // namespace Graphics
+} // namespace Dali
+#endif // DALI_GRAPHICS_VULKAN_PIPELINE_CACHE_H
index 5a6b574..ef61706 100644 (file)
@@ -79,7 +79,14 @@ struct Pipeline::Impl
       return vk::Result::eErrorInitializationFailed;
     }
 
-    CreatePipelineLayout();
+    if(!mInfo.layout)
+    {
+      CreatePipelineLayout();
+    }
+    else
+    {
+      mPipelineLayout = mInfo.layout;
+    }
 
     // use default render pass for default framebuffer
     // TODO: swapchain/surface should use vulkan-framebuffer object
@@ -90,15 +97,32 @@ struct Pipeline::Impl
                                 GetCurrentFramebuffer()->GetVkRenderPass());
     }
 
-    SetRasterizationState();
+    if(!mInfo.pRasterizationState)
+    {
+      SetRasterizationState();
+    }
+    else
+    {
+      mRasterizationState = *mInfo.pRasterizationState;
+    }
 
-    SetDepthStencilState();
+    if(!mInfo.pDepthStencilState)
+    {
+      SetDepthStencilState();
+    }
 
-    SetMultisampleState();
+    if(!mInfo.pMultisampleState)
+    {
+      SetMultisampleState();
+    }
 
-    SetColorBlendState();
+    if(!mInfo.pColorBlendState)
+    {
+      SetColorBlendState();
+    }
 
     mInfo.setFlags( vk::PipelineCreateFlagBits::eAllowDerivatives );
+
     // create pipeline
     mPipeline = VkAssert( mGraphics.GetDevice().createGraphicsPipeline( nullptr, mInfo, mGraphics.GetAllocator() ) );
     if(mPipeline)
@@ -263,6 +287,7 @@ struct Pipeline::Impl
 #pragma GCC diagnostic ignored "-Wframe-larger-than="
   void CreatePipelineLayout()
   {
+
     // pull desciptor set layouts from shaders
     auto layoutInfo = vk::PipelineLayoutCreateInfo{};
 
@@ -403,6 +428,8 @@ struct Pipeline::Impl
   // Color blend
   vk::PipelineColorBlendStateCreateInfo             mColorBlendState {};
   vk::PipelineColorBlendAttachmentState             mAttachementNoBlendState {};
+
+
 };
 
 /*********************************************************************
index d2d46f2..e8d6cf6 100644 (file)
@@ -34,7 +34,8 @@ struct Shader::Impl
   Impl( Shader& owner, Graphics& graphics, const vk::ShaderModuleCreateInfo& info ) :
     mOwner( owner ),
     mGraphics( graphics ),
-    mCreateInfo( info )
+    mCreateInfo( info ),
+    mPipelineShaderStage( vk::ShaderStageFlagBits::eAllGraphics )
   {
     mSPIRVShader = SpirV::SPIRVUtils::Parse( info.pCode, info.codeSize, vk::ShaderStageFlagBits::eVertex );
   }
@@ -66,6 +67,7 @@ struct Shader::Impl
   vk::ShaderModuleCreateInfo mCreateInfo;
   vk::ShaderModule mShaderModule;
   std::unique_ptr<SpirV::SPIRVShader> mSPIRVShader;
+  vk::ShaderStageFlagBits mPipelineShaderStage;
 };
 
 /*
@@ -114,6 +116,17 @@ const SpirV::SPIRVShader& Shader::GetSPIRVReflection() const
   return *mImpl->mSPIRVShader;
 }
 
+void Shader::SetExplicitShaderStage( vk::ShaderStageFlagBits shaderStage )
+{
+  mImpl->mPipelineShaderStage = shaderStage;
+}
+
+vk::ShaderStageFlagBits Shader::GetExplicitShaderStage() const
+{
+  return mImpl->mPipelineShaderStage;
+}
+
+
 }
 }
 }
\ No newline at end of file
index 042af6c..5c03607 100644 (file)
@@ -65,7 +65,7 @@ public:
   /**
    *
    */
-  ~Shader();
+  ~Shader() override;
 
   vk::ShaderModule GetVkShaderModule() const;
 
@@ -78,9 +78,13 @@ public:
     return GetVkShaderModule();
   }
 
-public:
+  /**
+   * Sets a unique pipeline stage to be used with the shader
+   * @param shaderStage
+   */
+  void SetExplicitShaderStage( vk::ShaderStageFlagBits shaderStage );
 
-  void SetDescriptorSetLayout( uint32_t set, vk::DescriptorSetLayoutCreateInfo info );
+  vk::ShaderStageFlagBits GetExplicitShaderStage() const;
 
 private:
 
index 0718c4b..86e184f 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali/internal/event/common/stage-impl.h>
 #include <dali/internal/update/manager/update-manager.h>
 
+
 namespace Dali
 {
 namespace Internal
@@ -179,6 +180,8 @@ PropertyBuffer::PropertyBuffer()
 
 void PropertyBuffer::Initialize( Dali::Property::Map& formatMap )
 {
+  // Old
+
   mRenderObject = new Render::PropertyBuffer();
   OwnerPointer< Render::PropertyBuffer > transferOwnership( mRenderObject );
   SceneGraph::AddPropertyBuffer( mEventThreadServices.GetUpdateManager(), transferOwnership );
index 596b72e..2289282 100644 (file)
@@ -48,7 +48,7 @@ class Shader;
 class RenderDataProvider
 {
 public:
-  typedef Dali::Vector< const PropertyBufferDataProvider* > VertexBuffers;
+
   typedef std::vector< Render::Sampler* > Samplers;
 
   /**
@@ -86,7 +86,7 @@ public:
    * Returns the shader
    * @return The shader
    */
-  Shader& GetShader() const;
+  Dali::Internal::SceneGraph::Shader& GetShader() const;
 
   /**
    * Returns the list of samplers
@@ -103,8 +103,8 @@ public:
 private:
 
   const UniformMapDataProvider*       mUniformMapDataProvider;
-  Shader*                             mShader;
-  std::vector<Render::Texture*>    mTextures;
+  Dali::Internal::SceneGraph::Shader* mShader;
+  std::vector<Render::Texture*>       mTextures;
   Samplers                            mSamplers;
 
   // Give Renderer access to our private data to reduce copying vectors on construction.
index 182dd27..f674fb7 100644 (file)
@@ -42,14 +42,6 @@ Geometry::~Geometry()
 {
 }
 
-void Geometry::GlContextCreated( Context& context )
-{
-}
-
-void Geometry::GlContextDestroyed()
-{
-}
-
 void Geometry::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
 {
   mVertexBuffers.PushBack( propertyBuffer );
@@ -77,6 +69,8 @@ void Geometry::RemovePropertyBuffer( const Render::PropertyBuffer* propertyBuffe
   }
 }
 
+
+
 void Geometry::GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex ) const
 {
   attributeLocation.Clear();
@@ -107,12 +101,13 @@ void Geometry::OnRenderFinished()
 }
 
 void Geometry::UploadAndDraw(
-    Context& context,
+    Graphics::API::Controller& controller,
     BufferIndex bufferIndex,
     Vector<GLint>& attributeLocation,
     size_t elementBufferOffset,
     size_t elementBufferCount )
 {
+#if 0
   if( !mHasBeenUpdated )
   {
     // Update buffers
@@ -140,7 +135,7 @@ void Geometry::UploadAndDraw(
     for( unsigned int i = 0; i < count; ++i )
     {
 
-      if( !mVertexBuffers[i]->Update( context ) )
+      if( !mVertexBuffers[i]->Update(  ) )
       {
         //Vertex buffer is not ready ( Size, data or format has not been specified yet )
         return;
@@ -245,6 +240,7 @@ void Geometry::UploadAndDraw(
       context.DisableVertexAttributeArray( attributeLocation[i] );
     }
   }
+#endif
 }
 
 } // namespace SceneGraph
index 7a34462..e503bda 100644 (file)
@@ -25,6 +25,8 @@
 #include <dali/internal/common/owner-pointer.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/gl-defines.h>
+#include <dali/graphics-api/graphics-api-controller.h>
+
 
 namespace Dali
 {
@@ -55,15 +57,6 @@ public:
    */
   ~Geometry();
 
-  /**
-   * Called on Gl Context created
-   */
-  void GlContextCreated( Context& context );
-
-  /**
-   * Called on Gl Context destroyed.
-   */
-  void GlContextDestroyed();
 
   /**
    * Adds a property buffer to the geometry
@@ -123,12 +116,26 @@ public:
    * @param[in] elementBufferOffset The index of first element to draw if index buffer bound
    * @param[in] elementBufferCount Number of elements to draw if index buffer bound, uses whole buffer when 0
    */
-  void UploadAndDraw(Context& context,
+  void UploadAndDraw(Graphics::API::Controller& controller,
                      BufferIndex bufferIndex,
                      Vector<GLint>& attributeLocation,
                      size_t elementBufferOffset,
                      size_t elementBufferCount );
 
+  /**
+   *
+   * @return
+   */
+  const Vector< Render::PropertyBuffer* >& GetVertexBuffers() const
+  {
+    return mVertexBuffers;
+  }
+
+  const Dali::Vector< unsigned short>& GetIndices() const
+  {
+    return mIndices;
+  }
+
 private:
 
   // PropertyBuffers
index 26d86c1..f0fa948 100644 (file)
@@ -17,7 +17,8 @@
 
 #include <dali/internal/render/renderers/render-property-buffer.h>
 #include <dali/internal/event/common/property-buffer-impl.h>  // Dali::Internal::PropertyBuffer
-
+#include <dali/graphics-api/graphics-api-controller.h>
+#include <dali/graphics-api/graphics-api-buffer.h>
 namespace
 {
 
@@ -122,7 +123,9 @@ PropertyBuffer::PropertyBuffer()
  mData(NULL),
  mGpuBuffer(NULL),
  mSize(0),
- mDataChanged(true)
+ mDataChanged(true),
+ mGfxBuffer{ nullptr },
+ mGfxBufferUsage{ Graphics::API::Buffer::UsageHint::ATTRIBUTES }
 {
 }
 
@@ -130,6 +133,11 @@ PropertyBuffer::~PropertyBuffer()
 {
 }
 
+void PropertyBuffer::SetUsage( Graphics::API::Buffer::UsageHint usage )
+{
+  mGfxBufferUsage = usage;
+}
+
 void PropertyBuffer::SetFormat( PropertyBuffer::Format* format )
 {
   mFormat = format;
@@ -143,6 +151,32 @@ void PropertyBuffer::SetData( Dali::Vector<char>* data, size_t size )
   mDataChanged = true;
 }
 
+bool PropertyBuffer::Update( Dali::Graphics::API::Controller& controller )
+{
+  if( !mData || !mFormat || !mSize )
+  {
+    return false;
+  }
+
+  if( mDataChanged || !mGfxBuffer )
+  {
+    if( !mGfxBuffer )
+    {
+      mGfxBuffer = controller.CreateBuffer( controller.GetBufferFactory()
+                                                      .SetUsage( mGfxBufferUsage )
+                                                      .SetSize( GetDataSize() ) );
+    }
+
+    // schedule deferred write
+    mGfxBuffer.Get().Write( mData.Get()->begin(), GetDataSize(), 0u );
+
+    mDataChanged = false;
+  }
+
+  return true;
+}
+
+#if 0
 bool PropertyBuffer::Update( Context& context )
 {
   if( !mData || !mFormat || !mSize )
@@ -169,6 +203,7 @@ bool PropertyBuffer::Update( Context& context )
 
   return true;
 }
+#endif
 
 void PropertyBuffer::BindBuffer(GpuBuffer::Target target)
 {
index b568259..655bfc4 100644 (file)
 #include <dali/internal/common/owner-pointer.h>
 #include <dali/internal/render/renderers/render-sampler.h>
 #include <dali/internal/render/gl-resources/gpu-buffer.h>
+#include <dali/graphics-api/graphics-api-accessor.h>
+#include <dali/graphics-api/graphics-api-buffer.h>
 
 namespace Dali
 {
+namespace Graphics
+{
+namespace API
+{
+class Controller;
+} // API
+} // Graphics
+
 namespace Internal
 {
 namespace Render
@@ -91,11 +101,20 @@ public:
    */
   void BindBuffer(GpuBuffer::Target target);
 
+#if 0
   /**
    * Perform the upload of the buffer only when requiered
    * @param[in] context The GL context
    */
   bool Update( Context& context );
+#endif
+
+  /**
+   * Perform the upload of the buffer only when required
+   * @param controller
+   * @return
+   */
+  bool Update( Dali::Graphics::API::Controller& controller );
 
   /**
    * Enable the vertex attributes for each vertex buffer from the corresponding
@@ -182,6 +201,18 @@ public:
     return mFormat.Get();
   }
 
+  inline void SetGfxObject( Graphics::API::Accessor<Graphics::API::Buffer> gfxObject )
+  {
+    mGfxBuffer = gfxObject;
+  }
+
+  inline Graphics::API::Accessor<Graphics::API::Buffer> GetGfxObject() const
+  {
+    return mGfxBuffer;
+  }
+
+  void SetUsage( Graphics::API::Buffer::UsageHint usage );
+
 private:
   OwnerPointer< PropertyBuffer::Format >  mFormat;    ///< Format of the buffer
   OwnerPointer< Dali::Vector< char > >    mData;      ///< Data
@@ -189,6 +220,10 @@ private:
 
   size_t mSize;       ///< Number of Elements in the buffer
   bool mDataChanged;  ///< Flag to know if data has changed in a frame
+
+  // GRAPHICS
+  Graphics::API::Accessor<Graphics::API::Buffer> mGfxBuffer;
+  Graphics::API::Buffer::UsageHint mGfxBufferUsage;
 };
 
 } // namespace Render
index a0a4f0f..3f09153 100644 (file)
@@ -216,7 +216,6 @@ void Renderer::SetBlending( Context& context, bool blend )
 
 void Renderer::GlContextDestroyed()
 {
-  mGeometry->GlContextDestroyed();
 }
 
 void Renderer::GlCleanup()
@@ -226,8 +225,13 @@ void Renderer::GlCleanup()
 void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program )
 {
   // Check if the map has changed
+
+
+
+#if 0
   DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
 
+
   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
 
   if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) ||
@@ -286,6 +290,8 @@ void Renderer::SetUniforms( BufferIndex bufferIndex, const SceneGraph::NodeDataP
   {
     program.SetSizeUniform3f( sizeLoc, size.x, size.y, size.z );
   }
+#endif
+
 }
 
 void Renderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
@@ -533,7 +539,7 @@ void Renderer::Render( Context& context,
 {
   // TODO: AB: no callig any GL now, to avoid asserts whole function commented out
   return;
-
+#if 0
   // Get the program to use:
   Program* program = mRenderDataProvider->GetShader().GetProgram();
   if( !program )
@@ -586,6 +592,7 @@ void Renderer::Render( Context& context,
                               mIndexedDrawFirstElement,
                               mIndexedDrawElementsCount );
   }
+#endif
 }
 
 void Renderer::SetSortAttributes( BufferIndex bufferIndex,
index 1aaf046..9be2e45 100644 (file)
@@ -369,6 +369,16 @@ public:
    */
   void SetSortAttributes( BufferIndex bufferIndex, SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes ) const;
 
+  inline const SceneGraph::RenderDataProvider& GetRenderDataProvider() const
+  {
+    return *mRenderDataProvider.Get();
+  };
+
+  inline const Geometry* GetRenderGeometry() const
+  {
+    return mGeometry;
+  };
+
 private:
 
   struct UniformIndexMap;
index 9e0d795..00a28e9 100644 (file)
@@ -69,7 +69,7 @@ void Shader::SetGfxObject( const Graphics::API::Accessor<Graphics::API::Shader>&
   mGfxShader = shader;
 }
 
-const Graphics::API::Accessor<Graphics::API::Shader>& Shader::GetGfxObject() const
+Graphics::API::Accessor<Graphics::API::Shader>& Shader::GetGfxObject()
 {
   return mGfxShader;
 }
index 6176506..3bfd542 100644 (file)
@@ -112,7 +112,7 @@ public:
 
   void SetGfxObject( const Graphics::API::Accessor<Graphics::API::Shader>& shader );
 
-  const Graphics::API::Accessor<Graphics::API::Shader>& GetGfxObject() const;
+  Graphics::API::Accessor<Graphics::API::Shader>& GetGfxObject();
 
   /**
    * Get the program built for this shader
index f365ff3..d63c823 100644 (file)
@@ -18,6 +18,9 @@
 // CLASS HEADER
 #include <dali/internal/update/graphics/graphics-algorithms.h>
 #include <dali/internal/update/rendering/scene-graph-texture-set.h>
+#include <dali/internal/render/renderers/render-geometry.h>
+#include <dali/internal/render/renderers/render-property-buffer.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
 #include <glm/glm.hpp>
 // EXTERNAL INCLUDES
 
 #include <dali/graphics-api/graphics-api-frame.h>
 #include <dali/graphics-api/graphics-api-render-command.h>
 
+
 // INTERNAL INCLUDES
 #include <dali/internal/common/buffer-index.h>
 #include <dali/internal/render/common/render-instruction-container.h>
 #include <dali/internal/render/common/render-instruction.h>
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
 namespace Dali
 {
 namespace Internal
@@ -38,62 +47,117 @@ namespace SceneGraph
 {
 namespace
 {
+Graphics::API::RenderCommand& BuildRenderCommand(
+  Graphics::API::Controller&           graphics,
+  Graphics::API::Frame&                frame,
+  BufferIndex                          bufferIndex,
+
+  Matrix                               viewProjection,
+  const RenderList&                    renderItemList,
+  Graphics::API::RenderCommand&        command
+)
+{
+  /*
+  // per item/renderer
+  //const auto& renderer = renderItemList.GetRenderer(0);
+  const auto& item = renderItemList.GetItem(0);
+
+  // scenegraph renderer should have complete data
+  const auto sgRenderer = item.mNode->GetRendererAt(0);
+
+
+  const auto& renderer = *item.mRenderer;
+  const auto& dataProviderConst = renderer.GetRenderDataProvider();
+  auto& dataProvider = const_cast<RenderDataProvider&>( dataProviderConst );
+  const auto& uniformMap = dataProvider.GetUniformMap().GetUniformMap( bufferIndex );
+
+  // get resources
+  const auto& shader = sgRenderer->GetShader();
+  const auto& textures = sgRenderer->GetTextures();
+  // todo: samplers
+  //const auto& samplers = sgRenderer->Get;
+
+
+  // prepare vertex buffers
+  const auto& vertexBuffers = sgRenderer->GetGeometry()->GetVertexBuffers();
+  std::vector<Graphics::API::RenderCommand::VertexAttributeBufferBinding> vertexAttributeBindings;
+  auto attribLocation = 0u;
+  auto bindingIndex = 0u;
+
+  for( auto&& vertexBuffer : vertexBuffers )
+  {
+    auto attributeCountInForBuffer = vertexBuffer->GetAttributeCount();
+
+    for( auto i = 0u; i < attributeCountInForBuffer; ++i )
+    {
+      // create binding per attribute
+      auto binding = Graphics::API::RenderCommand::VertexAttributeBufferBinding{}
+        .SetOffset( (vertexBuffer->GetFormat()->components[i]).offset )
+        .SetBinding( bindingIndex )
+        .SetBuffer( vertexBuffer->GetGfxObject() )
+        .SetInputAttributeRate( Graphics::API::RenderCommand::InputAttributeRate::PER_VERTEX )
+        .SetLocation( attribLocation + i )
+        .SetStride( vertexBuffer->GetFormat()->size );
+
+      vertexAttributeBindings.emplace_back( std::move(binding) );
+    }
+  }
+
+  // prepare uniforms
+  auto gfxShader = shader.GetGfxObject();
+
+  // find mapped uniforms
+*/
+  return command;
+}
+
+static constexpr float CLIP_MATRIX_DATA[] = {
+  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f
+};
+static const Matrix CLIP_MATRIX(CLIP_MATRIX_DATA);
+
+
 void SubmitRenderItemList( Graphics::API::Controller&           graphics,
                            Graphics::API::Frame&                frame,
                            BufferIndex                          bufferIndex,
                            Graphics::API::RenderCommandBuilder& commandBuilder,
                            Matrix                               viewProjection,
+                           RenderInstruction&                   instruction,
                            const RenderList&                    renderItemList )
 {
   // TODO: @todo Set shaders and other properties
   //commandBuilder.Set( );
 
   // TODO: @todo Clipping...
-  using InternalTextureSet = Dali::Internal::SceneGraph::TextureSet;
+  //using InternalTextureSet = Dali::Internal::SceneGraph::TextureSet;
   auto numberOfRenderItems = renderItemList.Count();
 
-  using DataT = struct
-  {
-    Matrix  world;
-    Vector4 color;
-    Vector3 size;
-    uint32_t samplerId;
-  } __attribute__((aligned(16)));
-
-  auto uniformBuffer = graphics.CreateBuffer<DataT>( numberOfRenderItems );
-  auto data = uniformBuffer->GetData();
-
-  // TODO: for now texture id is passed through the buffer however
-  // it isn't used by shader but only used to extract which texture
-  // should be used during rendering an item.
-  uint32_t opaqueTextureId = 0;
+  const auto viewMatrix = instruction.GetViewMatrix( bufferIndex );
+  const auto projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
+
+  Matrix vulkanProjectionMatrix;
+  Matrix::Multiply( vulkanProjectionMatrix, *projectionMatrix, CLIP_MATRIX );
+
+  std::vector<Graphics::API::RenderCommand*> commandList;
   for( auto i = 0u; i < numberOfRenderItems; ++i )
   {
     auto& item = renderItemList.GetItem( i );
-
-    if(item.mTextureSet)
-    {
-
-      auto textureSet = const_cast<InternalTextureSet*>(reinterpret_cast<const InternalTextureSet*>(item.mTextureSet));
-
-      auto& texture = textureSet->GetTexture(0)->GetGfxObject();
-      auto textureId = texture.GetHandle();
-
-      opaqueTextureId = uint32_t(textureId); // TODO: AB: hack!!!
-    }
-    Matrix::Multiply( data[i].world, item.mModelMatrix, viewProjection );
-    data[i].color = item.mNode->GetWorldColor( bufferIndex );
-    data[i].size  = item.mSize;
-    data[i].samplerId = opaqueTextureId;
+    auto sgRenderer = item.mNode->GetRendererAt(0);
+    auto& cmd = sgRenderer->GetGfxRenderCommand();
+
+    Matrix mvp;
+    Matrix::Multiply( mvp, item.mModelMatrix, viewProjection );
+    sgRenderer->WriteUniform( "uModelMatrix", item.mModelMatrix );
+    sgRenderer->WriteUniform( "uMvpMatrix", mvp );
+    sgRenderer->WriteUniform( "uViewMatrix", *viewMatrix );
+    sgRenderer->WriteUniform( "uModelViewMatrix", item.mModelViewMatrix );
+    sgRenderer->WriteUniform( "uProjection", vulkanProjectionMatrix );
+    sgRenderer->WriteUniform( "uSize", item.mSize );
+    sgRenderer->WriteUniform( "uColor", item.mNode->GetWorldColor( bufferIndex ));
+    commandList.push_back( &cmd  );
   }
-  commandBuilder.Set( Graphics::API::PrimitiveCount{numberOfRenderItems} );
-
-  auto buffers = std::vector<Graphics::API::BufferInfo>{};
-  buffers.emplace_back(std::move(uniformBuffer));
 
-  commandBuilder.Set( Graphics::API::BufferList{std::move(buffers)} );
-  auto cmd = commandBuilder.Build();
-  graphics.SubmitCommand( std::move(cmd) );
+  graphics.SubmitCommands( std::move(commandList) );
 }
 
 void SubmitInstruction( Graphics::API::Controller& graphics,
@@ -103,7 +167,7 @@ void SubmitInstruction( Graphics::API::Controller& graphics,
 {
   using namespace Graphics::API;
 
-  // Create constant buffer with static uniforms: view matrix, progrjection matrix
+  // Create constant buffer with static uniforms: view matrix, projection matrix
 
   // TODO: @todo: buffer for constant uniforms
   /*
@@ -123,7 +187,7 @@ void SubmitInstruction( Graphics::API::Controller& graphics,
   for( auto i = 0u; i < numberOfRenderLists; ++i )
   {
     SubmitRenderItemList(
-      graphics, frame, bufferIndex, commandBuilder, viewProjection, *instruction.GetRenderList( i ) );
+      graphics, frame, bufferIndex, commandBuilder, viewProjection, instruction, *instruction.GetRenderList( i ) );
   }
 }
 } // namespace
@@ -135,6 +199,7 @@ void SubmitRenderInstructions( Graphics::API::Controller&  graphics,
   auto frame = Graphics::API::Frame{};
   graphics.BeginFrame();
 
+
   auto numberOfInstructions = renderInstructions.Count( bufferIndex );
   for( size_t i = 0; i < numberOfInstructions; ++i )
   {
@@ -149,3 +214,5 @@ void SubmitRenderInstructions( Graphics::API::Controller&  graphics,
 } // namespace SceneGraph
 } // namespace Internal
 } // namespace Dali
+
+#pragma GCC diagnostic pop
index fe0f3a3..882df7e 100644 (file)
@@ -68,6 +68,9 @@
 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
 
+#include <dali/graphics-api/graphics-api-buffer-factory.h>
+#include <dali/graphics-api/graphics-api-buffer.h>
+
 // Un-comment to enable node tree debug logging
 //#define NODE_TREE_LOGGING 1
 
@@ -165,6 +168,54 @@ void SortSiblingNodesRecursively( Node& node )
 
 } // unnamed namespace
 
+//@todo: find better place for it
+// for now we don't want to spam with new shaders
+struct ShaderCache
+{
+  explicit ShaderCache( Dali::Graphics::API::Controller& _controller )
+  : controller( _controller )
+  {
+
+  }
+  struct Item
+  {
+    Item() = default;
+    ~Item() = default;
+    Dali::Graphics::API::Accessor<Dali::Graphics::API::Shader> shader{ nullptr };
+    Dali::Graphics::API::ShaderDetails::ShaderSource           vertexSource{""};
+    Dali::Graphics::API::ShaderDetails::ShaderSource           fragmentSource{""};
+  };
+
+  std::vector<Item> items;
+
+  Dali::Graphics::API::Accessor<Dali::Graphics::API::Shader> GetShader(
+    const Dali::Graphics::API::ShaderDetails::ShaderSource& vsh,
+    const Dali::Graphics::API::ShaderDetails::ShaderSource& fsh
+  )
+  {
+    for( auto&& item : items )
+    {
+      if( item.vertexSource == vsh && item.fragmentSource == fsh )
+      {
+        return item.shader;
+      }
+    }
+    auto shaderRef =
+           controller.CreateShader( controller.GetShaderFactory()
+                                              .SetShaderModule( Graphics::API::ShaderDetails::PipelineStage::VERTEX,
+                                                                Graphics::API::ShaderDetails::Language::SPIRV_1_0,
+                                                                vsh )
+                                              .SetShaderModule( Graphics::API::ShaderDetails::PipelineStage::FRAGMENT,
+                                                                Graphics::API::ShaderDetails::Language::SPIRV_1_0,
+                                                                fsh )
+           );
+    items.emplace_back( Item() = { shaderRef, vsh, fsh } );
+    return shaderRef;
+  }
+
+  Dali::Graphics::API::Controller& controller;
+};
+
 /**
  * Structure to contain UpdateManager internal data
  */
@@ -210,7 +261,8 @@ struct UpdateManager::Impl
     animationFinishedDuringUpdate( false ),
     previousUpdateScene( false ),
     renderTaskWaiting( false ),
-    renderersAdded( false )
+    renderersAdded( false ),
+    shaderCache( graphics.GetController() )
   {
     sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
 
@@ -317,6 +369,7 @@ struct UpdateManager::Impl
   bool                                 renderTaskWaiting;             ///< A REFRESH_ONCE render task is waiting to be rendered
   bool                                 renderersAdded;                ///< Flag to keep track when renderers have been added to avoid unnecessary processing
 
+  ShaderCache                          shaderCache;
 
 private:
 
@@ -523,20 +576,12 @@ void UpdateManager::RemoveShader( Shader* shader )
 void UpdateManager::SetShaderProgram( Shader* shader,
                                       Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
 {
-  auto& controller = mImpl->graphics.GetController();
-
   // TODO: for now we will use hardcoded binary SPIRV shaders which will replace anything
   // that is passed by the caller
 #ifdef DEBUG_OVERRIDE_VULKAN_SHADER
-  auto shaderRef =
-         controller.CreateShader( controller.GetShaderFactory()
-        .SetShaderModule( Graphics::API::ShaderDetails::PipelineStage::VERTEX,
-                          Graphics::API::ShaderDetails::Language::SPIRV_1_0,
-                          Graphics::API::ShaderDetails::ShaderSource( VSH_CODE ))
-        .SetShaderModule( Graphics::API::ShaderDetails::PipelineStage::FRAGMENT,
-                          Graphics::API::ShaderDetails::Language::SPIRV_1_0,
-                          Graphics::API::ShaderDetails::ShaderSource( FSH_CODE ))
-         );
+
+  auto shaderRef = mImpl->shaderCache.GetShader( Graphics::API::ShaderDetails::ShaderSource( VSH_IMAGE_VISUAL_CODE ),
+                                                 Graphics::API::ShaderDetails::ShaderSource( FSH_IMAGE_VISUAL_CODE ));
 
 #else
   auto shaderRef =
@@ -819,7 +864,8 @@ void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
     //Apply constraints
     ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
 
-    mImpl->renderers[i]->PrepareRender( bufferIndex );
+    //mImpl->renderers[i]->PrepareRender( bufferIndex );
+    mImpl->renderers[i]->PrepareRender( mImpl->graphics.GetController(), bufferIndex );
   }
 }
 
@@ -1164,6 +1210,7 @@ void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer
   new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::RemovePropertyBuffer, propertyBuffer );
 }
 
+#if 0
 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
 {
   // Message has ownership of format while in transit from update -> render
@@ -1175,7 +1222,21 @@ void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuf
   // Construct message in the render queue memory; note that delete should not be called on the return value
   new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
 }
+#endif
+
+void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
+{
+  // todo: may not be needed yet
+  // Message has ownership of format while in transit from update -> render
+  //auto& controller = GetGraphicsController();
+  //controller.CreateBuffer( controller.GetBufferFactory()
+  //.SetSize( format->size * format->components ))
 
+  // set format directly, on the update thread
+  propertyBuffer->SetFormat( format.Release() );
+}
+
+#if 0
 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
 {
   // Message has ownership of format while in transit from update -> render
@@ -1187,9 +1248,21 @@ void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffe
   // Construct message in the render queue memory; note that delete should not be called on the return value
   new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
 }
+#endif
+
+void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
+{
+  auto& controller = GetGraphicsController();
+  auto buffer = controller.CreateBuffer( controller.GetBufferFactory()
+                  .SetSize( uint32_t(propertyBuffer->GetFormat()->size * size) )
+                  .SetUsage(Graphics::API::Buffer::UsageHint::ATTRIBUTES ));
+  propertyBuffer->SetGfxObject( buffer );
+  propertyBuffer->SetData( data.Release(), size );
+}
 
 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
 {
+
   // Message has ownership of format while in transit from update -> render
   typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
 
@@ -1235,6 +1308,7 @@ void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uns
 
 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
 {
+  /*
   typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
 
   // Reserve some memory inside the render queue
@@ -1242,17 +1316,21 @@ void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::Prop
 
   // Construct message in the render queue memory; note that delete should not be called on the return value
   new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
+   */
+  geometry->RemovePropertyBuffer( propertyBuffer );
 }
 
 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
 {
-  typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
+  //typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
 
   // Reserve some memory inside the render queue
-  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+  //unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
 
   // Construct message in the render queue memory; note that delete should not be called on the return value
-  new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
+  //new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
+
+  geometry->AddPropertyBuffer( propertyBuffer );
 }
 
 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
@@ -1355,6 +1433,11 @@ void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameB
   new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
 }
 
+Graphics::API::Controller& UpdateManager::GetGraphicsController() const
+{
+  return mImpl->graphics.GetController();
+}
+
 } // namespace SceneGraph
 
 } // namespace Internal
index efbb11a..71c3978 100644 (file)
@@ -42,6 +42,7 @@
 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
 #include <dali/internal/update/rendering/scene-graph-renderer.h>    // for OwnerPointer< Renderer >
 #include <dali/internal/update/rendering/scene-graph-texture-set.h> // for OwnerPointer< TextureSet >
+#include <dali/graphics-api/graphics-api-controller.h>
 
 namespace Dali
 {
@@ -552,6 +553,8 @@ public:
    */
   void AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int face );
 
+  Graphics::API::Controller& GetGraphicsController() const;
+
 public:
 
   /**
index 715a83f..7fbced7 100644 (file)
  * limitations under the License.
  */
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
 // CLASS HEADER
 #include "scene-graph-renderer.h"
 
 #include <dali/internal/render/shaders/program.h>
 #include <dali/internal/render/shaders/scene-graph-shader.h>
 
+#include <dali/graphics-api/graphics-api-controller.h>
+#include <dali/graphics-api/graphics-api-render-command.h>
+#include <dali/graphics-api/graphics-api-shader.h>
+#include <dali/graphics-api/graphics-api-shader-details.h>
+
+#include <cstring>
+
+
+namespace
+{
+
+/**
+ * Helper to set view and projection matrices once per program
+ * @param program to set the matrices to
+ * @param modelMatrix to set
+ * @param viewMatrix to set
+ * @param projectionMatrix to set
+ * @param modelViewMatrix to set
+ * @param modelViewProjectionMatrix to set
+ */
+inline void SetMatrices(
+                         const Dali::Matrix& modelMatrix,
+                         const Dali::Matrix& viewMatrix,
+                         const Dali::Matrix& projectionMatrix,
+                         const Dali::Matrix& modelViewMatrix )
+{
+
+}
+
+}
+
 namespace // unnamed namespace
 {
 
@@ -143,6 +179,7 @@ Renderer::Renderer()
   mDepthWriteMode( DepthWriteMode::AUTO ),
   mDepthTestMode( DepthTestMode::AUTO ),
   mPremultipledAlphaEnabled( false ),
+  mGfxRenderCommand(),
   mDepthIndex( 0 )
 {
   mUniformMapChanged[0] = false;
@@ -172,8 +209,239 @@ void Renderer::operator delete( void* ptr )
 }
 
 
+void* AllocateUniformBufferMemory( size_t size )
+{
+  return nullptr;
+}
+
+
+
+void Renderer::PrepareRender( Graphics::API::Controller& controller, BufferIndex updateBufferIndex )
+{
+  // prepare all stuff
+  auto gfxShader = mShader->GetGfxObject();
+
+  if( !mGfxRenderCommand )
+  {
+    mGfxRenderCommand = controller.AllocateRenderCommand();
+  }
+
+  /**
+   * Prepare vertex attribute buffer bindings
+   */
+  uint32_t bindingIndex { 0u };
+  uint32_t locationIndex { 0u };
+  auto vertexAttributeBindings = Graphics::API::RenderCommand::NewVertexAttributeBufferBindings();
+  for( auto&& vertexBuffer : mGeometry->GetVertexBuffers() )
+  {
+    auto attributeCountInForBuffer = vertexBuffer->GetAttributeCount();
+
+    // update vertex buffer if necessary
+    vertexBuffer->Update( controller );
+
+    for( auto i = 0u; i < attributeCountInForBuffer; ++i )
+    {
+      // create binding per attribute
+      auto binding = Graphics::API::RenderCommand::VertexAttributeBufferBinding{}
+        .SetOffset( (vertexBuffer->GetFormat()->components[i]).offset )
+        .SetBinding( bindingIndex )
+        .SetBuffer( vertexBuffer->GetGfxObject() )
+        .SetInputAttributeRate( Graphics::API::RenderCommand::InputAttributeRate::PER_VERTEX )
+        .SetLocation( locationIndex + i )
+        .SetStride( vertexBuffer->GetFormat()->size );
+      vertexAttributeBindings.emplace_back( binding );
+    }
+  }
+
+
+
+  /**
+   * REGENERATE UNIFORM MAP
+   */
+  if( mRegenerateUniformMap > UNIFORM_MAP_READY )
+  {
+    if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
+    {
+      CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
+      localMap.Resize(0);
+
+      const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
+      AddMappings( localMap, rendererUniformMap );
+
+      if( mShader )
+      {
+        AddMappings( localMap, mShader->GetUniformMap() );
+      }
+    }
+    else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
+    {
+      // Copy old map into current map
+      CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
+      CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
+
+      localMap.Resize( oldMap.Count() );
+
+      unsigned int index = 0;
+      for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
+      {
+        localMap[index] = *iter;
+      }
+    }
+
+    mUniformMapChanged[updateBufferIndex] = true;
+    mRegenerateUniformMap--;
+  }
+
+
+
+
+  auto& shader = mShader->GetGfxObject().Get();
+  auto uboCount = shader.GetUniformBlockCount();
+
+  auto pushConstantsBindings = Graphics::API::RenderCommand::NewPushConstantsBindings( uboCount );
+
+  // allocate new command ( may be not necessary at all )
+ // mGfxRenderCommand = Graphics::API::RenderCommandBuilder().Build();
+
+  // see if we need to reallocate memory for each UBO
+  // todo: do it only when shader has changed
+  if( mUboMemory.size() != uboCount )
+  {
+    mUboMemory.resize(uboCount);
+  }
+
+  for( auto i = 0u; i < uboCount; ++i )
+  {
+    Graphics::API::ShaderDetails::UniformBlockInfo ubInfo;
+
+    std::cout<<sizeof(ubInfo) << std::endl;
+
+    shader.GetUniformBlock( i, ubInfo );
+
+    if( mUboMemory[i].size() != ubInfo.size )
+    {
+      mUboMemory[i].resize( ubInfo.size );
+    }
+
+    // Set push constant bindings
+    auto &pushBinding = pushConstantsBindings[i];
+    pushBinding.data = mUboMemory[i].data();
+    pushBinding.size = uint32_t(mUboMemory[i].size());
+    pushBinding.binding = ubInfo.binding;
+  }
+
+  // add built-in uniforms
+
+  // write to memory
+  for( auto&& i : mCollectedUniformMap )
+  {
+    for( auto&& j : i )
+    {
+      auto uniformInfo = Graphics::API::ShaderDetails::UniformInfo{};
+      if( shader.GetNamedUniform( j->uniformName, uniformInfo ) )
+      {
+        // write into correct uniform buffer
+        auto dst = (mUboMemory[uniformInfo.bufferIndex].data()+uniformInfo.offset);
+        switch( j->propertyPtr->GetType() )
+        {
+          case Property::Type::FLOAT:
+          case Property::Type::INTEGER:
+          case Property::Type::BOOLEAN:
+          {
+            std::cout << uniformInfo.name << ":["<<uniformInfo.bufferIndex<<"]: " << "Writing 32bit offset: " << uniformInfo.offset << ", size: " << sizeof(float) << std::endl;
+            memcpy( dst, &j->propertyPtr->GetFloat( updateBufferIndex ), sizeof(float) );
+            break;
+          }
+          case Property::Type::VECTOR2:
+          {
+            std::cout << uniformInfo.name << ":["<<uniformInfo.bufferIndex<<"]: " << "Writing vec2 offset: " << uniformInfo.offset << ", size: " << sizeof(Vector2) << std::endl;
+            memcpy( dst, &j->propertyPtr->GetVector2( updateBufferIndex ), sizeof(Vector2) );
+            break;
+          }
+          case Property::Type::VECTOR3:
+          {
+            std::cout << uniformInfo.name << ":["<<uniformInfo.bufferIndex<<"]: " <<  "Writing vec3 offset: " << uniformInfo.offset << ", size: " << sizeof(Vector3) << std::endl;
+            memcpy( dst, &j->propertyPtr->GetVector3( updateBufferIndex ), sizeof(Vector3) );
+            break;
+          }
+          case Property::Type::VECTOR4:
+          {
+            std::cout << uniformInfo.name << ":["<<uniformInfo.bufferIndex<<"]: " << "Writing vec4 offset: " << uniformInfo.offset << ", size: " << sizeof(Vector4) << std::endl;
+            memcpy( dst, &j->propertyPtr->GetVector4( updateBufferIndex ), sizeof(Vector4) );
+            break;
+          }
+          case Property::Type::MATRIX:
+          {
+            std::cout << uniformInfo.name << ":["<<uniformInfo.bufferIndex<<"]: " << "Writing mat4 offset: " << uniformInfo.offset << ", size: " << sizeof(Matrix) << std::endl;
+            memcpy( dst, &j->propertyPtr->GetMatrix( updateBufferIndex ), sizeof(Matrix) );
+            break;
+          }
+          case Property::Type::MATRIX3:
+          {
+            std::cout << uniformInfo.name << ":["<<uniformInfo.bufferIndex<<"]: " << "Writing mat3 offset: " << uniformInfo.offset << ", size: " << sizeof(Matrix3) << std::endl;
+            memcpy( dst, &j->propertyPtr->GetMatrix3( updateBufferIndex ), sizeof(Matrix3) );
+            break;
+          }
+          default:
+          {}
+        }
+      }
+    }
+  }
+
+  /**
+   * Prepare textures
+   */
+  auto textureBindings = Graphics::API::RenderCommand::NewTextureBindings();
+  auto samplers = shader.GetSamplers();
+
+  for( auto i = 0u; i < mTextureSet->GetTextureCount(); ++i )
+  {
+    auto texture = mTextureSet->GetTexture( i );
+    auto gfxTexture = texture->GetGfxObject();
+    auto binding = Graphics::API::RenderCommand::TextureBinding{}
+        .SetBinding( samplers[i].binding )
+        .SetTexture( texture->GetGfxObject() )
+        .SetSampler( nullptr );
+
+    textureBindings.emplace_back( binding );
+  }
+
+  // Build render command
+  // todo: this may be deferred until all render items are sorted, otherwise
+  // certain optimisations cannot be done
+
+  const auto& vb = mGeometry->GetVertexBuffers()[0];
+  //vb->Update()
+  mGfxRenderCommand->PushConstants( std::move(pushConstantsBindings) );
+  mGfxRenderCommand->BindVertexBuffers( std::move(vertexAttributeBindings) );
+  mGfxRenderCommand->BindTextures( std::move(textureBindings) );
+  mGfxRenderCommand->BindRenderState( std::move( Graphics::API::RenderCommand::RenderState{}
+                                       .SetShader( mShader->GetGfxObject() ) ) );
+  mGfxRenderCommand->Draw( std::move(Graphics::API::RenderCommand::DrawCommand{}
+                   .SetFirstVertex(0u)
+                   .SetDrawType( Graphics::API::RenderCommand::DrawType::VERTEX_DRAW )
+                   .SetFirstInstance(0u)
+                   .SetVertexCount( vb->GetElementCount() )
+                   .SetInstanceCount( 1u )));
+
+  std::cout << "done\n";
+}
+
+void Renderer::WriteUniform( const std::string& name, const void* data, uint32_t size )
+{
+  auto& gfxShader = mShader->GetGfxObject().Get();
+  auto uniformInfo = Graphics::API::ShaderDetails::UniformInfo{};
+  if( gfxShader.GetNamedUniform( name, uniformInfo ) )
+  {
+    auto dst = (mUboMemory[uniformInfo.bufferIndex].data()+uniformInfo.offset);
+    memcpy( dst, data, size );
+  }
+}
+
 void Renderer::PrepareRender( BufferIndex updateBufferIndex )
 {
+
   if( mRegenerateUniformMap > UNIFORM_MAP_READY )
   {
     if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
@@ -673,3 +941,5 @@ void Renderer::ObservedObjectDestroyed(PropertyOwner& owner)
 } // namespace SceneGraph
 } // namespace Internal
 } // namespace Dali
+
+#pragma GCC diagnostic pop
\ No newline at end of file
index ee6762d..cc8abd9 100644 (file)
@@ -118,6 +118,11 @@ public:
    */
   void SetGeometry( Render::Geometry* geometry );
 
+  Render::Geometry* GetGeometry() const
+  {
+    return mGeometry;
+  }
+
   /**
    * Set the depth index
    * @param[in] depthIndex the new depth index to use
@@ -248,12 +253,33 @@ public:
    */
   void PrepareRender( BufferIndex updateBufferIndex );
 
+  /**
+   * AB: preparing the command data
+   * @param controller
+   * @param updateBufferIndex
+   */
+  void PrepareRender( class Graphics::API::Controller& controller, BufferIndex updateBufferIndex );
+
   /*
    * Retrieve the Render thread renderer
    * @return The associated render thread renderer
    */
   Render::Renderer& GetRenderer();
 
+  Graphics::API::RenderCommand& GetGfxRenderCommand()
+  {
+    return *mGfxRenderCommand.get();
+  }
+
+  template<class T>
+  void WriteUniform( const std::string& name, const T& data )
+  {
+    WriteUniform( name, &data, sizeof(T) );
+  }
+
+  void WriteUniform( const std::string& name, const void* data, uint32_t size );
+
+
   /**
    * Query whether the renderer is fully opaque, fully transparent or transparent.
    * @param[in] updateBufferIndex The current update buffer index.
@@ -357,6 +383,7 @@ private:
    */
   const Vector4& GetBlendColor() const;
 
+
 private:
 
   CollectedUniformMap          mCollectedUniformMap[2];           ///< Uniform maps collected by the renderer
@@ -384,6 +411,8 @@ private:
   bool                         mUniformMapChanged[2];             ///< Records if the uniform map has been altered this frame
   bool                         mPremultipledAlphaEnabled:1;       ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
 
+  std::vector<std::vector<char>> mUboMemory;                  ///< Transient memory allocated for each UBO
+  std::unique_ptr<Graphics::API::RenderCommand>   mGfxRenderCommand;
 public:
 
   int                          mDepthIndex;                       ///< Used only in PrepareRenderInstructions