Merge "Fix an issue where TapGesture Events are not being received." into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2022 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/event/rendering/texture-impl.h>
26 #include <dali/internal/render/common/render-instruction.h>
27 #include <dali/internal/render/data-providers/node-data-provider.h>
28 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
29 #include <dali/internal/render/renderers/pipeline-cache.h>
30 #include <dali/internal/render/renderers/render-sampler.h>
31 #include <dali/internal/render/renderers/render-texture.h>
32 #include <dali/internal/render/renderers/render-vertex-buffer.h>
33 #include <dali/internal/render/renderers/shader-cache.h>
34 #include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
35 #include <dali/internal/render/renderers/uniform-buffer-view.h>
36 #include <dali/internal/render/shaders/program.h>
37 #include <dali/internal/render/shaders/render-shader.h>
38 #include <dali/internal/update/common/uniform-map.h>
39 #include <dali/public-api/signals/render-callback.h>
40
41 namespace Dali::Internal
42 {
43 namespace
44 {
45 // Helper to get the property value getter by type
46 typedef const float& (PropertyInputImpl::*FuncGetter)(BufferIndex) const;
47 constexpr FuncGetter GetPropertyValueGetter(Property::Type type)
48 {
49   switch(type)
50   {
51     case Property::BOOLEAN:
52     {
53       return FuncGetter(&PropertyInputImpl::GetBoolean);
54     }
55     case Property::INTEGER:
56     {
57       return FuncGetter(&PropertyInputImpl::GetInteger);
58     }
59     case Property::FLOAT:
60     {
61       return FuncGetter(&PropertyInputImpl::GetFloat);
62     }
63     case Property::VECTOR2:
64     {
65       return FuncGetter(&PropertyInputImpl::GetVector2);
66     }
67     case Property::VECTOR3:
68     {
69       return FuncGetter(&PropertyInputImpl::GetVector3);
70     }
71     case Property::VECTOR4:
72     {
73       return FuncGetter(&PropertyInputImpl::GetVector4);
74     }
75     case Property::MATRIX3:
76     {
77       return FuncGetter(&PropertyInputImpl::GetMatrix3);
78     }
79     case Property::MATRIX:
80     {
81       return FuncGetter(&PropertyInputImpl::GetMatrix);
82     }
83     default:
84     {
85       return nullptr;
86     }
87   }
88 }
89
90 /**
91  * Helper function that returns size of uniform datatypes based
92  * on property type.
93  */
94 constexpr int GetPropertyValueSizeForUniform(Property::Type type)
95 {
96   switch(type)
97   {
98     case Property::Type::BOOLEAN:
99     {
100       return sizeof(bool);
101     }
102     case Property::Type::FLOAT:
103     {
104       return sizeof(float);
105     }
106     case Property::Type::INTEGER:
107     {
108       return sizeof(int);
109     }
110     case Property::Type::VECTOR2:
111     {
112       return sizeof(Vector2);
113     }
114     case Property::Type::VECTOR3:
115     {
116       return sizeof(Vector3);
117     }
118     case Property::Type::VECTOR4:
119     {
120       return sizeof(Vector4);
121     }
122     case Property::Type::MATRIX3:
123     {
124       return sizeof(Matrix3);
125     }
126     case Property::Type::MATRIX:
127     {
128       return sizeof(Matrix);
129     }
130     default:
131     {
132       return 0;
133     }
134   };
135 }
136
137 /**
138  * Helper function to calculate the correct alignment of data for uniform buffers
139  * @param dataSize size of uniform buffer
140  * @return aligned offset of data
141  */
142 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
143 {
144   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
145 }
146
147 } // namespace
148
149 namespace Render
150 {
151 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
152                         Render::Geometry*               geometry,
153                         uint32_t                        blendingBitmask,
154                         const Vector4&                  blendColor,
155                         FaceCullingMode::Type           faceCullingMode,
156                         bool                            preMultipliedAlphaEnabled,
157                         DepthWriteMode::Type            depthWriteMode,
158                         DepthTestMode::Type             depthTestMode,
159                         DepthFunction::Type             depthFunction,
160                         StencilParameters&              stencilParameters)
161 {
162   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
163 }
164
165 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
166                    Render::Geometry*               geometry,
167                    uint32_t                        blendingBitmask,
168                    const Vector4&                  blendColor,
169                    FaceCullingMode::Type           faceCullingMode,
170                    bool                            preMultipliedAlphaEnabled,
171                    DepthWriteMode::Type            depthWriteMode,
172                    DepthTestMode::Type             depthTestMode,
173                    DepthFunction::Type             depthFunction,
174                    StencilParameters&              stencilParameters)
175 : mGraphicsController(nullptr),
176   mRenderDataProvider(dataProvider),
177   mGeometry(geometry),
178   mProgramCache(nullptr),
179   mStencilParameters(stencilParameters),
180   mBlendingOptions(),
181   mIndexedDrawFirstElement(0),
182   mIndexedDrawElementsCount(0),
183   mDepthFunction(depthFunction),
184   mFaceCullingMode(faceCullingMode),
185   mDepthWriteMode(depthWriteMode),
186   mDepthTestMode(depthTestMode),
187   mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled),
188   mShaderChanged(false),
189   mUpdated(true)
190 {
191   if(blendingBitmask != 0u)
192   {
193     mBlendingOptions.SetBitmask(blendingBitmask);
194   }
195
196   mBlendingOptions.SetBlendColor(blendColor);
197 }
198
199 void Renderer::Initialize(Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache, Render::UniformBufferManager& uniformBufferManager, Render::PipelineCache& pipelineCache)
200 {
201   mGraphicsController   = &graphicsController;
202   mProgramCache         = &programCache;
203   mShaderCache          = &shaderCache;
204   mUniformBufferManager = &uniformBufferManager;
205   mPipelineCache        = &pipelineCache;
206 }
207
208 Renderer::~Renderer() = default;
209
210 void Renderer::SetGeometry(Render::Geometry* geometry)
211 {
212   mGeometry = geometry;
213   mUpdated  = true;
214 }
215 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
216 {
217   mDrawCommands.clear();
218   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
219 }
220
221 void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
222 {
223   uint32_t textureUnit = 0;
224
225   const Dali::Vector<Render::Texture*>* textures(mRenderDataProvider->GetTextures());
226   const Dali::Vector<Render::Sampler*>* samplers(mRenderDataProvider->GetSamplers());
227
228   std::vector<Graphics::TextureBinding> textureBindings;
229
230   if(textures != nullptr)
231   {
232     const std::uint32_t texturesCount(static_cast<std::uint32_t>(textures->Count()));
233     textureBindings.reserve(texturesCount);
234
235     for(uint32_t i = 0; i < texturesCount; ++i) // not expecting more than uint32_t of textures
236     {
237       if((*textures)[i] && (*textures)[i]->GetGraphicsObject())
238       {
239         Graphics::Texture* graphicsTexture = (*textures)[i]->GetGraphicsObject();
240         // if the sampler exists,
241         //   if it's default, delete the graphics object
242         //   otherwise re-initialize it if dirty
243
244         const Graphics::Sampler* graphicsSampler = samplers ? ((*samplers)[i] ? (*samplers)[i]->GetGraphicsObject()
245                                                                               : nullptr)
246                                                             : nullptr;
247
248         boundTextures.PushBack(graphicsTexture);
249         const Graphics::TextureBinding textureBinding{graphicsTexture, graphicsSampler, textureUnit};
250         textureBindings.push_back(textureBinding);
251
252         ++textureUnit;
253       }
254     }
255   }
256
257   if(!textureBindings.empty())
258   {
259     commandBuffer.BindTextures(textureBindings);
260   }
261 }
262
263 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
264 {
265   mFaceCullingMode = mode;
266   mUpdated         = true;
267 }
268
269 void Renderer::SetBlendingBitMask(uint32_t bitmask)
270 {
271   mBlendingOptions.SetBitmask(bitmask);
272   mUpdated = true;
273 }
274
275 void Renderer::SetBlendColor(const Vector4& color)
276 {
277   mBlendingOptions.SetBlendColor(color);
278   mUpdated = true;
279 }
280
281 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
282 {
283   mIndexedDrawFirstElement = firstElement;
284   mUpdated                 = true;
285 }
286
287 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
288 {
289   mIndexedDrawElementsCount = elementsCount;
290   mUpdated                  = true;
291 }
292
293 void Renderer::EnablePreMultipliedAlpha(bool enable)
294 {
295   mPremultipliedAlphaEnabled = enable;
296   mUpdated                   = true;
297 }
298
299 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
300 {
301   mDepthWriteMode = depthWriteMode;
302   mUpdated        = true;
303 }
304
305 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
306 {
307   mDepthTestMode = depthTestMode;
308   mUpdated       = true;
309 }
310
311 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
312 {
313   return mDepthWriteMode;
314 }
315
316 DepthTestMode::Type Renderer::GetDepthTestMode() const
317 {
318   return mDepthTestMode;
319 }
320
321 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
322 {
323   mDepthFunction = depthFunction;
324   mUpdated       = true;
325 }
326
327 DepthFunction::Type Renderer::GetDepthFunction() const
328 {
329   return mDepthFunction;
330 }
331
332 void Renderer::SetRenderMode(RenderMode::Type renderMode)
333 {
334   mStencilParameters.renderMode = renderMode;
335   mUpdated                      = true;
336 }
337
338 RenderMode::Type Renderer::GetRenderMode() const
339 {
340   return mStencilParameters.renderMode;
341 }
342
343 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
344 {
345   mStencilParameters.stencilFunction = stencilFunction;
346   mUpdated                           = true;
347 }
348
349 StencilFunction::Type Renderer::GetStencilFunction() const
350 {
351   return mStencilParameters.stencilFunction;
352 }
353
354 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
355 {
356   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
357   mUpdated                               = true;
358 }
359
360 int Renderer::GetStencilFunctionMask() const
361 {
362   return mStencilParameters.stencilFunctionMask;
363 }
364
365 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
366 {
367   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
368   mUpdated                                    = true;
369 }
370
371 int Renderer::GetStencilFunctionReference() const
372 {
373   return mStencilParameters.stencilFunctionReference;
374 }
375
376 void Renderer::SetStencilMask(int stencilMask)
377 {
378   mStencilParameters.stencilMask = stencilMask;
379   mUpdated                       = true;
380 }
381
382 int Renderer::GetStencilMask() const
383 {
384   return mStencilParameters.stencilMask;
385 }
386
387 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
388 {
389   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
390   mUpdated                                  = true;
391 }
392
393 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
394 {
395   return mStencilParameters.stencilOperationOnFail;
396 }
397
398 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
399 {
400   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
401   mUpdated                                   = true;
402 }
403
404 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
405 {
406   return mStencilParameters.stencilOperationOnZFail;
407 }
408
409 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
410 {
411   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
412   mUpdated                                   = true;
413 }
414
415 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
416 {
417   return mStencilParameters.stencilOperationOnZPass;
418 }
419
420 void Renderer::Upload()
421 {
422   mGeometry->Upload(*mGraphicsController);
423 }
424
425 bool Renderer::Render(Graphics::CommandBuffer&                             commandBuffer,
426                       BufferIndex                                          bufferIndex,
427                       const SceneGraph::NodeDataProvider&                  node,
428                       const Matrix&                                        modelMatrix,
429                       const Matrix&                                        modelViewMatrix,
430                       const Matrix&                                        viewMatrix,
431                       const Matrix&                                        projectionMatrix,
432                       const Vector3&                                       size,
433                       bool                                                 blend,
434                       Vector<Graphics::Texture*>&                          boundTextures,
435                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
436                       uint32_t                                             queueIndex)
437 {
438   // Before doing anything test if the call happens in the right queue
439   if(mDrawCommands.empty() && queueIndex > 0)
440   {
441     return false;
442   }
443
444   // Check if there is render callback
445   if(mRenderCallback)
446   {
447     Graphics::DrawNativeInfo info{};
448     info.api      = Graphics::DrawNativeAPI::GLES;
449     info.callback = &static_cast<Dali::CallbackBase&>(*mRenderCallback);
450     info.userData = &mRenderCallbackInput;
451
452     // Set storage for the context to be used
453     info.glesNativeInfo.eglSharedContextStoragePointer = &mRenderCallbackInput.eglContext;
454     info.reserved                                      = nullptr;
455
456     auto& textureResources = mRenderCallback->GetTextureResources();
457
458     if(!textureResources.empty())
459     {
460       mRenderCallbackTextureBindings.clear();
461       mRenderCallbackInput.textureBindings.resize(textureResources.size());
462       auto i = 0u;
463       for(auto& texture : textureResources)
464       {
465         auto& textureImpl     = GetImplementation(texture);
466         auto  graphicsTexture = textureImpl.GetRenderObject()->GetGraphicsObject();
467
468         const auto& properties = mGraphicsController->GetTextureProperties(*graphicsTexture);
469
470         mRenderCallbackTextureBindings.emplace_back(graphicsTexture);
471         mRenderCallbackInput.textureBindings[i] = properties.nativeHandle;
472       }
473       info.textureCount = mRenderCallbackTextureBindings.size();
474       info.textureList  = mRenderCallbackTextureBindings.data();
475     }
476
477     // pass render callback input
478     mRenderCallbackInput.size       = size;
479     mRenderCallbackInput.projection = projectionMatrix;
480
481     Matrix::Multiply(mRenderCallbackInput.mvp, modelViewMatrix, projectionMatrix);
482
483     // submit draw
484     commandBuffer.DrawNative(&info);
485     return true;
486   }
487
488   // Prepare commands
489   std::vector<DevelRenderer::DrawCommand*> commands;
490   for(auto& cmd : mDrawCommands)
491   {
492     if(cmd.queue == queueIndex)
493     {
494       commands.emplace_back(&cmd);
495     }
496   }
497
498   // Have commands but nothing to be drawn - abort
499   if(!mDrawCommands.empty() && commands.empty())
500   {
501     return false;
502   }
503
504   // Set blending mode
505   if(!mDrawCommands.empty())
506   {
507     blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend;
508   }
509
510   // Create Program
511   ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
512
513   Program* program = Program::New(*mProgramCache,
514                                   shaderData,
515                                   *mGraphicsController);
516   if(!program)
517   {
518     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<const void*>(&mRenderDataProvider->GetShader()));
519     return false;
520   }
521
522   // If program doesn't have Gfx program object assigned yet, prepare it.
523   if(!program->GetGraphicsProgramPtr())
524   {
525     const std::vector<char>& vertShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
526     const std::vector<char>& fragShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
527     Dali::Graphics::Shader&  vertexShader = mShaderCache->GetShader(
528       vertShader,
529       Graphics::PipelineStage::VERTEX_SHADER,
530       shaderData->GetSourceMode());
531
532     Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
533       fragShader,
534       Graphics::PipelineStage::FRAGMENT_SHADER,
535       shaderData->GetSourceMode());
536
537     std::vector<Graphics::ShaderState> shaderStates{
538       Graphics::ShaderState()
539         .SetShader(vertexShader)
540         .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
541       Graphics::ShaderState()
542         .SetShader(fragmentShader)
543         .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
544
545     auto createInfo = Graphics::ProgramCreateInfo();
546     createInfo.SetShaderState(shaderStates);
547     auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
548     program->SetGraphicsProgram(std::move(graphicsProgram));
549   }
550
551   // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
552   auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
553
554   commandBuffer.BindPipeline(pipeline);
555
556   BindTextures(commandBuffer, boundTextures);
557
558   int nodeIndex = BuildUniformIndexMap(bufferIndex, node, size, *program);
559
560   WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size, nodeIndex);
561
562   bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
563                       // @todo We should detect this case much earlier to prevent unnecessary work
564
565   if(mDrawCommands.empty())
566   {
567     drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
568   }
569   else
570   {
571     for(auto& cmd : commands)
572     {
573       mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
574     }
575   }
576
577   mUpdated = false;
578   return drawn;
579 }
580
581 int Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
582 {
583   // Check if the map has changed
584   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
585
586   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
587   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetCollectedUniformMap();
588   const SceneGraph::UniformMap&             uniformMapNode         = node.GetNodeUniformMap();
589
590   bool updateMaps;
591
592   // Usual case is to only have 1 node, however we do allow multiple nodes to reuse the same
593   // renderer, so we have to cache uniform map per render item (node / renderer pair).
594
595   // Specially, if node don't have uniformMap, we mark nodePtr as nullptr.
596   // So, all nodes without uniformMap will share same UniformIndexMap, contains only render data providers.
597   const auto nodePtr = uniformMapNode.Count() ? &node : nullptr;
598
599   const auto nodeChangeCounter          = nodePtr ? uniformMapNode.GetChangeCounter() : 0;
600   const auto renderItemMapChangeCounter = uniformMap.GetChangeCounter();
601
602   auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [nodePtr](RenderItemLookup& element) { return element.node == nodePtr; });
603
604   int renderItemMapIndex;
605   if(iter == mNodeIndexMap.end())
606   {
607     renderItemMapIndex = mUniformIndexMaps.size();
608     RenderItemLookup renderItemLookup;
609     renderItemLookup.node                       = nodePtr;
610     renderItemLookup.index                      = renderItemMapIndex;
611     renderItemLookup.nodeChangeCounter          = nodeChangeCounter;
612     renderItemLookup.renderItemMapChangeCounter = renderItemMapChangeCounter;
613     mNodeIndexMap.emplace_back(renderItemLookup);
614
615     updateMaps = true;
616     mUniformIndexMaps.resize(mUniformIndexMaps.size() + 1);
617   }
618   else
619   {
620     renderItemMapIndex = iter->index;
621
622     updateMaps = (nodeChangeCounter != iter->nodeChangeCounter) ||
623                  (renderItemMapChangeCounter != iter->renderItemMapChangeCounter) ||
624                  (mUniformIndexMaps[renderItemMapIndex].size() == 0);
625
626     iter->nodeChangeCounter          = nodeChangeCounter;
627     iter->renderItemMapChangeCounter = renderItemMapChangeCounter;
628   }
629
630   if(updateMaps || mShaderChanged)
631   {
632     // Reset shader pointer
633     mShaderChanged = false;
634
635     const uint32_t mapCount     = uniformMap.Count();
636     const uint32_t mapNodeCount = uniformMapNode.Count();
637
638     mUniformIndexMaps[renderItemMapIndex].clear(); // Clear contents, but keep memory if we don't change size
639     mUniformIndexMaps[renderItemMapIndex].resize(mapCount + mapNodeCount);
640
641     // Copy uniform map into mUniformIndexMap
642     uint32_t mapIndex = 0;
643     for(; mapIndex < mapCount; ++mapIndex)
644     {
645       mUniformIndexMaps[renderItemMapIndex][mapIndex].propertyValue          = uniformMap.mUniformMap[mapIndex].propertyPtr;
646       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformName            = uniformMap.mUniformMap[mapIndex].uniformName;
647       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHash        = uniformMap.mUniformMap[mapIndex].uniformNameHash;
648       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHashNoArray = uniformMap.mUniformMap[mapIndex].uniformNameHashNoArray;
649       mUniformIndexMaps[renderItemMapIndex][mapIndex].arrayIndex             = uniformMap.mUniformMap[mapIndex].arrayIndex;
650     }
651
652     for(uint32_t nodeMapIndex = 0; nodeMapIndex < mapNodeCount; ++nodeMapIndex)
653     {
654       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
655       auto& name = uniformMapNode[nodeMapIndex].uniformName;
656       bool  found(false);
657       for(uint32_t i = 0; i < mapCount; ++i)
658       {
659         if(mUniformIndexMaps[renderItemMapIndex][i].uniformNameHash == hash &&
660            mUniformIndexMaps[renderItemMapIndex][i].uniformName == name)
661         {
662           mUniformIndexMaps[renderItemMapIndex][i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
663           found                                                  = true;
664           break;
665         }
666       }
667
668       if(!found)
669       {
670         mUniformIndexMaps[renderItemMapIndex][mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
671         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
672         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
673         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
674         mUniformIndexMaps[renderItemMapIndex][mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
675         ++mapIndex;
676       }
677     }
678
679     mUniformIndexMaps[renderItemMapIndex].resize(mapIndex);
680   }
681   return renderItemMapIndex;
682 }
683
684 void Renderer::WriteUniformBuffer(
685   BufferIndex                          bufferIndex,
686   Graphics::CommandBuffer&             commandBuffer,
687   Program*                             program,
688   const SceneGraph::RenderInstruction& instruction,
689   const SceneGraph::NodeDataProvider&  node,
690   const Matrix&                        modelMatrix,
691   const Matrix&                        modelViewMatrix,
692   const Matrix&                        viewMatrix,
693   const Matrix&                        projectionMatrix,
694   const Vector3&                       size,
695   int                                  nodeIndex)
696 {
697   // Create the UBO
698   uint32_t uboOffset{0u};
699
700   auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
701
702   uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired;
703
704   // Create uniform buffer view from uniform buffer
705   Graphics::UniquePtr<Render::UniformBufferView> uboView{nullptr};
706   if(uniformBlockAllocationBytes)
707   {
708     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex);
709     uboView          = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
710   }
711
712   // update the uniform buffer
713   // pass shared UBO and offset, return new offset for next item to be used
714   // don't process bindings if there are no uniform buffers allocated
715   if(uboView)
716   {
717     auto uboCount = reflection.GetUniformBlockCount();
718     mUniformBufferBindings.resize(uboCount);
719
720     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
721
722     mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset);
723
724     // Write default uniforms
725     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, modelMatrix);
726     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, viewMatrix);
727     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, projectionMatrix);
728     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, modelViewMatrix);
729
730     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
731     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
732     {
733       Matrix modelViewProjectionMatrix(false);
734       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
735       WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix);
736     }
737
738     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
739     if(normalUniformInfo && !normalUniformInfo->name.empty())
740     {
741       Matrix3 normalMatrix(modelViewMatrix);
742       normalMatrix.Invert();
743       normalMatrix.Transpose();
744       WriteDefaultUniform(normalUniformInfo, *uboView, normalMatrix);
745     }
746
747     Vector4        finalColor;                               ///< Applied renderer's opacity color
748     const Vector4& color = node.GetRenderColor(bufferIndex); ///< Actor's original color
749     if(mPremultipliedAlphaEnabled)
750     {
751       const float& alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
752       finalColor         = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
753     }
754     else
755     {
756       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
757     }
758     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, finalColor);
759     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::ACTOR_COLOR), *uboView, color);
760
761     // Write uniforms from the uniform map
762     FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex, nodeIndex);
763
764     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
765     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, size);
766
767     commandBuffer.BindUniformBuffers(*bindings);
768   }
769 }
770
771 template<class T>
772 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data)
773 {
774   if(uniformInfo && !uniformInfo->name.empty())
775   {
776     WriteUniform(ubo, *uniformInfo, data);
777     return true;
778   }
779   return false;
780 }
781
782 template<class T>
783 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data)
784 {
785   WriteUniform(ubo, uniformInfo, &data, sizeof(T));
786 }
787
788 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
789 {
790   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
791 }
792
793 void Renderer::FillUniformBuffer(Program&                                      program,
794                                  const SceneGraph::RenderInstruction&          instruction,
795                                  Render::UniformBufferView&                    ubo,
796                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
797                                  uint32_t&                                     offset,
798                                  BufferIndex                                   updateBufferIndex,
799                                  int                                           nodeIndex)
800 {
801   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
802   auto  uboCount   = reflection.GetUniformBlockCount();
803
804   // Setup bindings
805   uint32_t dataOffset = offset;
806   for(auto i = 0u; i < uboCount; ++i)
807   {
808     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
809     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
810
811     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
812     mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset);
813
814     for(auto iter = mUniformIndexMaps[nodeIndex].begin(),
815              end  = mUniformIndexMaps[nodeIndex].end();
816         iter != end;
817         ++iter)
818     {
819       auto& uniform    = *iter;
820       int   arrayIndex = uniform.arrayIndex;
821
822       if(!uniform.uniformFunc)
823       {
824         auto uniformInfo  = Graphics::UniformInfo{};
825         auto uniformFound = program.GetUniform(uniform.uniformName.GetStringView(),
826                                                uniform.uniformNameHash,
827                                                uniform.uniformNameHashNoArray,
828                                                uniformInfo);
829
830         uniform.uniformOffset   = uniformInfo.offset;
831         uniform.uniformLocation = uniformInfo.location;
832
833         if(uniformFound)
834         {
835           auto       dst      = ubo.GetOffset() + uniformInfo.offset;
836           const auto typeSize = GetPropertyValueSizeForUniform((*iter).propertyValue->GetType());
837           const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
838           const auto func     = GetPropertyValueGetter((*iter).propertyValue->GetType());
839
840           ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
841                     typeSize,
842                     dest);
843
844           uniform.uniformSize = typeSize;
845           uniform.uniformFunc = func;
846         }
847       }
848       else
849       {
850         auto       dst      = ubo.GetOffset() + uniform.uniformOffset;
851         const auto typeSize = uniform.uniformSize;
852         const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
853         const auto func     = uniform.uniformFunc;
854
855         ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
856                   typeSize,
857                   dest);
858       }
859     }
860   }
861   // write output bindings
862   outBindings = &mUniformBufferBindings;
863
864   // Update offset
865   offset = dataOffset;
866 }
867
868 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
869 {
870   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
871   sortAttributes.geometry = mGeometry;
872 }
873
874 void Renderer::SetShaderChanged(bool value)
875 {
876   mShaderChanged = value;
877 }
878
879 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
880 {
881   if(mUpdated)
882   {
883     mUpdated = false;
884     return true;
885   }
886
887   if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged())
888   {
889     return true;
890   }
891
892   auto* textures = mRenderDataProvider->GetTextures();
893   if(textures)
894   {
895     for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter)
896     {
897       auto texture = *iter;
898       if(texture && texture->IsNativeImage())
899       {
900         return true;
901       }
902     }
903   }
904
905   // Hash the property values. If the values are different, then rendering is required.
906   uint64_t                      hash           = 0xc70f6907UL;
907   const SceneGraph::UniformMap& uniformMapNode = node->GetNodeUniformMap();
908   for(uint32_t i = 0u, count = uniformMapNode.Count(); i < count; ++i)
909   {
910     hash = uniformMapNode[i].propertyPtr->Hash(bufferIndex, hash);
911   }
912
913   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
914   const SceneGraph::CollectedUniformMap&    collectedUniformMap    = uniformMapDataProvider.GetCollectedUniformMap();
915   for(uint32_t i = 0u, count = collectedUniformMap.Count(); i < count; ++i)
916   {
917     hash = collectedUniformMap.mUniformMap[i].propertyPtr->Hash(bufferIndex, hash);
918   }
919
920   if(mUniformsHash != hash)
921   {
922     mUniformsHash = hash;
923     return true;
924   }
925
926   return false;
927 }
928
929 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
930   Program&                                             program,
931   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
932   const SceneGraph::NodeDataProvider&                  node,
933   bool                                                 blend)
934 {
935   if(mGeometry->AttributesChanged())
936   {
937     mUpdated = true;
938   }
939
940   // Prepare query info
941   PipelineCacheQueryInfo queryInfo{};
942   queryInfo.program               = &program;
943   queryInfo.renderer              = this;
944   queryInfo.geometry              = mGeometry;
945   queryInfo.blendingEnabled       = blend;
946   queryInfo.blendingOptions       = &mBlendingOptions;
947   queryInfo.alphaPremultiplied    = mPremultipliedAlphaEnabled;
948   queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed();
949
950   auto pipelineResult = mPipelineCache->GetPipeline(queryInfo, true);
951
952   // should be never null?
953   return *pipelineResult.pipeline;
954 }
955
956 void Renderer::SetRenderCallback(RenderCallback* callback)
957 {
958   mRenderCallback = callback;
959 }
960
961 } // namespace Render
962
963 } // namespace Dali::Internal