Lock uniform buffer only 1 times per each render + minor fixup of uniforms
[platform/core/uifw/dali-core.git] / dali / internal / render / shaders / program.h
index d1047b5..09c5ff8 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_PROGRAM_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -23,7 +23,6 @@
 #include <string>
 
 // INTERNAL INCLUDES
-#include <dali/integration-api/gl-abstraction.h>
 #include <dali/internal/common/const-string.h>
 #include <dali/internal/common/shader-data.h>
 #include <dali/public-api/common/vector-wrapper.h>
@@ -35,14 +34,10 @@ namespace Graphics
 {
 class Controller;
 class Program;
-}
-class Matrix;
+class Reflection;
+} // namespace Graphics
 
-namespace Integration
-{
-class GlAbstraction;
-class ShaderData;
-} // namespace Integration
+class Matrix;
 
 namespace Internal
 {
@@ -50,55 +45,29 @@ class ProgramCache;
 
 /**
  * A program contains a vertex & fragment shader.
- *
- * Program caches some of vertex attribute locations and uniform variable values to reduce unnecessary state changes.
+ * It interfaces to the implementation program and it's reflection.
  */
 class Program
 {
 public:
-  /**
-   * Size of the uniform cache per program
-   * GLES specification states that minimum uniform count for fragment shader
-   * is 16 and for vertex shader 128. We're caching the 16 common ones for now
-   */
-  static const int32_t MAX_UNIFORM_CACHE_SIZE = 16;
-
-  /**
-   * Constant for uniform / attribute not found
-   */
-  static const int32_t NOT_FOUND = -1;
-
-  /**
-   * Vertex attributes
-   */
-  enum AttribType
-  {
-    ATTRIB_UNKNOWN = -1,
-    ATTRIB_POSITION,
-    ATTRIB_TEXCOORD,
-    ATTRIB_TYPE_LAST
-  };
+  using Hash = std::size_t;
 
   /**
-   * Common shader uniform names
+   * Indices of default uniforms
    */
-  enum UniformType
+  enum class DefaultUniformIndex
   {
-    UNIFORM_NOT_QUERIED = -2,
-    UNIFORM_UNKNOWN     = -1,
-    UNIFORM_MVP_MATRIX,
-    UNIFORM_MODELVIEW_MATRIX,
-    UNIFORM_PROJECTION_MATRIX,
-    UNIFORM_MODEL_MATRIX,
-    UNIFORM_VIEW_MATRIX,
-    UNIFORM_NORMAL_MATRIX,
-    UNIFORM_COLOR,
-    UNIFORM_SAMPLER,
-    UNIFORM_SAMPLER_RECT,
-    UNIFORM_EFFECT_SAMPLER,
-
-    UNIFORM_SIZE,
-    UNIFORM_TYPE_LAST
+    MODEL_MATRIX = 0,
+    MVP_MATRIX,
+    VIEW_MATRIX,
+    MODEL_VIEW_MATRIX,
+    NORMAL_MATRIX,
+    PROJECTION_MATRIX,
+    SIZE,
+    COLOR,
+    ACTOR_COLOR,
+
+    COUNT
   };
 
   /**
@@ -107,170 +76,10 @@ public:
    * @param[in] shaderData  A pointer to a data structure containing the program source
    *                        and optionally precompiled binary. If the binary is empty the program bytecode
    *                        is copied into it after compilation and linking)
-   * param[in]  gfxController Reference to valid graphics Controller object
-   * param[in]  gfxProgram Reference to vali graphics Program object
-   * @param[in] modifiesGeometry True if the shader modifies geometry
+   * @param[in]  gfxController Reference to valid graphics Controller object
    * @return pointer to the program
    */
-  static Program* New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController, Graphics::UniquePtr<Graphics::Program>&& gfxProgram, bool modifiesGeometry);
-
-  /**
-   * Takes this program into use
-   */
-  void Use();
-
-  /**
-   * @return true if this program is used currently
-   */
-  bool IsUsed();
-
-  /**
-   * @param [in] type of the attribute
-   * @return the index of the attribute
-   */
-  GLint GetAttribLocation(AttribType type);
-
-  /**
-   * Register an attribute name in our local cache
-   * @param [in] name attribute name
-   * @return the index of the attribute name in local cache
-   */
-  uint32_t RegisterCustomAttribute(ConstString name);
-
-  /**
-   * Gets the location of a pre-registered attribute.
-   * @param [in] attributeIndex of the attribute in local cache
-   * @return the index of the attribute in the GL program
-   */
-  GLint GetCustomAttributeLocation(uint32_t attributeIndex);
-
-  /**
-   * Register a uniform name in our local cache
-   * @param [in] name uniform name
-   * @return the index of the uniform name in local cache
-   */
-  uint32_t RegisterUniform(ConstString name);
-
-  /**
-   * Gets the location of a pre-registered uniform.
-   * Uniforms in list UniformType are always registered and in the order of the enumeration
-   * @param [in] uniformIndex of the uniform in local cache
-   * @return the index of the uniform in the GL program
-   */
-  GLint GetUniformLocation(uint32_t uniformIndex);
-
-  /**
-   * Introspect the newly loaded shader to get the active sampler locations
-   */
-  void GetActiveSamplerUniforms();
-
-  /**
-   * Gets the uniform location for a sampler
-   * @param [in] index The index of the active sampler
-   * @param [out] location The location of the requested sampler
-   * @return true if the active sampler was found
-   */
-  bool GetSamplerUniformLocation(uint32_t index, GLint& location);
-
-  /**
-   * Get the number of active samplers present in the shader
-   * @return The number of active samplers
-   */
-  uint32_t GetActiveSamplerCount() const;
-
-  /**
-   * Sets the uniform value
-   * @param [in] location of uniform
-   * @param [in] value0 as int
-   */
-  void SetUniform1i(GLint location, GLint value0);
-
-  /**
-   * Sets the uniform value
-   * @param [in] location of uniform
-   * @param [in] value0 as int
-   * @param [in] value1 as int
-   * @param [in] value2 as int
-   * @param [in] value3 as int
-   */
-  void SetUniform4i(GLint location, GLint value0, GLint value1, GLint value2, GLint value3);
-
-  /**
-   * Sets the uniform value
-   * @param [in] location of uniform
-   * @param [in] value0 as float
-   */
-  void SetUniform1f(GLint location, GLfloat value0);
-
-  /**
-   * Sets the uniform value
-   * @param [in] location of uniform
-   * @param [in] value0 as float
-   * @param [in] value1 as float
-   */
-  void SetUniform2f(GLint location, GLfloat value0, GLfloat value1);
-
-  /**
-   * Special handling for size as we're using uniform geometry so size is passed on to most programs
-   * but it rarely changes so we can cache it
-   * @param [in] location of uniform
-   * @param [in] value0 as float
-   * @param [in] value1 as float
-   * @param [in] value2 as float
-   */
-  void SetSizeUniform3f(GLint location, GLfloat value0, GLfloat value1, GLfloat value2);
-
-  /**
-   * Sets the uniform value
-   * @param [in] location of uniform
-   * @param [in] value0 as float
-   * @param [in] value1 as float
-   * @param [in] value2 as float
-   */
-  void SetUniform3f(GLint location, GLfloat value0, GLfloat value1, GLfloat value2);
-
-  /**
-   * Sets the uniform value
-   * @param [in] location of uniform
-   * @param [in] value0 as float
-   * @param [in] value1 as float
-   * @param [in] value2 as float
-   * @param [in] value3 as float
-   */
-  void SetUniform4f(GLint location, GLfloat value0, GLfloat value1, GLfloat value2, GLfloat value3);
-
-  /**
-   * Sets the uniform value as matrix. NOTE! we never want GPU to transpose
-   * so make sure your matrix is in correct order for GL.
-   * @param [in] location Location of uniform
-   * @param [in] count Count of matrices
-   * @param [in] value values as float pointers
-   */
-  void SetUniformMatrix4fv(GLint location, GLsizei count, const GLfloat* value);
-
-  /**
-   * Sets the uniform value as matrix. NOTE! we never want GPU to transpose
-   * so make sure your matrix is in correct order for GL.
-   * @param [in] location Location of uniform
-   * @param [in] count Count of matrices
-   * @param [in] value values as float pointers
-   */
-  void SetUniformMatrix3fv(GLint location, GLsizei count, const GLfloat* value);
-
-  /**
-   * Needs to be called when GL context is (re)created
-   */
-  void GlContextCreated();
-
-  /**
-   * Needs to be called when GL context is destroyed
-   */
-  void GlContextDestroyed();
-
-  /**
-   * @return true if this program modifies geometry
-   */
-  bool ModifiesGeometry();
+  static Program* New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController);
 
   /**
    * Set the projection matrix that has currently been sent
@@ -308,100 +117,113 @@ public:
     return mViewMatrix;
   }
 
-  GLuint GetProgramId()
+  [[nodiscard]] Graphics::Program& GetGraphicsProgram() const
   {
-    return mProgramId;
+    return *mGfxProgram;
   }
 
-  [[nodiscard]] Graphics::Program& GetGraphicsProgram() const
+  [[nodiscard]] Graphics::Program* GetGraphicsProgramPtr() const
   {
-    return *mGfxProgram;
+    return mGfxProgram.get();
   }
 
+  void SetGraphicsProgram(Graphics::UniquePtr<Graphics::Program>&& program);
+
+  /**
+   * Retrieves uniform data.
+   * The lookup tries to minimise string comparisons. Ideally, when the hashedName is known
+   * and there are no hash collisions in the reflection it's the most optimal case.
+   *
+   * @param name Name of uniform
+   * @param hashedName Hash value from name or 0 if unknown
+   * @param hashedNameNoArray Hash value from name without array index & trailing string, or 0 if unknown
+   * @param out Reference to output structure
+   *
+   * @return False when uniform is not found or due to hash collision the result is ambiguous
+   */
+  bool GetUniform(const std::string_view& name, Hash hashedName, Hash hashedNameNoArray, Graphics::UniformInfo& out) const;
+
+  /**
+   * Retrieves default uniform
+   * @param[in] defaultUniformIndex index of the uniform
+   * @return Valid pointer to the UniformInfo object or nullptr
+   */
+  [[nodiscard]] const Graphics::UniformInfo* GetDefaultUniform(DefaultUniformIndex defaultUniformIndex) const;
+
 private: // Implementation
   /**
    * Constructor, private so no direct instantiation
    * @param[in] cache where the programs are stored
    * @param[in] shaderData A smart pointer to a data structure containing the program source and binary
-   * @param[in] gfxProgram Graphics Program object
    * @param[in] gfxController Reference to Graphics Controller object
-   * @param[in] modifiesGeometry True if the vertex shader changes geometry
    */
