Removing GL usage from dali core
[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-types.h>
23 #include <dali/integration-api/debug.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/renderers/render-sampler.h>
29 #include <dali/internal/render/renderers/render-texture.h>
30 #include <dali/internal/render/renderers/render-vertex-buffer.h>
31 #include <dali/internal/render/renderers/shader-cache.h>
32 #include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
33 #include <dali/internal/render/renderers/uniform-buffer-view.h>
34 #include <dali/internal/render/shaders/program.h>
35 #include <dali/internal/render/shaders/render-shader.h>
36 #include <dali/internal/update/common/uniform-map.h>
37
38 namespace Dali::Internal
39 {
40 namespace
41 {
42 // Helper to get the vertex input format
43 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
44 {
45   Dali::Graphics::VertexInputFormat type{};
46
47   switch(propertyType)
48   {
49     case Property::NONE:
50     case Property::STRING:
51     case Property::ARRAY:
52     case Property::MAP:
53     case Property::EXTENTS:   // i4?
54     case Property::RECTANGLE: // i4/f4?
55     case Property::ROTATION:
56     {
57       type = Dali::Graphics::VertexInputFormat::UNDEFINED;
58       break;
59     }
60     case Property::BOOLEAN:
61     {
62       type = Dali::Graphics::VertexInputFormat::UNDEFINED; // type = GL_BYTE; @todo new type for this?
63       break;
64     }
65     case Property::INTEGER:
66     {
67       type = Dali::Graphics::VertexInputFormat::INTEGER; // (short)
68       break;
69     }
70     case Property::FLOAT:
71     {
72       type = Dali::Graphics::VertexInputFormat::FLOAT;
73       break;
74     }
75     case Property::VECTOR2:
76     {
77       type = Dali::Graphics::VertexInputFormat::FVECTOR2;
78       break;
79     }
80     case Property::VECTOR3:
81     {
82       type = Dali::Graphics::VertexInputFormat::FVECTOR3;
83       break;
84     }
85     case Property::VECTOR4:
86     {
87       type = Dali::Graphics::VertexInputFormat::FVECTOR4;
88       break;
89     }
90     case Property::MATRIX3:
91     case Property::MATRIX:
92     {
93       type = Dali::Graphics::VertexInputFormat::FLOAT;
94       break;
95     }
96   }
97
98   return type;
99 }
100
101 constexpr Graphics::CullMode ConvertCullFace(Dali::FaceCullingMode::Type mode)
102 {
103   switch(mode)
104   {
105     case Dali::FaceCullingMode::NONE:
106     {
107       return Graphics::CullMode::NONE;
108     }
109     case Dali::FaceCullingMode::FRONT:
110     {
111       return Graphics::CullMode::FRONT;
112     }
113     case Dali::FaceCullingMode::BACK:
114     {
115       return Graphics::CullMode::BACK;
116     }
117     case Dali::FaceCullingMode::FRONT_AND_BACK:
118     {
119       return Graphics::CullMode::FRONT_AND_BACK;
120     }
121   }
122   return Graphics::CullMode::NONE;
123 }
124
125 constexpr Graphics::BlendFactor ConvertBlendFactor(BlendFactor::Type blendFactor)
126 {
127   switch(blendFactor)
128   {
129     case BlendFactor::ZERO:
130       return Graphics::BlendFactor::ZERO;
131     case BlendFactor::ONE:
132       return Graphics::BlendFactor::ONE;
133     case BlendFactor::SRC_COLOR:
134       return Graphics::BlendFactor::SRC_COLOR;
135     case BlendFactor::ONE_MINUS_SRC_COLOR:
136       return Graphics::BlendFactor::ONE_MINUS_SRC_COLOR;
137     case BlendFactor::SRC_ALPHA:
138       return Graphics::BlendFactor::SRC_ALPHA;
139     case BlendFactor::ONE_MINUS_SRC_ALPHA:
140       return Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA;
141     case BlendFactor::DST_ALPHA:
142       return Graphics::BlendFactor::DST_ALPHA;
143     case BlendFactor::ONE_MINUS_DST_ALPHA:
144       return Graphics::BlendFactor::ONE_MINUS_DST_ALPHA;
145     case BlendFactor::DST_COLOR:
146       return Graphics::BlendFactor::DST_COLOR;
147     case BlendFactor::ONE_MINUS_DST_COLOR:
148       return Graphics::BlendFactor::ONE_MINUS_DST_COLOR;
149     case BlendFactor::SRC_ALPHA_SATURATE:
150       return Graphics::BlendFactor::SRC_ALPHA_SATURATE;
151     case BlendFactor::CONSTANT_COLOR:
152       return Graphics::BlendFactor::CONSTANT_COLOR;
153     case BlendFactor::ONE_MINUS_CONSTANT_COLOR:
154       return Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR;
155     case BlendFactor::CONSTANT_ALPHA:
156       return Graphics::BlendFactor::CONSTANT_ALPHA;
157     case BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
158       return Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA;
159   }
160   return Graphics::BlendFactor{};
161 }
162
163 constexpr Graphics::BlendOp ConvertBlendEquation(DevelBlendEquation::Type blendEquation)
164 {
165   switch(blendEquation)
166   {
167     case DevelBlendEquation::ADD:
168       return Graphics::BlendOp::ADD;
169     case DevelBlendEquation::SUBTRACT:
170       return Graphics::BlendOp::SUBTRACT;
171     case DevelBlendEquation::REVERSE_SUBTRACT:
172       return Graphics::BlendOp::REVERSE_SUBTRACT;
173     case DevelBlendEquation::COLOR:
174     case DevelBlendEquation::COLOR_BURN:
175     case DevelBlendEquation::COLOR_DODGE:
176     case DevelBlendEquation::DARKEN:
177     case DevelBlendEquation::DIFFERENCE:
178     case DevelBlendEquation::EXCLUSION:
179     case DevelBlendEquation::HARD_LIGHT:
180     case DevelBlendEquation::HUE:
181     case DevelBlendEquation::LIGHTEN:
182     case DevelBlendEquation::LUMINOSITY:
183     case DevelBlendEquation::MAX:
184     case DevelBlendEquation::MIN:
185     case DevelBlendEquation::MULTIPLY:
186     case DevelBlendEquation::OVERLAY:
187     case DevelBlendEquation::SATURATION:
188     case DevelBlendEquation::SCREEN:
189     case DevelBlendEquation::SOFT_LIGHT:
190       return Graphics::BlendOp{};
191   }
192   return Graphics::BlendOp{};
193 }
194
195 /**
196  * Helper function to calculate the correct alignment of data for uniform buffers
197  * @param dataSize size of uniform buffer
198  * @return aligned offset of data
199  */
200 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
201 {
202   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
203 }
204
205 } // namespace
206
207 namespace Render
208 {
209 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
210                         Render::Geometry*               geometry,
211                         uint32_t                        blendingBitmask,
212                         const Vector4&                  blendColor,
213                         FaceCullingMode::Type           faceCullingMode,
214                         bool                            preMultipliedAlphaEnabled,
215                         DepthWriteMode::Type            depthWriteMode,
216                         DepthTestMode::Type             depthTestMode,
217                         DepthFunction::Type             depthFunction,
218                         StencilParameters&              stencilParameters)
219 {
220   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
221 }
222
223 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
224                    Render::Geometry*               geometry,
225                    uint32_t                        blendingBitmask,
226                    const Vector4&                  blendColor,
227                    FaceCullingMode::Type           faceCullingMode,
228                    bool                            preMultipliedAlphaEnabled,
229                    DepthWriteMode::Type            depthWriteMode,
230                    DepthTestMode::Type             depthTestMode,
231                    DepthFunction::Type             depthFunction,
232                    StencilParameters&              stencilParameters)
233 : mGraphicsController(nullptr),
234   mRenderDataProvider(dataProvider),
235   mGeometry(geometry),
236   mProgramCache(nullptr),
237   mUniformIndexMap(),
238   mAttributeLocations(),
239   mUniformsHash(),
240   mStencilParameters(stencilParameters),
241   mBlendingOptions(),
242   mIndexedDrawFirstElement(0),
243   mIndexedDrawElementsCount(0),
244   mDepthFunction(depthFunction),
245   mFaceCullingMode(faceCullingMode),
246   mDepthWriteMode(depthWriteMode),
247   mDepthTestMode(depthTestMode),
248   mUpdateAttributeLocations(true),
249   mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled),
250   mShaderChanged(false),
251   mUpdated(true)
252 {
253   if(blendingBitmask != 0u)
254   {
255     mBlendingOptions.SetBitmask(blendingBitmask);
256   }
257
258   mBlendingOptions.SetBlendColor(blendColor);
259 }
260
261 void Renderer::Initialize(Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache, Render::UniformBufferManager& uniformBufferManager)
262 {
263   mGraphicsController   = &graphicsController;
264   mProgramCache         = &programCache;
265   mShaderCache          = &shaderCache;
266   mUniformBufferManager = &uniformBufferManager;
267 }
268
269 Renderer::~Renderer() = default;
270
271 void Renderer::SetGeometry(Render::Geometry* geometry)
272 {
273   mGeometry                 = geometry;
274   mUpdateAttributeLocations = true;
275 }
276 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
277 {
278   mDrawCommands.clear();
279   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
280 }
281
282 void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
283 {
284   uint32_t textureUnit = 0;
285
286   std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
287   std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
288
289   std::vector<Graphics::TextureBinding> textureBindings;
290   for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()); ++i) // not expecting more than uint32_t of textures
291   {
292     if(textures[i] && textures[i]->GetGraphicsObject())
293     {
294       // if the sampler exists,
295       //   if it's default, delete the graphics object
296       //   otherwise re-initialize it if dirty
297
298       const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
299                                                               : nullptr);
300
301       boundTextures.PushBack(textures[i]->GetGraphicsObject());
302       const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
303       textureBindings.push_back(textureBinding);
304
305       ++textureUnit;
306     }
307   }
308
309   if(!textureBindings.empty())
310   {
311     commandBuffer.BindTextures(textureBindings);
312   }
313 }
314
315 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
316 {
317   mFaceCullingMode = mode;
318   mUpdated         = true;
319 }
320
321 void Renderer::SetBlendingBitMask(uint32_t bitmask)
322 {
323   mBlendingOptions.SetBitmask(bitmask);
324   mUpdated = true;
325 }
326
327 void Renderer::SetBlendColor(const Vector4& color)
328 {
329   mBlendingOptions.SetBlendColor(color);
330   mUpdated = true;
331 }
332
333 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
334 {
335   mIndexedDrawFirstElement = firstElement;
336   mUpdated                 = true;
337 }
338
339 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
340 {
341   mIndexedDrawElementsCount = elementsCount;
342   mUpdated                  = true;
343 }
344
345 void Renderer::EnablePreMultipliedAlpha(bool enable)
346 {
347   mPremultipliedAlphaEnabled = enable;
348   mUpdated                   = true;
349 }
350
351 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
352 {
353   mDepthWriteMode = depthWriteMode;
354   mUpdated        = true;
355 }
356
357 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
358 {
359   mDepthTestMode = depthTestMode;
360   mUpdated       = true;
361 }
362
363 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
364 {
365   return mDepthWriteMode;
366 }
367
368 DepthTestMode::Type Renderer::GetDepthTestMode() const
369 {
370   return mDepthTestMode;
371 }
372
373 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
374 {
375   mDepthFunction = depthFunction;
376   mUpdated       = true;
377 }
378
379 DepthFunction::Type Renderer::GetDepthFunction() const
380 {
381   return mDepthFunction;
382 }
383
384 void Renderer::SetRenderMode(RenderMode::Type renderMode)
385 {
386   mStencilParameters.renderMode = renderMode;
387   mUpdated                      = true;
388 }
389
390 RenderMode::Type Renderer::GetRenderMode() const
391 {
392   return mStencilParameters.renderMode;
393 }
394
395 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
396 {
397   mStencilParameters.stencilFunction = stencilFunction;
398   mUpdated                           = true;
399 }
400
401 StencilFunction::Type Renderer::GetStencilFunction() const
402 {
403   return mStencilParameters.stencilFunction;
404 }
405
406 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
407 {
408   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
409   mUpdated                               = true;
410 }
411
412 int Renderer::GetStencilFunctionMask() const
413 {
414   return mStencilParameters.stencilFunctionMask;
415 }
416
417 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
418 {
419   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
420   mUpdated                                    = true;
421 }
422
423 int Renderer::GetStencilFunctionReference() const
424 {
425   return mStencilParameters.stencilFunctionReference;
426 }
427
428 void Renderer::SetStencilMask(int stencilMask)
429 {
430   mStencilParameters.stencilMask = stencilMask;
431   mUpdated                       = true;
432 }
433
434 int Renderer::GetStencilMask() const
435 {
436   return mStencilParameters.stencilMask;
437 }
438
439 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
440 {
441   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
442   mUpdated                                  = true;
443 }
444
445 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
446 {
447   return mStencilParameters.stencilOperationOnFail;
448 }
449
450 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
451 {
452   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
453   mUpdated                                   = true;
454 }
455
456 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
457 {
458   return mStencilParameters.stencilOperationOnZFail;
459 }
460
461 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
462 {
463   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
464   mUpdated                                   = true;
465 }
466
467 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
468 {
469   return mStencilParameters.stencilOperationOnZPass;
470 }
471
472 void Renderer::Upload()
473 {
474   mGeometry->Upload(*mGraphicsController);
475 }
476
477 bool Renderer::Render(Graphics::CommandBuffer&                             commandBuffer,
478                       BufferIndex                                          bufferIndex,
479                       const SceneGraph::NodeDataProvider&                  node,
480                       const Matrix&                                        modelMatrix,
481                       const Matrix&                                        modelViewMatrix,
482                       const Matrix&                                        viewMatrix,
483                       const Matrix&                                        projectionMatrix,
484                       const Vector3&                                       size,
485                       bool                                                 blend,
486                       Vector<Graphics::Texture*>&                          boundTextures,
487                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
488                       uint32_t                                             queueIndex)
489 {
490   // Before doing anything test if the call happens in the right queue
491   if(mDrawCommands.empty() && queueIndex > 0)
492   {
493     return false;
494   }
495
496   // Prepare commands
497   std::vector<DevelRenderer::DrawCommand*> commands;
498   for(auto& cmd : mDrawCommands)
499   {
500     if(cmd.queue == queueIndex)
501     {
502       commands.emplace_back(&cmd);
503     }
504   }
505
506   // Have commands but nothing to be drawn - abort
507   if(!mDrawCommands.empty() && commands.empty())
508   {
509     return false;
510   }
511
512   // Set blending mode
513   if(!mDrawCommands.empty())
514   {
515     blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend;
516   }
517
518   // Create Program
519   ShaderDataPtr            shaderData   = mRenderDataProvider->GetShader().GetShaderData();
520   const std::vector<char>& vertShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
521   const std::vector<char>& fragShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
522   Dali::Graphics::Shader&  vertexShader = mShaderCache->GetShader(
523     vertShader,
524     Graphics::PipelineStage::VERTEX_SHADER,
525     shaderData->GetSourceMode());
526
527   Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
528     fragShader,
529     Graphics::PipelineStage::FRAGMENT_SHADER,
530     shaderData->GetSourceMode());
531
532   std::vector<Graphics::ShaderState> shaderStates{
533     Graphics::ShaderState()
534       .SetShader(vertexShader)
535       .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
536     Graphics::ShaderState()
537       .SetShader(fragmentShader)
538       .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
539
540   auto createInfo = Graphics::ProgramCreateInfo();
541   createInfo.SetShaderState(shaderStates);
542
543   auto     graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
544   Program* program         = Program::New(*mProgramCache,
545                                   shaderData,
546                                   *mGraphicsController,
547                                   std::move(graphicsProgram));
548
549   if(!program)
550   {
551     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
552     return false;
553   }
554
555   // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
556   auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
557
558   commandBuffer.BindPipeline(pipeline);
559
560   BindTextures(commandBuffer, boundTextures);
561
562   BuildUniformIndexMap(bufferIndex, node, size, *program);
563
564   WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size);
565
566   bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
567                       // @todo We should detect this case much earlier to prevent unnecessary work
568
569   if(mDrawCommands.empty())
570   {
571     drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
572   }
573   else
574   {
575     for(auto& cmd : commands)
576     {
577       mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
578     }
579   }
580
581   mUpdated = false;
582   return drawn;
583 }
584
585 void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
586 {
587   // Check if the map has changed
588   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
589
590   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
591
592   if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
593      node.GetUniformMapChanged(bufferIndex) ||
594      mUniformIndexMap.Count() == 0 ||
595      mShaderChanged)
596   {
597     // Reset shader pointer
598     mShaderChanged = false;
599
600     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
601     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
602
603     auto maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
604     mUniformIndexMap.Clear();                                                          // Clear contents, but keep memory if we don't change size
605     mUniformIndexMap.Resize(maxMaps);
606
607     // Copy uniform map into mUniformIndexMap
608     uint32_t mapIndex = 0;
609     for(; mapIndex < uniformMap.Count(); ++mapIndex)
610     {
611       mUniformIndexMap[mapIndex].propertyValue          = uniformMap[mapIndex].propertyPtr;
612       mUniformIndexMap[mapIndex].uniformName            = uniformMap[mapIndex].uniformName;
613       mUniformIndexMap[mapIndex].uniformNameHash        = uniformMap[mapIndex].uniformNameHash;
614       mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMap[mapIndex].uniformNameHashNoArray;
615       mUniformIndexMap[mapIndex].arrayIndex             = uniformMap[mapIndex].arrayIndex;
616     }
617
618     for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
619     {
620       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
621       auto& name = uniformMapNode[nodeMapIndex].uniformName;
622       bool  found(false);
623       for(uint32_t i = 0; i < uniformMap.Count(); ++i)
624       {
625         if(mUniformIndexMap[i].uniformNameHash == hash &&
626            mUniformIndexMap[i].uniformName == name)
627         {
628           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
629           found                             = true;
630           break;
631         }
632       }
633
634       if(!found)
635       {
636         mUniformIndexMap[mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
637         mUniformIndexMap[mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
638         mUniformIndexMap[mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
639         mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
640         mUniformIndexMap[mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
641         ++mapIndex;
642       }
643     }
644
645     mUniformIndexMap.Resize(mapIndex);
646   }
647 }
648
649 void Renderer::WriteUniformBuffer(
650   BufferIndex                          bufferIndex,
651   Graphics::CommandBuffer&             commandBuffer,
652   Program*                             program,
653   const SceneGraph::RenderInstruction& instruction,
654   const SceneGraph::NodeDataProvider&  node,
655   const Matrix&                        modelMatrix,
656   const Matrix&                        modelViewMatrix,
657   const Matrix&                        viewMatrix,
658   const Matrix&                        projectionMatrix,
659   const Vector3&                       size)
660 {
661   // Create the UBO
662   uint32_t uniformBlockAllocationBytes{0u};
663   uint32_t uniformBlockMaxSize{0u};
664   uint32_t uboOffset{0u};
665
666   auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
667   for(auto i = 0u; i < reflection.GetUniformBlockCount(); ++i)
668   {
669     auto blockSize = GetUniformBufferDataAlignment(reflection.GetUniformBlockSize(i));
670     if(uniformBlockMaxSize < blockSize)
671     {
672       uniformBlockMaxSize = blockSize;
673     }
674     uniformBlockAllocationBytes += blockSize;
675   }
676
677   // Create uniform buffer view from uniform buffer
678   Graphics::UniquePtr<Render::UniformBufferView> uboView{nullptr};
679   if(uniformBlockAllocationBytes)
680   {
681     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex);
682
683     uboView = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
684   }
685
686   // update the uniform buffer
687   // pass shared UBO and offset, return new offset for next item to be used
688   // don't process bindings if there are no uniform buffers allocated
689   if(uboView)
690   {
691     auto uboCount = reflection.GetUniformBlockCount();
692     mUniformBufferBindings.resize(uboCount);
693
694     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
695
696     mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset);
697
698     // Write default uniforms
699     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, *bindings, modelMatrix);
700     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, *bindings, viewMatrix);
701     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, *bindings, projectionMatrix);
702     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, *bindings, modelViewMatrix);
703
704     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
705     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
706     {
707       Matrix modelViewProjectionMatrix(false);
708       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
709       WriteDefaultUniform(mvpUniformInfo, *uboView, *bindings, modelViewProjectionMatrix);
710     }
711
712     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
713     if(normalUniformInfo && !normalUniformInfo->name.empty())
714     {
715       Matrix3 normalMatrix(modelViewMatrix);
716       normalMatrix.Invert();
717       normalMatrix.Transpose();
718       WriteDefaultUniform(normalUniformInfo, *uboView, *bindings, normalMatrix);
719     }
720
721     Vector4        finalColor;
722     const Vector4& color = node.GetRenderColor(bufferIndex);
723     if(mPremultipliedAlphaEnabled)
724     {
725       float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
726       finalColor  = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
727     }
728     else
729     {
730       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
731     }
732     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, *bindings, finalColor);
733
734     // Write uniforms from the uniform map
735     FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex);
736
737     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
738     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, *bindings, size);
739
740     commandBuffer.BindUniformBuffers(*bindings);
741   }
742 }
743
744 template<class T>
745 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const T& data)
746 {
747   if(uniformInfo && !uniformInfo->name.empty())
748   {
749     WriteUniform(ubo, bindings, *uniformInfo, data);
750     return true;
751   }
752   return false;
753 }
754
755 template<class T>
756 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const T& data)
757 {
758   WriteUniform(ubo, bindings, uniformInfo, &data, sizeof(T));
759 }
760
761 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
762 {
763   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
764 }
765
766 void Renderer::FillUniformBuffer(Program&                                      program,
767                                  const SceneGraph::RenderInstruction&          instruction,
768                                  Render::UniformBufferView&                    ubo,
769                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
770                                  uint32_t&                                     offset,
771                                  BufferIndex                                   updateBufferIndex)
772 {
773   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
774   auto  uboCount   = reflection.GetUniformBlockCount();
775
776   // Setup bindings
777   uint32_t dataOffset = offset;
778   for(auto i = 0u; i < uboCount; ++i)
779   {
780     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
781     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
782
783     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
784     mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset);
785
786     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
787                                        end  = mUniformIndexMap.End();
788         iter != end;
789         ++iter)
790     {
791       // @todo This means parsing the uniform string every frame. Instead, store the array index if present.
792       int arrayIndex = (*iter).arrayIndex;
793
794       auto uniformInfo  = Graphics::UniformInfo{};
795       auto uniformFound = program.GetUniform((*iter).uniformName.GetCString(),
796                                              (*iter).uniformNameHashNoArray ? (*iter).uniformNameHashNoArray
797                                                                             : (*iter).uniformNameHash,
798                                              uniformInfo);
799
800       if(uniformFound)
801       {
802         auto dst = ubo.GetOffset() + uniformInfo.offset;
803         switch((*iter).propertyValue->GetType())
804         {
805           case Property::Type::BOOLEAN:
806           {
807             ubo.Write(&(*iter).propertyValue->GetBoolean(updateBufferIndex),
808                       sizeof(bool),
809                       dst + static_cast<uint32_t>(sizeof(bool)) * arrayIndex);
810             break;
811           }
812           case Property::Type::INTEGER:
813           {
814             ubo.Write(&(*iter).propertyValue->GetInteger(updateBufferIndex),
815                       sizeof(int32_t),
816                       dst + static_cast<int32_t>(sizeof(int32_t)) * arrayIndex);
817             break;
818           }
819           case Property::Type::FLOAT:
820           {
821             ubo.Write(&(*iter).propertyValue->GetFloat(updateBufferIndex),
822                       sizeof(float),
823                       dst + static_cast<uint32_t>(sizeof(float)) * arrayIndex);
824             break;
825           }
826           case Property::Type::VECTOR2:
827           {
828             ubo.Write(&(*iter).propertyValue->GetVector2(updateBufferIndex),
829                       sizeof(Vector2),
830                       dst + static_cast<uint32_t>(sizeof(Vector2)) * arrayIndex);
831             break;
832           }
833           case Property::Type::VECTOR3:
834           {
835             ubo.Write(&(*iter).propertyValue->GetVector3(updateBufferIndex),
836                       sizeof(Vector3),
837                       dst + static_cast<uint32_t>(sizeof(Vector3)) * arrayIndex);
838             break;
839           }
840           case Property::Type::VECTOR4:
841           {
842             ubo.Write(&(*iter).propertyValue->GetVector4(updateBufferIndex),
843                       sizeof(Vector4),
844                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
845             break;
846           }
847           case Property::Type::MATRIX:
848           {
849             ubo.Write(&(*iter).propertyValue->GetMatrix(updateBufferIndex),
850                       sizeof(Matrix),
851                       dst + static_cast<uint32_t>(sizeof(Matrix)) * arrayIndex);
852             break;
853           }
854           case Property::Type::MATRIX3:
855           {
856             // @todo: handle data padding properly
857             // Get padding requirement from Graphics
858             //
859             // Vulkan:
860             //
861             //const auto& matrix = &(*iter).propertyValue->GetMatrix3(updateBufferIndex);
862             //for(int i = 0; i < 3; ++i)
863             //{
864             //ubo.Write(&matrix->AsFloat()[i * 3],
865             //          sizeof(float) * 3,
866             //          dst + (i * static_cast<uint32_t>(sizeof(Vector4))));
867             //}
868             // GL:
869             ubo.Write(&(*iter).propertyValue->GetMatrix3(updateBufferIndex),
870                       sizeof(Matrix3),
871                       dst + static_cast<uint32_t>(sizeof(Matrix3)) * arrayIndex);
872             break;
873           }
874           default:
875           {
876           }
877         }
878       }
879     }
880   }
881   // write output bindings
882   outBindings = &mUniformBufferBindings;
883
884   // Update offset
885   offset = dataOffset;
886 }
887
888 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
889 {
890   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
891   sortAttributes.geometry = mGeometry;
892 }
893
894 void Renderer::SetShaderChanged(bool value)
895 {
896   mShaderChanged = value;
897 }
898
899 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
900 {
901   if(mUpdated)
902   {
903     mUpdated = false;
904     return true;
905   }
906
907   if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
908   {
909     return true;
910   }
911
912   for(const auto& texture : mRenderDataProvider->GetTextures())
913   {
914     if(texture && texture->IsNativeImage())
915     {
916       return true;
917     }
918   }
919
920   uint64_t                               hash           = 0xc70f6907UL;
921   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
922   for(const auto& uniformProperty : uniformMapNode)
923   {
924     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
925   }
926
927   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
928   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
929   for(const auto& uniformProperty : uniformMap)
930   {
931     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
932   }
933
934   if(mUniformsHash != hash)
935   {
936     mUniformsHash = hash;
937     return true;
938   }
939
940   return false;
941 }
942
943 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
944   Program&                                             program,
945   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
946   const SceneGraph::NodeDataProvider&                  node,
947   bool                                                 blend)
948 {
949   Graphics::InputAssemblyState inputAssemblyState{};
950   Graphics::VertexInputState   vertexInputState{};
951   Graphics::ProgramState       programState{};
952   uint32_t                     bindingIndex{0u};
953
954   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
955   {
956     mAttributeLocations.Clear();
957     mUpdateAttributeLocations = true;
958   }
959
960   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
961
962   /**
963    * Bind Attributes
964    */
965   uint32_t base = 0;
966   for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
967   {
968     const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
969
970     vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
971                                                  Graphics::VertexInputRate::PER_VERTEX);
972
973     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
974     for(uint32_t i = 0; i < attributeCount; ++i)
975     {
976       if(mUpdateAttributeLocations)
977       {
978         auto    attributeName = vertexBuffer->GetAttributeName(i);
979         int32_t pLocation     = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
980         if(-1 == pLocation)
981         {
982           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
983         }
984         mAttributeLocations.PushBack(pLocation);
985       }
986
987       auto location = static_cast<uint32_t>(mAttributeLocations[base + i]);
988
989       vertexInputState.attributes.emplace_back(location,
990                                                bindingIndex,
991                                                vertexFormat.components[i].offset,
992                                                GetPropertyVertexFormat(vertexFormat.components[i].type));
993     }
994     base += attributeCount;
995     ++bindingIndex;
996   }
997   mUpdateAttributeLocations = false;
998
999   // Get the topology
1000   inputAssemblyState.SetTopology(mGeometry->GetTopology());
1001
1002   // Get the program
1003   programState.SetProgram(program.GetGraphicsProgram());
1004
1005   Graphics::RasterizationState rasterizationState{};
1006
1007   //Set cull face  mode
1008   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
1009   if(cam->GetReflectionUsed())
1010   {
1011     auto adjFaceCullingMode = mFaceCullingMode;
1012     switch(mFaceCullingMode)
1013     {
1014       case FaceCullingMode::Type::FRONT:
1015       {
1016         adjFaceCullingMode = FaceCullingMode::Type::BACK;
1017         break;
1018       }
1019       case FaceCullingMode::Type::BACK:
1020       {
1021         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
1022         break;
1023       }
1024       default:
1025       {
1026         // nothing to do, leave culling as it is
1027       }
1028     }
1029     rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
1030   }
1031   else
1032   {
1033     rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
1034   }
1035
1036   rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
1037
1038   /**
1039    * Set Polygon mode
1040    */
1041   switch(mGeometry->GetTopology())
1042   {
1043     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
1044     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
1045     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
1046       rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
1047       break;
1048     case Graphics::PrimitiveTopology::LINE_LIST:
1049     case Graphics::PrimitiveTopology::LINE_LOOP:
1050     case Graphics::PrimitiveTopology::LINE_STRIP:
1051       rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
1052       break;
1053     case Graphics::PrimitiveTopology::POINT_LIST:
1054       rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
1055       break;
1056   }
1057
1058   // @todo Add blend barrier to the Graphics API if we are using advanced
1059   // blending options. Command?
1060
1061   Graphics::ColorBlendState colorBlendState{};
1062   colorBlendState.SetBlendEnable(false);
1063
1064   if(blend)
1065   {
1066     colorBlendState.SetBlendEnable(true);
1067
1068     Graphics::BlendOp rgbOp   = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1069     Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1070     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipliedAlphaEnabled)
1071     {
1072       if(rgbOp != alphaOp)
1073       {
1074         DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1075         alphaOp = rgbOp;
1076       }
1077     }
1078
1079     colorBlendState
1080       .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1081       .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1082       .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1083       .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1084       .SetColorBlendOp(rgbOp)
1085       .SetAlphaBlendOp(alphaOp);
1086
1087     // Blend color is optional and rarely used
1088     auto* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1089     if(blendColor)
1090     {
1091       colorBlendState.SetBlendConstants(blendColor->AsFloat());
1092     }
1093   }
1094
1095   mUpdated = true;
1096
1097   // Create the pipeline
1098   Graphics::PipelineCreateInfo createInfo;
1099   createInfo
1100     .SetInputAssemblyState(&inputAssemblyState)
1101     .SetVertexInputState(&vertexInputState)
1102     .SetRasterizationState(&rasterizationState)
1103     .SetColorBlendState(&colorBlendState)
1104     .SetProgramState(&programState);
1105
1106   // Store a pipeline per renderer per render (renderer can be owned by multiple nodes,
1107   // and re-drawn in multiple instructions).
1108   // @todo This is only needed because ColorBlend state can change. Fixme!
1109   // This is ameliorated by the fact that implementation caches pipelines, and we're only storing
1110   // handles.
1111   auto            hash           = HashedPipeline::GetHash(&node, &instruction, blend);
1112   HashedPipeline* hashedPipeline = nullptr;
1113   for(auto& element : mGraphicsPipelines)
1114   {
1115     if(element.mHash == hash)
1116     {
1117       hashedPipeline = &element;
1118       break;
1119     }
1120   }
1121
1122   if(hashedPipeline != nullptr)
1123   {
1124     hashedPipeline->mGraphicsPipeline = mGraphicsController->CreatePipeline(
1125       createInfo,
1126       std::move(hashedPipeline->mGraphicsPipeline));
1127   }
1128   else
1129   {
1130     mGraphicsPipelines.emplace_back();
1131     mGraphicsPipelines.back().mHash             = hash;
1132     mGraphicsPipelines.back().mGraphicsPipeline = mGraphicsController->CreatePipeline(createInfo, nullptr);
1133     hashedPipeline                              = &mGraphicsPipelines.back();
1134   }
1135   return *hashedPipeline->mGraphicsPipeline.get();
1136 }
1137
1138 } // namespace Render
1139
1140 } // namespace Dali::Internal