UBO support on the Core side using CPU-based Buffer memory
[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       std::vector<Graphics::UniformBufferBinding>* bindings{nullptr};
893       FillUniformBuffers(*program, instruction, *ubo, bindings, uboOffset, bufferIndex);
894
895       Vector4        finalColor;
896       const Vector4& color = node.GetRenderColor(bufferIndex);
897       if(mPremultipledAlphaEnabled)
898       {
899         float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
900         finalColor  = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
901       }
902       else
903       {
904         finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
905       }
906
907       // We know bindings for this renderer, so we can use 'offset' and write additional uniforms
908       Matrix modelViewProjectionMatrix(false);
909       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
910
911       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *ubo, *bindings, modelMatrix);
912       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *ubo, *bindings, viewMatrix);
913       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *ubo, *bindings, projectionMatrix);
914       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX), *ubo, *bindings, modelViewProjectionMatrix);
915       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *ubo, *bindings, modelViewMatrix);
916       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *ubo, *bindings, size);
917       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *ubo, *bindings, finalColor);
918
919       // Update normal matrix only when used in the shader
920       Matrix3 normalMatrix(modelViewMatrix);
921       normalMatrix.Invert();
922       normalMatrix.Transpose();
923       WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX), *ubo, *bindings, normalMatrix);
924
925       commandBuffer->BindUniformBuffers(*bindings);
926     }
927
928     bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
929                         // @todo We should detect this case much earlier to prevent unnecessary work
930
931     //@todo manage mDrawCommands in the same way as above command buffer?!
932     if(mDrawCommands.empty())
933     {
934       drawn = mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), mIndexedDrawFirstElement, mIndexedDrawElementsCount);
935     }
936     else
937     {
938       for(auto& cmd : commands)
939       {
940         // @todo This should generate a command buffer per cmd
941         // Tests WILL fail. (Temporarily commented out)
942         mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), cmd->firstIndex, cmd->elementCount);
943       }
944     }
945
946     // Command buffer contains Texture bindings, vertex bindings, index buffer binding, pipeline(vertex format)
947     // @todo We should return the command buffer(s) and let the calling method submit
948     // If not drawn, then don't add command buffer to submit info, and if empty, don't
949     // submit.
950     if(drawn)
951     {
952       Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
953       submitInfo.cmdBuffer.push_back(commandBuffer.get());
954       mGraphicsController->SubmitCommandBuffers(submitInfo);
955     }
956
957     mUpdated = false;
958   }
959 }
960
961 template<class T>
962 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const T& data)
963 {
964   if(uniformInfo && !uniformInfo->name.empty())
965   {
966     WriteUniform(ubo, bindings, *uniformInfo, data);
967     return true;
968   }
969   return false;
970 }
971
972 template<class T>
973 void Renderer::WriteUniform(Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const T& data)
974 {
975   WriteUniform(ubo, bindings, uniformInfo, &data, sizeof(T));
976 }
977
978 void Renderer::WriteUniform(Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
979 {
980   ubo.Write(data, size, bindings[uniformInfo.bufferIndex].offset + uniformInfo.offset);
981 }
982
983 void Renderer::FillUniformBuffers(Program&                                      program,
984                                   const SceneGraph::RenderInstruction&          instruction,
985                                   Render::UniformBuffer&                        ubo,
986                                   std::vector<Graphics::UniformBufferBinding>*& outBindings,
987                                   uint32_t&                                     offset,
988                                   BufferIndex                                   updateBufferIndex)
989 {
990   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
991   auto  uboCount   = reflection.GetUniformBlockCount();
992
993   mUniformBufferBindings.resize(uboCount);
994
995   // Setup bindings
996   uint32_t dataOffset = offset;
997   for(auto i = 0u; i < uboCount; ++i)
998   {
999     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
1000     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
1001     mUniformBufferBindings[i].offset   = dataOffset;
1002
1003     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
1004     mUniformBufferBindings[i].buffer = ubo.GetBuffer();
1005
1006     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
1007                                        end  = mUniformIndexMap.End();
1008         iter != end;
1009         ++iter)
1010     {
1011       // @todo This means parsing the uniform string every frame. Instead, store the array index if present.
1012       int arrayIndex = (*iter).arrayIndex;
1013
1014       auto uniformInfo  = Graphics::UniformInfo{};
1015       auto uniformFound = program.GetUniform((*iter).uniformName.GetCString(),
1016                                              (*iter).uniformNameHashNoArray ? (*iter).uniformNameHashNoArray : (*iter).uniformNameHash,
1017                                              uniformInfo);
1018
1019       if(uniformFound)
1020       {
1021         auto dst = mUniformBufferBindings[uniformInfo.bufferIndex].offset + uniformInfo.offset;
1022
1023         switch((*iter).propertyValue->GetType())
1024         {
1025           case Property::Type::BOOLEAN:
1026           {
1027             ubo.Write(&(*iter).propertyValue->GetBoolean(updateBufferIndex),
1028                       sizeof(bool),
1029                       dst + static_cast<uint32_t>(sizeof(bool)) * arrayIndex);
1030             break;
1031           }
1032           case Property::Type::INTEGER:
1033           {
1034             ubo.Write(&(*iter).propertyValue->GetInteger(updateBufferIndex),
1035                       sizeof(int32_t),
1036                       dst + static_cast<int32_t>(sizeof(int32_t)) * arrayIndex);
1037             break;
1038           }
1039           case Property::Type::FLOAT:
1040           {
1041             ubo.Write(&(*iter).propertyValue->GetFloat(updateBufferIndex),
1042                       sizeof(float),
1043                       dst + static_cast<uint32_t>(sizeof(float)) * arrayIndex);
1044             break;
1045           }
1046           case Property::Type::VECTOR2:
1047           {
1048             ubo.Write(&(*iter).propertyValue->GetVector2(updateBufferIndex),
1049                       sizeof(Vector2),
1050                       dst + static_cast<uint32_t>(sizeof(Vector2)) * arrayIndex);
1051             break;
1052           }
1053           case Property::Type::VECTOR3:
1054           {
1055             ubo.Write(&(*iter).propertyValue->GetVector3(updateBufferIndex),
1056                       sizeof(Vector3),
1057                       dst + static_cast<uint32_t>(sizeof(Vector3)) * arrayIndex);
1058             break;
1059           }
1060           case Property::Type::VECTOR4:
1061           {
1062             ubo.Write(&(*iter).propertyValue->GetVector4(updateBufferIndex),
1063                       sizeof(Vector4),
1064                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
1065             break;
1066           }
1067           case Property::Type::MATRIX:
1068           {
1069             ubo.Write(&(*iter).propertyValue->GetMatrix(updateBufferIndex),
1070                       sizeof(Matrix),
1071                       dst + static_cast<uint32_t>(sizeof(Matrix)) * arrayIndex);
1072             break;
1073           }
1074           case Property::Type::MATRIX3:
1075           {
1076             // todo: handle data padding properly
1077             // Vulkan:
1078             //
1079             //const auto& matrix = &(*iter).propertyValue->GetMatrix3(updateBufferIndex);
1080             //for(int i = 0; i < 3; ++i)
1081             //{
1082               //ubo.Write(&matrix->AsFloat()[i * 3],
1083               //          sizeof(float) * 3,
1084               //          dst + (i * static_cast<uint32_t>(sizeof(Vector4))));
1085             //}
1086             // GL:
1087             ubo.Write(&(*iter).propertyValue->GetMatrix3(updateBufferIndex),
1088                       sizeof(Matrix3),
1089                       dst + static_cast<uint32_t>(sizeof(Matrix3)) * arrayIndex);
1090             break;
1091           }
1092           default:
1093           {
1094           }
1095         }
1096       }
1097     }
1098   }
1099   // write output bindings
1100   outBindings = &mUniformBufferBindings;
1101
1102   // Update offset
1103   offset = dataOffset;
1104 }
1105
1106 void Renderer::SetSortAttributes(BufferIndex                                             bufferIndex,
1107                                  SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
1108 {
1109   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
1110   sortAttributes.geometry = mGeometry;
1111 }
1112
1113 void Renderer::SetShaderChanged(bool value)
1114 {
1115   mShaderChanged = value;
1116 }
1117
1118 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
1119 {
1120   if(mUpdated)
1121   {
1122     mUpdated = false;
1123     return true;
1124   }
1125
1126   if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
1127   {
1128     return true;
1129   }
1130
1131   for(const auto& texture : mRenderDataProvider->GetTextures())
1132   {
1133     if(texture && texture->IsNativeImage())
1134     {
1135       return true;
1136     }
1137   }
1138
1139   uint64_t                               hash           = 0xc70f6907UL;
1140   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
1141   for(const auto& uniformProperty : uniformMapNode)
1142   {
1143     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
1144   }
1145
1146   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
1147   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
1148   for(const auto& uniformProperty : uniformMap)
1149   {
1150     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
1151   }
1152
1153   if(mUniformsHash != hash)
1154   {
1155     mUniformsHash = hash;
1156     return true;
1157   }
1158
1159   return false;
1160 }
1161
1162 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
1163   Program&                                             program,
1164   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
1165   bool                                                 blend,
1166   Graphics::UniquePtr<Graphics::Pipeline>&&            oldPipeline)
1167 {
1168   Graphics::InputAssemblyState inputAssemblyState{};
1169   Graphics::VertexInputState   vertexInputState{};
1170   Graphics::ProgramState       programState{};
1171   uint32_t                     bindingIndex{0u};
1172
1173   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
1174   {
1175     mAttributeLocations.Clear();
1176     mUpdateAttributeLocations = true;
1177   }
1178
1179   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
1180
1181   /**
1182    * Bind Attributes
1183    */
1184   uint32_t base = 0;
1185   for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
1186   {
1187     const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
1188
1189     vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
1190                                                  Graphics::VertexInputRate::PER_VERTEX);
1191
1192     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
1193     for(uint32_t i = 0; i < attributeCount; ++i)
1194     {
1195       if(mUpdateAttributeLocations)
1196       {
1197         auto    attributeName = vertexBuffer->GetAttributeName(i);
1198         int32_t pLocation     = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
1199         if(-1 == pLocation)
1200         {
1201           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
1202         }
1203         mAttributeLocations.PushBack(pLocation);
1204       }
1205
1206       uint32_t location = static_cast<uint32_t>(mAttributeLocations[base + i]);
1207
1208       vertexInputState.attributes.emplace_back(location,
1209                                                bindingIndex,
1210                                                vertexFormat.components[i].offset,
1211                                                GetPropertyVertexFormat(vertexFormat.components[i].type));
1212     }
1213     base += attributeCount;
1214     ++bindingIndex;
1215   }
1216   mUpdateAttributeLocations = false;
1217
1218   // Get the topology
1219   inputAssemblyState.SetTopology(mGeometry->GetTopology());
1220
1221   // Get the program
1222   programState.SetProgram(program.GetGraphicsProgram());
1223
1224   Graphics::RasterizationState rasterizationState{};
1225
1226   //Set cull face  mode
1227   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
1228   if(cam->GetReflectionUsed())
1229   {
1230     auto adjFaceCullingMode = mFaceCullingMode;
1231     switch(mFaceCullingMode)
1232     {
1233       case FaceCullingMode::Type::FRONT:
1234       {
1235         adjFaceCullingMode = FaceCullingMode::Type::BACK;
1236         break;
1237       }
1238       case FaceCullingMode::Type::BACK:
1239       {
1240         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
1241         break;
1242       }
1243       default:
1244       {
1245         // nothing to do, leave culling as it is
1246       }
1247     }
1248     rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
1249   }
1250   else
1251   {
1252     rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
1253   }
1254
1255   rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
1256
1257   /**
1258    * Set Polygon mode
1259    */
1260   switch(mGeometry->GetTopology())
1261   {
1262     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
1263     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
1264     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
1265       rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
1266       break;
1267     case Graphics::PrimitiveTopology::LINE_LIST:
1268     case Graphics::PrimitiveTopology::LINE_LOOP:
1269     case Graphics::PrimitiveTopology::LINE_STRIP:
1270       rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
1271       break;
1272     case Graphics::PrimitiveTopology::POINT_LIST:
1273       rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
1274       break;
1275   }
1276
1277   // @todo How to signal a blend barrier is needed?
1278   //if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1279   //{
1280   //  context.BlendBarrier();
1281   //}
1282
1283   Graphics::ColorBlendState colorBlendState{};
1284   colorBlendState.SetBlendEnable(false);
1285
1286   if(blend)
1287   {
1288     colorBlendState.SetBlendEnable(true);
1289
1290     Graphics::BlendOp rgbOp   = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1291     Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1292     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1293     {
1294       if(rgbOp != alphaOp)
1295       {
1296         DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1297         alphaOp = rgbOp;
1298       }
1299     }
1300
1301     colorBlendState
1302       .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1303       .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1304       .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1305       .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1306       .SetColorBlendOp(rgbOp)
1307       .SetAlphaBlendOp(alphaOp);
1308
1309     // Blend color is optional and rarely used
1310     Vector4* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1311     if(blendColor)
1312     {
1313       colorBlendState.SetBlendConstants(blendColor->AsFloat());
1314     }
1315   }
1316
1317   // Take the program into use so we can send uniforms to it
1318   // @todo Remove this call entirely!
1319   program.Use();
1320
1321   mUpdated = true;
1322
1323   // Create a new pipeline
1324   return mGraphicsController->CreatePipeline(
1325     Graphics::PipelineCreateInfo()
1326       .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
1327       .SetVertexInputState(&vertexInputState)
1328       .SetRasterizationState(&rasterizationState)
1329       .SetColorBlendState(&colorBlendState)
1330       .SetProgramState(&programState)
1331       .SetNextExtension(&mLegacyProgram),
1332     std::move(oldPipeline));
1333 }
1334
1335 } // namespace Render
1336
1337 } // namespace Internal
1338
1339 } // namespace Dali