-  Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController, Graphics::UniquePtr<Graphics::Program>&& gfxProgram, bool modifiesGeometry);
+  Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController);
 
 public:
+  Program()               = delete;            ///< default constructor, not defined
+  Program(const Program&) = delete;            ///< copy constructor, not defined
+  Program& operator=(const Program&) = delete; ///< assignment operator, not defined
+
   /**
    * Destructor, non virtual as no virtual methods or inheritance
    */
   ~Program();
 
-private:
-  Program();                          ///< default constructor, not defined
-  Program(const Program&);            ///< copy constructor, not defined
-  Program& operator=(const Program&); ///< assignment operator, not defined
-
+public:
   /**
-   * Load the shader, from a precompiled binary if available, else from source code
+   * Struct ReflectionUniformInfo
+   * Contains details of a single uniform buffer field and/or sampler.
    */
-  void Load();
+  struct ReflectionUniformInfo
+  {
+    size_t                hashValue{0};
+    bool                  hasCollision{false};
+    Graphics::UniformInfo uniformInfo{};
+  };
 
   /**
-   * Unload the shader
+   * Build optimized shader reflection of uniforms
+   * @param graphicsReflection The graphics reflection
    */
-  void Unload();
+  void BuildReflection(const Graphics::Reflection& graphicsReflection);
 
   /**
-   * Compile the shader
-   * @param shaderType vertex or fragment shader
-   * @param shaderId of the shader, returned
-   * @param src of the shader
-   * @return true if the compilation succeeded
+   * Struct UniformBlockMemoryRequirements
+   * Contains details of a uniform blocks memory requirements
    */
