Create UBO for uniform buffer bindings
[platform/core/uifw/dali-core.git] / dali / internal / render / shaders / program.h
1 #ifndef DALI_INTERNAL_PROGRAM_H
2 #define DALI_INTERNAL_PROGRAM_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <cstdint> // int32_t, uint32_t
23 #include <string>
24
25 // INTERNAL INCLUDES
26 #include <dali/integration-api/gl-abstraction.h>
27 #include <dali/internal/common/const-string.h>
28 #include <dali/internal/common/shader-data.h>
29 #include <dali/public-api/common/vector-wrapper.h>
30 #include <dali/public-api/object/ref-object.h>
31
32 namespace Dali
33 {
34 namespace Graphics
35 {
36 class Controller;
37 class Program;
38 class Reflection;
39 } // namespace Graphics
40
41 class Matrix;
42
43 namespace Integration
44 {
45 class GlAbstraction;
46 class ShaderData;
47 } // namespace Integration
48
49 namespace Internal
50 {
51 class ProgramCache;
52
53 /**
54  * A program contains a vertex & fragment shader.
55  *
56  * Program caches some of vertex attribute locations and uniform variable values to reduce unnecessary state changes.
57  */
58 class Program
59 {
60 public:
61   /**
62    * Size of the uniform cache per program
63    * GLES specification states that minimum uniform count for fragment shader
64    * is 16 and for vertex shader 128. We're caching the 16 common ones for now
65    */
66   static const int32_t MAX_UNIFORM_CACHE_SIZE = 16;
67
68   /**
69    * Constant for uniform / attribute not found
70    */
71   static const int32_t NOT_FOUND = -1;
72
73   /**
74    * Vertex attributes
75    */
76   enum AttribType
77   {
78     ATTRIB_UNKNOWN = -1,
79     ATTRIB_POSITION,
80     ATTRIB_TEXCOORD,
81     ATTRIB_TYPE_LAST
82   };
83
84   /**
85    * Common shader uniform names
86    */
87   enum UniformType
88   {
89     UNIFORM_NOT_QUERIED = -2,
90     UNIFORM_UNKNOWN     = -1,
91     UNIFORM_MVP_MATRIX,
92     UNIFORM_MODELVIEW_MATRIX,
93     UNIFORM_PROJECTION_MATRIX,
94     UNIFORM_MODEL_MATRIX,
95     UNIFORM_VIEW_MATRIX,
96     UNIFORM_NORMAL_MATRIX,
97     UNIFORM_COLOR,
98     UNIFORM_SAMPLER,
99     UNIFORM_SAMPLER_RECT,
100     UNIFORM_EFFECT_SAMPLER,
101
102     UNIFORM_SIZE,
103     UNIFORM_TYPE_LAST
104   };
105
106   /**
107    * Indices of default uniforms
108    */
109   enum class DefaultUniformIndex
110   {
111     MODEL_MATRIX = 0,
112     MVP_MATRIX,
113     VIEW_MATRIX,
114     MODEL_VIEW_MATRIX,
115     NORMAL_MATRIX,
116     PROJECTION_MATRIX,
117     SIZE,
118     COLOR
119   };
120
121   /**
122    * Creates a new program, or returns a copy of an existing program in the program cache
123    * @param[in] cache where the programs are stored
124    * @param[in] shaderData  A pointer to a data structure containing the program source
125    *                        and optionally precompiled binary. If the binary is empty the program bytecode
126    *                        is copied into it after compilation and linking)
127    * param[in]  gfxController Reference to valid graphics Controller object
128    * param[in]  gfxProgram Reference to vali graphics Program object
129    * @param[in] modifiesGeometry True if the shader modifies geometry
130    * @return pointer to the program
131    */
132   static Program* New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController, Graphics::UniquePtr<Graphics::Program>&& gfxProgram, bool modifiesGeometry);
133
134   /**
135    * Takes this program into use
136    */
137   void Use();
138
139   /**
140    * @return true if this program is used currently
141    */
142   bool IsUsed();
143
144   /**
145    * @param [in] type of the attribute
146    * @return the index of the attribute
147    */
148   GLint GetAttribLocation(AttribType type);
149
150   /**
151    * Register an attribute name in our local cache
152    * @param [in] name attribute name
153    * @return the index of the attribute name in local cache
154    */
155   uint32_t RegisterCustomAttribute(ConstString name);
156
157   /**
158    * Gets the location of a pre-registered attribute.
159    * @param [in] attributeIndex of the attribute in local cache
160    * @return the index of the attribute in the GL program
161    */
162   GLint GetCustomAttributeLocation(uint32_t attributeIndex);
163
164   /**
165    * Register a uniform name in our local cache
166    * @param [in] name uniform name
167    * @return the index of the uniform name in local cache
168    */
169   uint32_t RegisterUniform(ConstString name);
170
171   /**
172    * Gets the location of a pre-registered uniform.
173    * Uniforms in list UniformType are always registered and in the order of the enumeration
174    * @param [in] uniformIndex of the uniform in local cache
175    * @return the index of the uniform in the GL program
176    */
177   GLint GetUniformLocation(uint32_t uniformIndex);
178
179   /**
180    * Introspect the newly loaded shader to get the active sampler locations
181    */
182   void GetActiveSamplerUniforms();
183
184   /**
185    * Gets the uniform location for a sampler
186    * @param [in] index The index of the active sampler
187    * @param [out] location The location of the requested sampler
188    * @return true if the active sampler was found
189    */
190   bool GetSamplerUniformLocation(uint32_t index, GLint& location);
191
192   /**
193    * Get the number of active samplers present in the shader
194    * @return The number of active samplers
195    */
196   uint32_t GetActiveSamplerCount() const;
197
198   /**
199    * Sets the uniform value
200    * @param [in] location of uniform
201    * @param [in] value0 as int
202    */
203   void SetUniform1i(GLint location, GLint value0);
204
205   /**
206    * Sets the uniform value
207    * @param [in] location of uniform
208    * @param [in] value0 as int
209    * @param [in] value1 as int
210    * @param [in] value2 as int
211    * @param [in] value3 as int
212    */
213   void SetUniform4i(GLint location, GLint value0, GLint value1, GLint value2, GLint value3);
214
215   /**
216    * Sets the uniform value
217    * @param [in] location of uniform
218    * @param [in] value0 as float
219    */
220   void SetUniform1f(GLint location, GLfloat value0);
221
222   /**
223    * Sets the uniform value
224    * @param [in] location of uniform
225    * @param [in] value0 as float
226    * @param [in] value1 as float
227    */
228   void SetUniform2f(GLint location, GLfloat value0, GLfloat value1);
229
230   /**
231    * Special handling for size as we're using uniform geometry so size is passed on to most programs
232    * but it rarely changes so we can cache it
233    * @param [in] location of uniform
234    * @param [in] value0 as float
235    * @param [in] value1 as float
236    * @param [in] value2 as float
237    */
238   void SetSizeUniform3f(GLint location, GLfloat value0, GLfloat value1, GLfloat value2);
239
240   /**
241    * Sets the uniform value
242    * @param [in] location of uniform
243    * @param [in] value0 as float
244    * @param [in] value1 as float
245    * @param [in] value2 as float
246    */
247   void SetUniform3f(GLint location, GLfloat value0, GLfloat value1, GLfloat value2);
248
249   /**
250    * Sets the uniform value
251    * @param [in] location of uniform
252    * @param [in] value0 as float
253    * @param [in] value1 as float
254    * @param [in] value2 as float
255    * @param [in] value3 as float
256    */
257   void SetUniform4f(GLint location, GLfloat value0, GLfloat value1, GLfloat value2, GLfloat value3);
258
259   /**
260    * Sets the uniform value as matrix. NOTE! we never want GPU to transpose
261    * so make sure your matrix is in correct order for GL.
262    * @param [in] location Location of uniform
263    * @param [in] count Count of matrices
264    * @param [in] value values as float pointers
265    */
266   void SetUniformMatrix4fv(GLint location, GLsizei count, const GLfloat* value);
267
268   /**
269    * Sets the uniform value as matrix. NOTE! we never want GPU to transpose
270    * so make sure your matrix is in correct order for GL.
271    * @param [in] location Location of uniform
272    * @param [in] count Count of matrices
273    * @param [in] value values as float pointers
274    */
275   void SetUniformMatrix3fv(GLint location, GLsizei count, const GLfloat* value);
276
277   /**
278    * Needs to be called when GL context is (re)created
279    */
280   void GlContextCreated();
281
282   /**
283    * Needs to be called when GL context is destroyed
284    */
285   void GlContextDestroyed();
286
287   /**
288    * @return true if this program modifies geometry
289    */
290   bool ModifiesGeometry();
291
292   /**
293    * Set the projection matrix that has currently been sent
294    * @param matrix to set
295    */
296   void SetProjectionMatrix(const Matrix* matrix)
297   {
298     mProjectionMatrix = matrix;
299   }
300
301   /**
302    * Get the projection matrix that has currently been sent
303    * @return the matrix that is set
304    */
305   const Matrix* GetProjectionMatrix()
306   {
307     return mProjectionMatrix;
308   }
309
310   /**
311    * Set the projection matrix that has currently been sent
312    * @param matrix to set
313    */
314   void SetViewMatrix(const Matrix* matrix)
315   {
316     mViewMatrix = matrix;
317   }
318
319   /**
320    * Get the projection matrix that has currently been sent
321    * @return the matrix that is set
322    */
323   const Matrix* GetViewMatrix()
324   {
325     return mViewMatrix;
326   }
327
328   GLuint GetProgramId()
329   {
330     return mProgramId;
331   }
332
333   [[nodiscard]] Graphics::Program& GetGraphicsProgram() const
334   {
335     return *mGfxProgram;
336   }
337
338   /**
339    * Retrieves uniform data.
340    * The lookup tries to minimise string comparisons. Ideally, when the hashedName is known
341    * and there are no hash collisions in the reflection it's the most optimal case.
342    *
343    * @param name Name of uniform
344    * @param hashedName Hash value from name or 0 if unknown
345    * @param out Reference to output structure
346    *
347    * @return False when uniform is not found or due to hash collision the result is ambiguous
348    */
349   bool GetUniform(const std::string& name, size_t hashedName, Graphics::UniformInfo& out) const;
350
351   /**
352    * Retrieves default uniform
353    * @param[in] defaultUniformIndex index of the uniform
354    * @param[out] outputUniformInfo the reference to UniformInfo object
355    * @return True is uniform found, false otherwise
356    */
357   bool GetDefaultUniform(DefaultUniformIndex defaultUniformIndex, Graphics::UniformInfo& outputUniformInfo) const;
358
359   /**
360    * Retrievs default uniform
361    * @param[in] defaultUniformIndex index of the uniform
362    * @return Valid pointer to the UniformInfo object or nullptr
363    */
364   const Graphics::UniformInfo* GetDefaultUniform(DefaultUniformIndex defaultUniformIndex) const;
365
366 private: // Implementation
367   /**
368    * Constructor, private so no direct instantiation
369    * @param[in] cache where the programs are stored
370    * @param[in] shaderData A smart pointer to a data structure containing the program source and binary
371    * @param[in] gfxProgram Graphics Program object
372    * @param[in] gfxController Reference to Graphics Controller object
373    * @param[in] modifiesGeometry True if the vertex shader changes geometry
374    */
375   Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController, Graphics::UniquePtr<Graphics::Program>&& gfxProgram, bool modifiesGeometry);
376
377 public:
378   /**
379    * Destructor, non virtual as no virtual methods or inheritance
380    */
381   ~Program();
382
383 private:
384   Program();                          ///< default constructor, not defined
385   Program(const Program&);            ///< copy constructor, not defined
386   Program& operator=(const Program&); ///< assignment operator, not defined
387
388   /**
389    * Resets caches
390    */
391   void ResetAttribsUniformCache();
392
393   /**
394    * Struct ReflectionUniformInfo
395    * Contains details of a single uniform buffer field and/or sampler.
396    */
397   struct ReflectionUniformInfo
398   {
399     size_t                hashValue{0};
400     bool                  hasCollision{false};
401     Graphics::UniformInfo uniformInfo{};
402   };
403
404   /**
405    * Build optimized shader reflection of uniforms
406    * @param graphicsReflection The graphics reflection
407    */
408   void BuildReflection(const Graphics::Reflection& graphicsReflection);
409
410 private:                                                    // Data
411   ProgramCache&                          mCache;            ///< The program cache
412   Integration::GlAbstraction&            mGlAbstraction;    ///< The OpenGL Abstraction layer
413   const Matrix*                          mProjectionMatrix; ///< currently set projection matrix
414   const Matrix*                          mViewMatrix;       ///< currently set view matrix
415   GLuint                                 mProgramId;        ///< GL identifier for program
416   Graphics::UniquePtr<Graphics::Program> mGfxProgram;       ///< Gfx program
417   Graphics::Controller&                  mGfxController;    /// < Gfx controller
418   Internal::ShaderDataPtr                mProgramData;      ///< Shader program source and binary (when compiled & linked or loaded)
419
420   // location caches
421   using NameLocationPair = std::pair<ConstString, GLint>;
422   using Locations        = std::vector<NameLocationPair>;
423
424   Locations          mAttributeLocations;      ///< attribute location cache
425   Locations          mUniformLocations;        ///< uniform location cache
426   std::vector<GLint> mSamplerUniformLocations; ///< sampler uniform location cache
427
428   // uniform value caching
429   GLint   mUniformCacheInt[MAX_UNIFORM_CACHE_SIZE];       ///< Value cache for uniforms of single int
430   GLfloat mUniformCacheFloat[MAX_UNIFORM_CACHE_SIZE];     ///< Value cache for uniforms of single float
431   GLfloat mUniformCacheFloat2[MAX_UNIFORM_CACHE_SIZE][2]; ///< Value cache for uniforms of two floats
432   GLfloat mUniformCacheFloat4[MAX_UNIFORM_CACHE_SIZE][4]; ///< Value cache for uniforms of four floats
433   Vector3 mSizeUniformCache;                              ///< Cache value for size uniform
434   bool    mModifiesGeometry;                              ///< True if the program changes geometry
435
436   using UniformReflectionContainer = std::vector<ReflectionUniformInfo>;
437
438   UniformReflectionContainer mReflection{};                ///< Contains reflection build per program
439   UniformReflectionContainer mReflectionDefaultUniforms{}; ///< Contains default uniforms
440 };
441
442 } // namespace Internal
443
444 } // namespace Dali
445
446 #endif // DALI_INTERNAL_PROGRAM_H