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