-  bool CompileShader(GLenum shaderType, GLuint& shaderId, const char* src);
+  struct UniformBlockMemoryRequirements
+  {
+    uint32_t blockCount;
+    uint32_t totalSizeRequired;
+  };
 
   /**
-   * Links the shaders together to create program
+   * Retrieves uniform blocks requirements
+   *
+   * @return Reference to the valid UniformBlockMemoryRequirements struct
    */
-  void Link();
+  [[nodiscard]] const UniformBlockMemoryRequirements& GetUniformBlocksMemoryRequirements() const
+  {
+    return mUniformBlockRequirements;
+  }
 
-  /**
-   * Frees the shader programs
-   */
-  void FreeShaders();
+private:                           // Data
+  ProgramCache& mCache;            ///< The program cache
+  const Matrix* mProjectionMatrix; ///< currently set projection matrix
+  const Matrix* mViewMatrix;       ///< currently set view matrix
 
-  /**
-   * Resets caches
-   */
-  void ResetAttribsUniformCache();
-
-private:                                         // Data
-  ProgramCache&               mCache;            ///< The program cache
-  Integration::GlAbstraction& mGlAbstraction;    ///< The OpenGL Abstraction layer
-  const Matrix*               mProjectionMatrix; ///< currently set projection matrix
-  const Matrix*               mViewMatrix;       ///< currently set view matrix
-  bool                        mLinked;           ///< whether the program is linked
-  GLuint                      mVertexShaderId;   ///< GL identifier for vertex shader
-  GLuint                      mFragmentShaderId; ///< GL identifier for fragment shader
-  GLuint                      mProgramId;        ///< GL identifier for program
-  Graphics::UniquePtr<Graphics::Program> mGfxProgram; ///< Gfx program
-  Graphics::Controller&       mGfxController;    /// < Gfx controller
-  Internal::ShaderDataPtr     mProgramData;      ///< Shader program source and binary (when compiled & linked or loaded)
-
-  // location caches
-  using NameLocationPair = std::pair<ConstString, GLint>;
-  using Locations        = std::vector<NameLocationPair>;
-
-  Locations          mAttributeLocations;      ///< attribute location cache
-  Locations          mUniformLocations;        ///< uniform location cache
-  std::vector<GLint> mSamplerUniformLocations; ///< sampler uniform location cache
+  Graphics::UniquePtr<Graphics::Program> mGfxProgram;    ///< Gfx program
+  Graphics::Controller&                  mGfxController; /// < Gfx controller
+  Internal::ShaderDataPtr                mProgramData;   ///< Shader program source and binary (when compiled & linked or loaded)
 
   // uniform value caching
-  GLint   mUniformCacheInt[MAX_UNIFORM_CACHE_SIZE];       ///< Value cache for uniforms of single int
-  GLfloat mUniformCacheFloat[MAX_UNIFORM_CACHE_SIZE];     ///< Value cache for uniforms of single float
-  GLfloat mUniformCacheFloat2[MAX_UNIFORM_CACHE_SIZE][2]; ///< Value cache for uniforms of two floats
-  GLfloat mUniformCacheFloat4[MAX_UNIFORM_CACHE_SIZE][4]; ///< Value cache for uniforms of four floats
-  Vector3 mSizeUniformCache;                              ///< Cache value for size uniform
-  bool    mModifiesGeometry;                              ///< True if the program changes geometry
+  Vector3 mSizeUniformCache; ///< Cache value for size uniform
+
+  using UniformReflectionContainer = std::vector<ReflectionUniformInfo>;
+
+  UniformReflectionContainer     mReflection{};                ///< Contains reflection build per program
+  UniformReflectionContainer     mReflectionDefaultUniforms{}; ///< Contains default uniforms
+  UniformBlockMemoryRequirements mUniformBlockRequirements{};  ///< Memory requirements for uniform blocks
 };
 
 } // namespace Internal