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