Write default uniforms in UBO before the properties in the uniform map
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/renderers/render-renderer.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/graphics-api/graphics-program.h>
23 #include <dali/graphics-api/graphics-types.h>
24 #include <dali/internal/common/image-sampler.h>
25 #include <dali/internal/render/common/render-instruction.h>
26 #include <dali/internal/render/data-providers/node-data-provider.h>
27 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
28 #include <dali/internal/render/gl-resources/context.h>
29 #include <dali/internal/render/renderers/render-sampler.h>
30 #include <dali/internal/render/renderers/render-texture.h>
31 #include <dali/internal/render/renderers/render-vertex-buffer.h>
32 #include <dali/internal/render/renderers/shader-cache.h>
33 #include <dali/internal/render/shaders/program.h>
34 #include <dali/internal/render/shaders/scene-graph-shader.h>
35 #include <dali/internal/update/common/uniform-map.h>
36
37 namespace Dali
38 {
39 namespace Internal
40 {
41 namespace
42 {
43 // Size of uniform buffer page used when resizing
44 constexpr uint32_t UBO_PAGE_SIZE = 8192u;
45
46 // UBO allocation threshold below which the UBO will shrink
47 constexpr auto UBO_SHRINK_THRESHOLD = 0.75f;
48
49 /**
50  * Helper to set view and projection matrices once per program
51  * @param program to set the matrices to
52  * @param modelMatrix to set
53  * @param viewMatrix to set
54  * @param projectionMatrix to set
55  * @param modelViewMatrix to set
56  * @param modelViewProjectionMatrix to set
57  */
58 inline void SetMatrices(Program&      program,
59                         const Matrix& modelMatrix,
60                         const Matrix& viewMatrix,
61                         const Matrix& projectionMatrix,
62                         const Matrix& modelViewMatrix)
63 {
64   GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
65   if(Program::UNIFORM_UNKNOWN != loc)
66   {
67     program.SetUniformMatrix4fv(loc, 1, modelMatrix.AsFloat());
68   }
69   loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX);
70   if(Program::UNIFORM_UNKNOWN != loc)
71   {
72     if(program.GetViewMatrix() != &viewMatrix)
73     {
74       program.SetViewMatrix(&viewMatrix);
75       program.SetUniformMatrix4fv(loc, 1, viewMatrix.AsFloat());
76     }
77   }
78   // set projection matrix if program has not yet received it this frame or if it is dirty
79   loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX);
80   if(Program::UNIFORM_UNKNOWN != loc)
81   {
82     if(program.GetProjectionMatrix() != &projectionMatrix)
83     {
84       program.SetProjectionMatrix(&projectionMatrix);
85       program.SetUniformMatrix4fv(loc, 1, projectionMatrix.AsFloat());
86     }
87   }
88   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
89   if(Program::UNIFORM_UNKNOWN != loc)
90   {
91     program.SetUniformMatrix4fv(loc, 1, modelViewMatrix.AsFloat());
92   }
93
94   loc = program.GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
95   if(Program::UNIFORM_UNKNOWN != loc)
96   {
97     Matrix modelViewProjectionMatrix(false);
98     Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
99     program.SetUniformMatrix4fv(loc, 1, modelViewProjectionMatrix.AsFloat());
100   }
101
102   loc = program.GetUniformLocation(Program::UNIFORM_NORMAL_MATRIX);
103   if(Program::UNIFORM_UNKNOWN != loc)
104   {
105     Matrix3 normalMatrix;
106     normalMatrix = modelViewMatrix;
107     normalMatrix.Invert();
108     normalMatrix.Transpose();
109     program.SetUniformMatrix3fv(loc, 1, normalMatrix.AsFloat());
110   }
111 }
112
113 // Helper to get the vertex input format
114 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
115 {
116   Dali::Graphics::VertexInputFormat type{};
117
118   switch(propertyType)
119   {
120     case Property::NONE:
121     case Property::STRING:
122     case Property::ARRAY:
123     case Property::MAP:
124     case Property::EXTENTS:   // i4?
125     case Property::RECTANGLE: // i4/f4?
126     case Property::ROTATION:
127     {
128       type = Dali::Graphics::VertexInputFormat::UNDEFINED;
129       break;
130     }
131     case Property::BOOLEAN:
132     {
133       type = Dali::Graphics::VertexInputFormat::UNDEFINED; // type = GL_BYTE; @todo new type for this?
134       break;
135     }
136     case Property::INTEGER:
137     {
138       type = Dali::Graphics::VertexInputFormat::INTEGER; // (short)
139       break;
140     }
141     case Property::FLOAT:
142     {
143       type = Dali::Graphics::VertexInputFormat::FLOAT;
144       break;
145     }
146     case Property::VECTOR2:
147     {
148       type = Dali::Graphics::VertexInputFormat::FVECTOR2;
149       break;
150     }
151     case Property::VECTOR3:
152     {
153       type = Dali::Graphics::VertexInputFormat::FVECTOR3;
154       break;
155     }
156     case Property::VECTOR4:
157     {
158       type = Dali::Graphics::VertexInputFormat::FVECTOR4;
159       break;
160     }
161     case Property::MATRIX3:
162     {
163       type = Dali::Graphics::VertexInputFormat::FLOAT;
164       break;
165     }
166     case Property::MATRIX:
167     {
168       type = Dali::Graphics::VertexInputFormat::FLOAT;
169       break;
170     }
171   }
172
173   return type;
174 }
175
176 constexpr Graphics::CullMode ConvertCullFace(Dali::FaceCullingMode::Type mode)
177 {
178   switch(mode)
179   {
180     case Dali::FaceCullingMode::NONE:
181     {
182       return Graphics::CullMode::NONE;
183     }
184     case Dali::FaceCullingMode::FRONT:
185     {
186       return Graphics::CullMode::FRONT;
187     }
188     case Dali::FaceCullingMode::BACK:
189     {
190       return Graphics::CullMode::BACK;
191     }
192     case Dali::FaceCullingMode::FRONT_AND_BACK:
193     {
194       return Graphics::CullMode::FRONT_AND_BACK;
195     }
196   }
197   return Graphics::CullMode::NONE;
198 }
199
200 constexpr Graphics::BlendFactor ConvertBlendFactor(BlendFactor::Type blendFactor)
201 {
202   switch(blendFactor)
203   {
204     case BlendFactor::ZERO:
205       return Graphics::BlendFactor::ZERO;
206     case BlendFactor::ONE:
207       return Graphics::BlendFactor::ONE;
208     case BlendFactor::SRC_COLOR:
209       return Graphics::BlendFactor::SRC_COLOR;
210     case BlendFactor::ONE_MINUS_SRC_COLOR:
211       return Graphics::BlendFactor::ONE_MINUS_SRC_COLOR;
212     case BlendFactor::SRC_ALPHA:
213       return Graphics::BlendFactor::SRC_ALPHA;
214     case BlendFactor::ONE_MINUS_SRC_ALPHA:
215       return Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA;
216     case BlendFactor::DST_ALPHA:
217       return Graphics::BlendFactor::DST_ALPHA;
218     case BlendFactor::ONE_MINUS_DST_ALPHA:
219       return Graphics::BlendFactor::ONE_MINUS_DST_ALPHA;
220     case BlendFactor::DST_COLOR:
221       return Graphics::BlendFactor::DST_COLOR;
222     case BlendFactor::ONE_MINUS_DST_COLOR:
223       return Graphics::BlendFactor::ONE_MINUS_DST_COLOR;
224     case BlendFactor::SRC_ALPHA_SATURATE:
225       return Graphics::BlendFactor::SRC_ALPHA_SATURATE;
226     case BlendFactor::CONSTANT_COLOR:
227       return Graphics::BlendFactor::CONSTANT_COLOR;
228     case BlendFactor::ONE_MINUS_CONSTANT_COLOR:
229       return Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR;
230     case BlendFactor::CONSTANT_ALPHA:
231       return Graphics::BlendFactor::CONSTANT_ALPHA;
232     case BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
233       return Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA;
234   }
235   return Graphics::BlendFactor{};
236 }
237
238 constexpr Graphics::BlendOp ConvertBlendEquation(DevelBlendEquation::Type blendEquation)
239 {
240   switch(blendEquation)
241   {
242     case DevelBlendEquation::ADD:
243       return Graphics::BlendOp::ADD;
244     case DevelBlendEquation::SUBTRACT:
245       return Graphics::BlendOp::SUBTRACT;
246     case DevelBlendEquation::REVERSE_SUBTRACT:
247       return Graphics::BlendOp::REVERSE_SUBTRACT;
248     case DevelBlendEquation::COLOR:
249     case DevelBlendEquation::COLOR_BURN:
250     case DevelBlendEquation::COLOR_DODGE:
251     case DevelBlendEquation::DARKEN:
252     case DevelBlendEquation::DIFFERENCE:
253     case DevelBlendEquation::EXCLUSION:
254     case DevelBlendEquation::HARD_LIGHT:
255     case DevelBlendEquation::HUE:
256     case DevelBlendEquation::LIGHTEN:
257     case DevelBlendEquation::LUMINOSITY:
258     case DevelBlendEquation::MAX:
259     case DevelBlendEquation::MIN:
260     case DevelBlendEquation::MULTIPLY:
261     case DevelBlendEquation::OVERLAY:
262     case DevelBlendEquation::SATURATION:
263     case DevelBlendEquation::SCREEN:
264     case DevelBlendEquation::SOFT_LIGHT:
265       return Graphics::BlendOp{};
266   }
267   return Graphics::BlendOp{};
268 }
269
270 /**
271  * Helper function to calculate the correct alignment of data for uniform buffers
272  * @param dataSize size of uniform buffer
273  * @return aligned offset of data
274  */
275 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
276 {
277   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
278 }
279
280 } // namespace
281
282 namespace Render
283 {
284 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
285                         Render::Geometry*               geometry,
286                         uint32_t                        blendingBitmask,
287                         const Vector4&                  blendColor,
288                         FaceCullingMode::Type           faceCullingMode,
289                         bool                            preMultipliedAlphaEnabled,
290                         DepthWriteMode::Type            depthWriteMode,
291                         DepthTestMode::Type             depthTestMode,
292                         DepthFunction::Type             depthFunction,
293                         StencilParameters&              stencilParameters)
294 {
295   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
296 }
297
298 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
299                    Render::Geometry*               geometry,
300                    uint32_t                        blendingBitmask,
301                    const Vector4&                  blendColor,
302                    FaceCullingMode::Type           faceCullingMode,
303                    bool                            preMultipliedAlphaEnabled,
304                    DepthWriteMode::Type            depthWriteMode,
305                    DepthTestMode::Type             depthTestMode,
306                    DepthFunction::Type             depthFunction,
307                    StencilParameters&              stencilParameters)
308 : mRenderDataProvider(dataProvider),
309   mContext(nullptr),
310   mGeometry(geometry),
311   mProgramCache(nullptr),
312   mUniformIndexMap(),
313   mAttributeLocations(),
314   mUniformsHash(),
315   mStencilParameters(stencilParameters),
316   mBlendingOptions(),
317   mIndexedDrawFirstElement(0),
318   mIndexedDrawElementsCount(0),
319   mDepthFunction(depthFunction),
320   mFaceCullingMode(faceCullingMode),
321   mDepthWriteMode(depthWriteMode),
322   mDepthTestMode(depthTestMode),
323   mUpdateAttributeLocations(true),
324   mPremultipledAlphaEnabled(preMultipliedAlphaEnabled),
325   mShaderChanged(false),
326   mUpdated(true)
327 {
328   if(blendingBitmask != 0u)
329   {
330     mBlendingOptions.SetBitmask(blendingBitmask);
331   }
332
333   mBlendingOptions.SetBlendColor(blendColor);
334 }
335
336 void Renderer::Initialize(Context& context, Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache, Render::UniformBufferManager& uniformBufferManager)
337 {
338   mContext              = &context;
339   mGraphicsController   = &graphicsController;
340   mProgramCache         = &programCache;
341   mShaderCache          = &shaderCache;
342   mUniformBufferManager = &uniformBufferManager;
343 }
344
345 Renderer::~Renderer() = default;
346
347 void Renderer::SetGeometry(Render::Geometry* geometry)
348 {
349   mGeometry                 = geometry;
350   mUpdateAttributeLocations = true;
351 }
352 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
353 {
354   mDrawCommands.clear();
355   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
356 }
357
358 void Renderer::GlContextDestroyed()
359 {
360   mGeometry->GlContextDestroyed();
361 }
362
363 void Renderer::GlCleanup()
364 {
365 }
366
367 void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
368 {
369   // Check if the map has changed
370   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
371
372   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
373
374   if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
375      node.GetUniformMapChanged(bufferIndex) ||
376      mUniformIndexMap.Count() == 0 ||
377      mShaderChanged)
378   {
379     // Reset shader pointer
380     mShaderChanged = false;
381
382     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
383     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
384
385     uint32_t maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
386     mUniformIndexMap.Clear();                                                              // Clear contents, but keep memory if we don't change size
387     mUniformIndexMap.Resize(maxMaps);
388
389     uint32_t mapIndex = 0;
390     for(; mapIndex < uniformMap.Count(); ++mapIndex)
391     {
392       mUniformIndexMap[mapIndex].propertyValue          = uniformMap[mapIndex].propertyPtr;
393       mUniformIndexMap[mapIndex].uniformIndex           = program.RegisterUniform(uniformMap[mapIndex].uniformName);
394       mUniformIndexMap[mapIndex].uniformName            = uniformMap[mapIndex].uniformName;
395       mUniformIndexMap[mapIndex].uniformNameHash        = uniformMap[mapIndex].uniformNameHash;
396       mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMap[mapIndex].uniformNameHashNoArray;
397       mUniformIndexMap[mapIndex].arrayIndex             = uniformMap[mapIndex].arrayIndex;
398     }
399
400     for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
401     {
402       uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
403       bool     found(false);
404       for(uint32_t i = 0; i < uniformMap.Count(); ++i)
405       {
406         if(mUniformIndexMap[i].uniformIndex == uniformIndex)
407         {
408           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
409           found                             = true;
410           break;
411         }
412       }
413
414       if(!found)
415       {
416         mUniformIndexMap[mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
417         mUniformIndexMap[mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
418         mUniformIndexMap[mapIndex].uniformIndex           = uniformIndex;
419         mUniformIndexMap[mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
420         mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
421         mUniformIndexMap[mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
422         ++mapIndex;
423       }
424     }
425
426     mUniformIndexMap.Resize(mapIndex);
427   }
428
429   // The code below is disabled because the uniforms should now be set in the graphics backend.
430
431   /*
432   // Set uniforms in local map
433   for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
434                                      end  = mUniformIndexMap.End();
435       iter != end;
436       ++iter)
437   {
438     SetUniformFromProperty(bufferIndex, program, *iter);
439   }
440
441   GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE);
442   if(-1 != sizeLoc)
443   {
444     program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z);
445   }
446 */
447 }
448
449 void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map)
450 {
451   GLint location = program.GetUniformLocation(map.uniformIndex);
452   if(Program::UNIFORM_UNKNOWN != location)
453   {
454     // switch based on property type to use correct GL uniform setter
455     switch(map.propertyValue->GetType())
456     {
457       case Property::INTEGER:
458       {
459         program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex));
460         break;
461       }
462       case Property::FLOAT:
463       {
464         program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex));
465         break;
466       }
467       case Property::VECTOR2:
468       {
469         Vector2 value(map.propertyValue->GetVector2(bufferIndex));
470         program.SetUniform2f(location, value.x, value.y);
471         break;
472       }
473
474       case Property::VECTOR3:
475       {
476         Vector3 value(map.propertyValue->GetVector3(bufferIndex));
477         program.SetUniform3f(location, value.x, value.y, value.z);
478         break;
479       }
480
481       case Property::VECTOR4:
482       {
483         Vector4 value(map.propertyValue->GetVector4(bufferIndex));
484         program.SetUniform4f(location, value.x, value.y, value.z, value.w);
485         break;
486       }
487
488       case Property::ROTATION:
489       {
490         Quaternion value(map.propertyValue->GetQuaternion(bufferIndex));
491         program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w);
492         break;
493       }
494
495       case Property::MATRIX:
496       {
497         const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
498         program.SetUniformMatrix4fv(location, 1, value.AsFloat());
499         break;
500       }
501
502       case Property::MATRIX3:
503       {
504         const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
505         program.SetUniformMatrix3fv(location, 1, value.AsFloat());
506         break;
507       }
508
509       default:
510       {
511         // Other property types are ignored
512         break;
513       }
514     }
515   }
516 }
517
518 bool Renderer::BindTextures(Program& program, Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
519 {
520   uint32_t textureUnit = 0;
521
522   GLint                          uniformLocation(-1);
523   std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
524   std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
525
526   std::vector<Graphics::TextureBinding> textureBindings;
527   for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()); ++i) // not expecting more than uint32_t of textures
528   {
529     if(textures[i] && textures[i]->GetGraphicsObject())
530     {
531       if(program.GetSamplerUniformLocation(i, uniformLocation))
532       {
533         // if the sampler exists,
534         //   if it's default, delete the graphics object
535         //   otherwise re-initialize it if dirty
536
537         const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
538                                                                 : nullptr);
539
540         boundTextures.PushBack(textures[i]->GetGraphicsObject());
541         const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
542         textureBindings.push_back(textureBinding);
543
544         program.SetUniform1i(uniformLocation, textureUnit); // Get through shader reflection
545         ++textureUnit;
546       }
547     }
548   }
549
550   if(textureBindings.size() > 0)
551   {
552     commandBuffer.BindTextures(textureBindings);
553   }
554
555   // @todo remove check from caller.
556   return true;
557 }
558
559 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
560 {
561   mFaceCullingMode = mode;
562   mUpdated         = true;
563 }
564
565 void Renderer::SetBlendingBitMask(uint32_t bitmask)
566 {
567   mBlendingOptions.SetBitmask(bitmask);
568   mUpdated = true;
569 }
570
571 void Renderer::SetBlendColor(const Vector4& color)
572 {
573   mBlendingOptions.SetBlendColor(color);
574   mUpdated = true;
575 }
576
577 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
578 {
579   mIndexedDrawFirstElement = firstElement;
580   mUpdated                 = true;
581 }
582
583 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
584 {
585   mIndexedDrawElementsCount = elementsCount;
586   mUpdated                  = true;
587 }
588
589 void Renderer::EnablePreMultipliedAlpha(bool enable)
590 {
591   mPremultipledAlphaEnabled = enable;
592   mUpdated                  = true;
593 }
594
595 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
596 {
597   mDepthWriteMode = depthWriteMode;
598   mUpdated        = true;
599 }
600
601 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
602 {
603   mDepthTestMode = depthTestMode;
604   mUpdated       = true;
605 }
606
607 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
608 {
609   return mDepthWriteMode;
610 }
611
612 DepthTestMode::Type Renderer::GetDepthTestMode() const
613 {
614   return mDepthTestMode;
615 }
616
617 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
618 {
619   mDepthFunction = depthFunction;
620   mUpdated       = true;
621 }
622
623 DepthFunction::Type Renderer::GetDepthFunction() const
624 {
625   return mDepthFunction;
626 }
627
628 void Renderer::SetRenderMode(RenderMode::Type renderMode)
629 {
630   mStencilParameters.renderMode = renderMode;
631   mUpdated                      = true;
632 }
633
634 RenderMode::Type Renderer::GetRenderMode() const
635 {
636   return mStencilParameters.renderMode;
637 }
638
639 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
640 {
641   mStencilParameters.stencilFunction = stencilFunction;
642   mUpdated                           = true;
643 }
644
645 StencilFunction::Type Renderer::GetStencilFunction() const
646 {
647   return mStencilParameters.stencilFunction;
648 }
649
650 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
651 {
652   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
653   mUpdated                               = true;
654 }
655
656 int Renderer::GetStencilFunctionMask() const
657 {
658   return mStencilParameters.stencilFunctionMask;
659 }
660
661 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
662 {
663   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
664   mUpdated                                    = true;
665 }
666
667 int Renderer::GetStencilFunctionReference() const
668 {
669   return mStencilParameters.stencilFunctionReference;
670 }
671
672 void Renderer::SetStencilMask(int stencilMask)
673 {
674   mStencilParameters.stencilMask = stencilMask;
675   mUpdated                       = true;
676 }
677
678 int Renderer::GetStencilMask() const
679 {
680   return mStencilParameters.stencilMask;
681 }
682
683 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
684 {
685   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
686   mUpdated                                  = true;
687 }
688
689 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
690 {
691   return mStencilParameters.stencilOperationOnFail;
692 }
693
694 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
695 {
696   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
697   mUpdated                                   = true;
698 }
699
700 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
701 {
702   return mStencilParameters.stencilOperationOnZFail;
703 }
704
705 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
706 {
707   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
708   mUpdated                                   = true;
709 }
710
711 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
712 {
713   return mStencilParameters.stencilOperationOnZPass;
714 }
715
716 void Renderer::Upload()
717 {
718   mGeometry->Upload(*mGraphicsController);
719 }
720
721 void Renderer::Render(Context&                                             context,
722                       BufferIndex                                          bufferIndex,
723                       const SceneGraph::NodeDataProvider&                  node,
724                       const Matrix&                                        modelMatrix,
725                       const Matrix&                                        modelViewMatrix,
726                       const Matrix&                                        viewMatrix,
727                       const Matrix&                                        projectionMatrix,
728                       const Vector3&                                       size,
729                       bool                                                 blend,
730                       Vector<Graphics::Texture*>&                          boundTextures,
731                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
732                       uint32_t                                             queueIndex)
733 {
734   // Before doing anything test if the call happens in the right queue
735   if(mDrawCommands.empty() && queueIndex > 0)
736   {
737     return;
738   }
739
740   // Prepare commands
741   std::vector<DevelRenderer::DrawCommand*> commands;
742   for(auto& cmd : mDrawCommands)
743   {
744     if(cmd.queue == queueIndex)
745     {
746       commands.emplace_back(&cmd);
747     }
748   }
749
750   // Have commands but nothing to be drawn - abort
751   if(!mDrawCommands.empty() && commands.empty())
752   {
753     return;
754   }
755   if(!mGraphicsCommandBuffer)
756   {
757     mGraphicsCommandBuffer = mGraphicsController->CreateCommandBuffer(
758       Graphics::CommandBufferCreateInfo()
759         .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
760       nullptr);
761   }
762   else
763   {
764     mGraphicsCommandBuffer->Reset();
765   }
766
767   auto& commandBuffer = mGraphicsCommandBuffer;
768
769   //Set blending mode
770   if(!mDrawCommands.empty())
771   {
772     blend = (commands[0]->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
773   }
774
775   // Create Shader.
776   // Really, need to have a pipeline cache in implementation.
777   // Get the program to use
778   // The program cache owns the Program object so we don't need to worry about this raw allocation here.
779   ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
780
781   Dali::Graphics::Shader& vertexShader = mShaderCache->GetShader(
782     shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
783     Graphics::PipelineStage::VERTEX_SHADER,
784     shaderData->GetSourceMode());
785
786   Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
787     shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER),
788     Graphics::PipelineStage::FRAGMENT_SHADER,
789     shaderData->GetSourceMode());
790
791   std::vector<Graphics::ShaderState> shaderStates{
792     Graphics::ShaderState()
793       .SetShader(vertexShader)
794       .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
795     Graphics::ShaderState()
796       .SetShader(fragmentShader)
797       .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
798
799   auto createInfo = Graphics::ProgramCreateInfo();
800   createInfo.SetShaderState(shaderStates);
801
802   auto     graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
803   Program* program         = Program::New(*mProgramCache,
804                                   shaderData,
805                                   *mGraphicsController,
806                                   std::move(graphicsProgram),
807                                   (shaderData->GetHints() & Dali::Shader::Hint::MODIFIES_GEOMETRY) != 0x0);
808
809   if(!program)
810   {
811     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
812     return;
813   }
814
815   // Temporarily create a pipeline here - this will be used for transporting
816   // topology, vertex format, attrs, rasterization state
817   mGraphicsPipeline = PrepareGraphicsPipeline(*program, instruction, blend, std::move(mGraphicsPipeline));
818
819   commandBuffer->BindPipeline(*mGraphicsPipeline.get());
820
821   if(DALI_LIKELY(BindTextures(*program, *commandBuffer.get(), boundTextures)))
822   {
823     // Only set up and draw if we have textures and they are all valid
824
825     // The code below is disabled because the uniforms should now be set in the graphics backend.
826
827     /*
828     // set projection and view matrix if program has not yet received them yet this frame
829     SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
830
831     // set color uniform
832     GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
833     if(Program::UNIFORM_UNKNOWN != loc)
834     {
835       const Vector4& color = node.GetRenderColor(bufferIndex);
836       if(mPremultipledAlphaEnabled)
837       {
838         float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
839         program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
840       }
841       else
842       {
843         program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
844       }
845     }
846 */
847
848     BuildUniformIndexMap(bufferIndex, node, size, *program);
849
850     // Create the UBO
851     uint32_t uniformBlockAllocationBytes{0u};
852     uint32_t uniformBlockMaxSize{0u};
853     uint32_t uboOffset{0u};
854
855     auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
856     for(auto i = 0u; i < reflection.GetUniformBlockCount(); ++i)
857     {
858       auto blockSize = GetUniformBufferDataAlignment(reflection.GetUniformBlockSize(i));
859       if(uniformBlockMaxSize < blockSize)
860       {
861         uniformBlockMaxSize = blockSize;
862       }
863       uniformBlockAllocationBytes += blockSize;
864     }
865
866     auto pagedAllocation = ((uniformBlockAllocationBytes / UBO_PAGE_SIZE + 1u)) * UBO_PAGE_SIZE;
867
868     // Allocate twice memory as required by the uniform buffers
869     // todo: memory usage backlog to use optimal allocation
870     if(uniformBlockAllocationBytes && !mUniformBuffer[bufferIndex])
871     {
872       mUniformBuffer[bufferIndex] = std::move(mUniformBufferManager->AllocateUniformBuffer(pagedAllocation));
873     }
874     else if(uniformBlockAllocationBytes && (mUniformBuffer[bufferIndex]->GetSize() < pagedAllocation ||
875                                             (pagedAllocation < uint32_t(float(mUniformBuffer[bufferIndex]->GetSize()) * UBO_SHRINK_THRESHOLD))))
876     {
877       mUniformBuffer[bufferIndex]->Reserve(pagedAllocation);
878     }
879
880     // Clear UBO
881     if(mUniformBuffer[bufferIndex])
882     {
883       mUniformBuffer[bufferIndex]->Fill(0, 0u, 0u);
884     }
885
886     // update the uniform buffer
887     // pass shared UBO and offset, return new offset for next item to be used
888     // don't process bindings if there are no uniform buffers allocated
889     auto ubo = mUniformBuffer[bufferIndex].get();
890     if(ubo)
891     {
892       auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
893       auto  uboCount   = reflection.GetUniformBlockCount();
894       mUniformBufferBindings.resize(uboCount);
895
896       std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
897
898       // Write default uniforms
899       Matrix modelViewProjectionMatrix(false);
900       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
901
902       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *ubo, *bindings, modelMatrix);
903       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *ubo, *bindings, viewMatrix);
904       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *ubo, *bindings, projectionMatrix);
905       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX), *ubo, *bindings, modelViewProjectionMatrix);
906       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *ubo, *bindings, modelViewMatrix);
907
908       // Update normal matrix only when used in the shader
909       Matrix3 normalMatrix(modelViewMatrix);
910       normalMatrix.Invert();
911       normalMatrix.Transpose();
912       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX), *ubo, *bindings, normalMatrix);
913
914       Vector4        finalColor;
915       const Vector4& color = node.GetRenderColor(bufferIndex);
916       if(mPremultipledAlphaEnabled)
917       {
918         float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
919         finalColor  = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
920       }
921       else
922       {
923         finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
924       }
925       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *ubo, *bindings, finalColor);
926
927       // Write uniforms from the uniform map
928       FillUniformBuffers(*program, instruction, *ubo, bindings, uboOffset, bufferIndex);
929
930       // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
931       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *ubo, *bindings, size);
932
933       commandBuffer->BindUniformBuffers(*bindings);
934     }
935
936     bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
937                         // @todo We should detect this case much earlier to prevent unnecessary work
938
939     //@todo manage mDrawCommands in the same way as above command buffer?!
940     if(mDrawCommands.empty())
941     {
942       drawn = mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), mIndexedDrawFirstElement, mIndexedDrawElementsCount);
943     }
944     else
945     {
946       for(auto& cmd : commands)
947       {
948         // @todo This should generate a command buffer per cmd
949         // Tests WILL fail. (Temporarily commented out)
950         mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), cmd->firstIndex, cmd->elementCount);
951       }
952     }
953
954     // Command buffer contains Texture bindings, vertex bindings, index buffer binding, pipeline(vertex format)
955     // @todo We should return the command buffer(s) and let the calling method submit
956     // If not drawn, then don't add command buffer to submit info, and if empty, don't
957     // submit.
958     if(drawn)
959     {
960       Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
961       submitInfo.cmdBuffer.push_back(commandBuffer.get());
962       mGraphicsController->SubmitCommandBuffers(submitInfo);
963     }
964
965     mUpdated = false;
966   }
967 }
968
969 template<class T>
970 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const T& data)
971 {
972   if(uniformInfo && !uniformInfo->name.empty())
973   {
974     WriteUniform(ubo, bindings, *uniformInfo, data);
975     return true;
976   }
977   return false;
978 }
979
980 template<class T>
981 void Renderer::WriteUniform(Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const T& data)
982 {
983   WriteUniform(ubo, bindings, uniformInfo, &data, sizeof(T));
984 }
985
986 void Renderer::WriteUniform(Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
987 {
988   ubo.Write(data, size, bindings[uniformInfo.bufferIndex].offset + uniformInfo.offset);
989 }
990
991 void Renderer::FillUniformBuffers(Program&                                      program,
992                                   const SceneGraph::RenderInstruction&          instruction,
993                                   Render::UniformBuffer&                        ubo,
994                                   std::vector<Graphics::UniformBufferBinding>*& outBindings,
995                                   uint32_t&                                     offset,
996                                   BufferIndex                                   updateBufferIndex)
997 {
998   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
999   auto  uboCount   = reflection.GetUniformBlockCount();
1000
1001   // Setup bindings
1002   uint32_t dataOffset = offset;
1003   for(auto i = 0u; i < uboCount; ++i)
1004   {
1005     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
1006     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
1007     mUniformBufferBindings[i].offset   = dataOffset;
1008
1009     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
1010     mUniformBufferBindings[i].buffer = ubo.GetBuffer();
1011
1012     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
1013                                        end  = mUniformIndexMap.End();
1014         iter != end;
1015         ++iter)
1016     {
1017       // @todo This means parsing the uniform string every frame. Instead, store the array index if present.
1018       int arrayIndex = (*iter).arrayIndex;
1019
1020       auto uniformInfo  = Graphics::UniformInfo{};
1021       auto uniformFound = program.GetUniform((*iter).uniformName.GetCString(),
1022                                              (*iter).uniformNameHashNoArray ? (*iter).uniformNameHashNoArray : (*iter).uniformNameHash,
1023                                              uniformInfo);
1024
1025       if(uniformFound)
1026       {
1027         auto dst = mUniformBufferBindings[uniformInfo.bufferIndex].offset + uniformInfo.offset;
1028
1029         switch((*iter).propertyValue->GetType())
1030         {
1031           case Property::Type::BOOLEAN:
1032           {
1033             ubo.Write(&(*iter).propertyValue->GetBoolean(updateBufferIndex),
1034                       sizeof(bool),
1035                       dst + static_cast<uint32_t>(sizeof(bool)) * arrayIndex);
1036             break;
1037           }
1038           case Property::Type::INTEGER:
1039           {
1040             ubo.Write(&(*iter).propertyValue->GetInteger(updateBufferIndex),
1041                       sizeof(int32_t),
1042                       dst + static_cast<int32_t>(sizeof(int32_t)) * arrayIndex);
1043             break;
1044           }
1045           case Property::Type::FLOAT:
1046           {
1047             ubo.Write(&(*iter).propertyValue->GetFloat(updateBufferIndex),
1048                       sizeof(float),
1049                       dst + static_cast<uint32_t>(sizeof(float)) * arrayIndex);
1050             break;
1051           }
1052           case Property::Type::VECTOR2:
1053           {
1054             ubo.Write(&(*iter).propertyValue->GetVector2(updateBufferIndex),
1055                       sizeof(Vector2),
1056                       dst + static_cast<uint32_t>(sizeof(Vector2)) * arrayIndex);
1057             break;
1058           }
1059           case Property::Type::VECTOR3:
1060           {
1061             ubo.Write(&(*iter).propertyValue->GetVector3(updateBufferIndex),
1062                       sizeof(Vector3),
1063                       dst + static_cast<uint32_t>(sizeof(Vector3)) * arrayIndex);
1064             break;
1065           }
1066           case Property::Type::VECTOR4:
1067           {
1068             ubo.Write(&(*iter).propertyValue->GetVector4(updateBufferIndex),
1069                       sizeof(Vector4),
1070                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
1071             break;
1072           }
1073           case Property::Type::MATRIX:
1074           {
1075             ubo.Write(&(*iter).propertyValue->GetMatrix(updateBufferIndex),
1076                       sizeof(Matrix),
1077                       dst + static_cast<uint32_t>(sizeof(Matrix)) * arrayIndex);
1078             break;
1079           }
1080           case Property::Type::MATRIX3:
1081           {
1082             // todo: handle data padding properly
1083             // Vulkan:
1084             //
1085             //const auto& matrix = &(*iter).propertyValue->GetMatrix3(updateBufferIndex);
1086             //for(int i = 0; i < 3; ++i)
1087             //{
1088               //ubo.Write(&matrix->AsFloat()[i * 3],
1089               //          sizeof(float) * 3,
1090               //          dst + (i * static_cast<uint32_t>(sizeof(Vector4))));
1091             //}
1092             // GL:
1093             ubo.Write(&(*iter).propertyValue->GetMatrix3(updateBufferIndex),
1094                       sizeof(Matrix3),
1095                       dst + static_cast<uint32_t>(sizeof(Matrix3)) * arrayIndex);
1096             break;
1097           }
1098           default:
1099           {
1100           }
1101         }
1102       }
1103     }
1104   }
1105   // write output bindings
1106   outBindings = &mUniformBufferBindings;
1107
1108   // Update offset
1109   offset = dataOffset;
1110 }
1111
1112 void Renderer::SetSortAttributes(BufferIndex                                             bufferIndex,
1113                                  SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
1114 {
1115   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
1116   sortAttributes.geometry = mGeometry;
1117 }
1118
1119 void Renderer::SetShaderChanged(bool value)
1120 {
1121   mShaderChanged = value;
1122 }
1123
1124 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
1125 {
1126   if(mUpdated)
1127   {
1128     mUpdated = false;
1129     return true;
1130   }
1131
1132   if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
1133   {
1134     return true;
1135   }
1136
1137   for(const auto& texture : mRenderDataProvider->GetTextures())
1138   {
1139     if(texture && texture->IsNativeImage())
1140     {
1141       return true;
1142     }
1143   }
1144
1145   uint64_t                               hash           = 0xc70f6907UL;
1146   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
1147   for(const auto& uniformProperty : uniformMapNode)
1148   {
1149     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
1150   }
1151
1152   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
1153   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
1154   for(const auto& uniformProperty : uniformMap)
1155   {
1156     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
1157   }
1158
1159   if(mUniformsHash != hash)
1160   {
1161     mUniformsHash = hash;
1162     return true;
1163   }
1164
1165   return false;
1166 }
1167
1168 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
1169   Program&                                             program,
1170   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
1171   bool                                                 blend,
1172   Graphics::UniquePtr<Graphics::Pipeline>&&            oldPipeline)
1173 {
1174   Graphics::InputAssemblyState inputAssemblyState{};
1175   Graphics::VertexInputState   vertexInputState{};
1176   Graphics::ProgramState       programState{};
1177   uint32_t                     bindingIndex{0u};
1178
1179   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
1180   {
1181     mAttributeLocations.Clear();
1182     mUpdateAttributeLocations = true;
1183   }
1184
1185   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
1186
1187   /**
1188    * Bind Attributes
1189    */
1190   uint32_t base = 0;
1191   for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
1192   {
1193     const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
1194
1195     vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
1196                                                  Graphics::VertexInputRate::PER_VERTEX);
1197
1198     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
1199     for(uint32_t i = 0; i < attributeCount; ++i)
1200     {
1201       if(mUpdateAttributeLocations)
1202       {
1203         auto    attributeName = vertexBuffer->GetAttributeName(i);
1204         int32_t pLocation     = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
1205         if(-1 == pLocation)
1206         {
1207           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
1208         }
1209         mAttributeLocations.PushBack(pLocation);
1210       }
1211
1212       uint32_t location = static_cast<uint32_t>(mAttributeLocations[base + i]);
1213
1214       vertexInputState.attributes.emplace_back(location,
1215                                                bindingIndex,
1216                                                vertexFormat.components[i].offset,
1217                                                GetPropertyVertexFormat(vertexFormat.components[i].type));
1218     }
1219     base += attributeCount;
1220     ++bindingIndex;
1221   }
1222   mUpdateAttributeLocations = false;
1223
1224   // Get the topology
1225   inputAssemblyState.SetTopology(mGeometry->GetTopology());
1226
1227   // Get the program
1228   programState.SetProgram(program.GetGraphicsProgram());
1229
1230   Graphics::RasterizationState rasterizationState{};
1231
1232   //Set cull face  mode
1233   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
1234   if(cam->GetReflectionUsed())
1235   {
1236     auto adjFaceCullingMode = mFaceCullingMode;
1237     switch(mFaceCullingMode)
1238     {
1239       case FaceCullingMode::Type::FRONT:
1240       {
1241         adjFaceCullingMode = FaceCullingMode::Type::BACK;
1242         break;
1243       }
1244       case FaceCullingMode::Type::BACK:
1245       {
1246         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
1247         break;
1248       }
1249       default:
1250       {
1251         // nothing to do, leave culling as it is
1252       }
1253     }
1254     rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
1255   }
1256   else
1257   {
1258     rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
1259   }
1260
1261   rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
1262
1263   /**
1264    * Set Polygon mode
1265    */
1266   switch(mGeometry->GetTopology())
1267   {
1268     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
1269     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
1270     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
1271       rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
1272       break;
1273     case Graphics::PrimitiveTopology::LINE_LIST:
1274     case Graphics::PrimitiveTopology::LINE_LOOP:
1275     case Graphics::PrimitiveTopology::LINE_STRIP:
1276       rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
1277       break;
1278     case Graphics::PrimitiveTopology::POINT_LIST:
1279       rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
1280       break;
1281   }
1282
1283   // @todo How to signal a blend barrier is needed?
1284   //if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1285   //{
1286   //  context.BlendBarrier();
1287   //}
1288
1289   Graphics::ColorBlendState colorBlendState{};
1290   colorBlendState.SetBlendEnable(false);
1291
1292   if(blend)
1293   {
1294     colorBlendState.SetBlendEnable(true);
1295
1296     Graphics::BlendOp rgbOp   = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1297     Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1298     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1299     {
1300       if(rgbOp != alphaOp)
1301       {
1302         DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1303         alphaOp = rgbOp;
1304       }
1305     }
1306
1307     colorBlendState
1308       .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1309       .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1310       .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1311       .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1312       .SetColorBlendOp(rgbOp)
1313       .SetAlphaBlendOp(alphaOp);
1314
1315     // Blend color is optional and rarely used
1316     Vector4* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1317     if(blendColor)
1318     {
1319       colorBlendState.SetBlendConstants(blendColor->AsFloat());
1320     }
1321   }
1322
1323   // Take the program into use so we can send uniforms to it
1324   // @todo Remove this call entirely!
1325   program.Use();
1326
1327   mUpdated = true;
1328
1329   // Create a new pipeline
1330   return mGraphicsController->CreatePipeline(
1331     Graphics::PipelineCreateInfo()
1332       .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
1333       .SetVertexInputState(&vertexInputState)
1334       .SetRasterizationState(&rasterizationState)
1335       .SetColorBlendState(&colorBlendState)
1336       .SetProgramState(&programState)
1337       .SetNextExtension(&mLegacyProgram),
1338     std::move(oldPipeline));
1339 }
1340
1341 } // namespace Render
1342
1343 } // namespace Internal
1344
1345 } // namespace Dali