Implement some more speed-up : Reserve TextureBindings + don't copy geometry
[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/render/common/render-instruction.h>
26 #include <dali/internal/render/data-providers/node-data-provider.h>
27 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
28 #include <dali/internal/render/renderers/pipeline-cache.h>
29 #include <dali/internal/render/renderers/render-sampler.h>
30 #include <dali/internal/render/renderers/render-texture.h>
31 #include <dali/internal/render/renderers/render-vertex-buffer.h>
32 #include <dali/internal/render/renderers/shader-cache.h>
33 #include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
34 #include <dali/internal/render/renderers/uniform-buffer-view.h>
35 #include <dali/internal/render/shaders/program.h>
36 #include <dali/internal/render/shaders/render-shader.h>
37 #include <dali/internal/update/common/uniform-map.h>
38
39 namespace Dali::Internal
40 {
41 namespace
42 {
43 // Helper to get the property value getter by type
44 typedef const float& (PropertyInputImpl::*FuncGetter)(BufferIndex) const;
45 constexpr FuncGetter GetPropertyValueGetter(Property::Type type)
46 {
47   switch(type)
48   {
49     case Property::BOOLEAN:
50     {
51       return FuncGetter(&PropertyInputImpl::GetBoolean);
52     }
53     case Property::INTEGER:
54     {
55       return FuncGetter(&PropertyInputImpl::GetInteger);
56     }
57     case Property::FLOAT:
58     {
59       return FuncGetter(&PropertyInputImpl::GetFloat);
60     }
61     case Property::VECTOR2:
62     {
63       return FuncGetter(&PropertyInputImpl::GetVector2);
64     }
65     case Property::VECTOR3:
66     {
67       return FuncGetter(&PropertyInputImpl::GetVector3);
68     }
69     case Property::VECTOR4:
70     {
71       return FuncGetter(&PropertyInputImpl::GetVector4);
72     }
73     case Property::MATRIX3:
74     {
75       return FuncGetter(&PropertyInputImpl::GetMatrix3);
76     }
77     case Property::MATRIX:
78     {
79       return FuncGetter(&PropertyInputImpl::GetMatrix);
80     }
81     default:
82     {
83       return nullptr;
84     }
85   }
86 }
87
88 /**
89  * Helper function that returns size of uniform datatypes based
90  * on property type.
91  */
92 constexpr int GetPropertyValueSizeForUniform(Property::Type type)
93 {
94   switch(type)
95   {
96     case Property::Type::BOOLEAN:
97     {
98       return sizeof(bool);
99     }
100     case Property::Type::FLOAT:
101     {
102       return sizeof(float);
103     }
104     case Property::Type::INTEGER:
105     {
106       return sizeof(int);
107     }
108     case Property::Type::VECTOR2:
109     {
110       return sizeof(Vector2);
111     }
112     case Property::Type::VECTOR3:
113     {
114       return sizeof(Vector3);
115     }
116     case Property::Type::VECTOR4:
117     {
118       return sizeof(Vector4);
119     }
120     case Property::Type::MATRIX3:
121     {
122       return sizeof(Matrix3);
123     }
124     case Property::Type::MATRIX:
125     {
126       return sizeof(Matrix);
127     }
128     default:
129     {
130       return 0;
131     }
132   };
133 }
134
135 /**
136  * Helper function to calculate the correct alignment of data for uniform buffers
137  * @param dataSize size of uniform buffer
138  * @return aligned offset of data
139  */
140 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
141 {
142   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
143 }
144
145 } // namespace
146
147 namespace Render
148 {
149 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
150                         Render::Geometry*               geometry,
151                         uint32_t                        blendingBitmask,
152                         const Vector4&                  blendColor,
153                         FaceCullingMode::Type           faceCullingMode,
154                         bool                            preMultipliedAlphaEnabled,
155                         DepthWriteMode::Type            depthWriteMode,
156                         DepthTestMode::Type             depthTestMode,
157                         DepthFunction::Type             depthFunction,
158                         StencilParameters&              stencilParameters)
159 {
160   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
161 }
162
163 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
164                    Render::Geometry*               geometry,
165                    uint32_t                        blendingBitmask,
166                    const Vector4&                  blendColor,
167                    FaceCullingMode::Type           faceCullingMode,
168                    bool                            preMultipliedAlphaEnabled,
169                    DepthWriteMode::Type            depthWriteMode,
170                    DepthTestMode::Type             depthTestMode,
171                    DepthFunction::Type             depthFunction,
172                    StencilParameters&              stencilParameters)
173 : mGraphicsController(nullptr),
174   mRenderDataProvider(dataProvider),
175   mGeometry(geometry),
176   mProgramCache(nullptr),
177   mUniformIndexMap(),
178   mUniformsHash(),
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   // Prepare commands
445   std::vector<DevelRenderer::DrawCommand*> commands;
446   for(auto& cmd : mDrawCommands)
447   {
448     if(cmd.queue == queueIndex)
449     {
450       commands.emplace_back(&cmd);
451     }
452   }
453
454   // Have commands but nothing to be drawn - abort
455   if(!mDrawCommands.empty() && commands.empty())
456   {
457     return false;
458   }
459
460   // Set blending mode
461   if(!mDrawCommands.empty())
462   {
463     blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend;
464   }
465
466   // Create Program
467   ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
468
469   Program* program = Program::New(*mProgramCache,
470                                   shaderData,
471                                   *mGraphicsController);
472   if(!program)
473   {
474     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<const void*>(&mRenderDataProvider->GetShader()));
475     return false;
476   }
477
478   // If program doesn't have Gfx program object assigned yet, prepare it.
479   if(!program->GetGraphicsProgramPtr())
480   {
481     const std::vector<char>& vertShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
482     const std::vector<char>& fragShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
483     Dali::Graphics::Shader&  vertexShader = mShaderCache->GetShader(
484       vertShader,
485       Graphics::PipelineStage::VERTEX_SHADER,
486       shaderData->GetSourceMode());
487
488     Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
489       fragShader,
490       Graphics::PipelineStage::FRAGMENT_SHADER,
491       shaderData->GetSourceMode());
492
493     std::vector<Graphics::ShaderState> shaderStates{
494       Graphics::ShaderState()
495         .SetShader(vertexShader)
496         .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
497       Graphics::ShaderState()
498         .SetShader(fragmentShader)
499         .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
500
501     auto createInfo = Graphics::ProgramCreateInfo();
502     createInfo.SetShaderState(shaderStates);
503     auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
504     program->SetGraphicsProgram(std::move(graphicsProgram));
505   }
506
507   // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
508   auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
509
510   commandBuffer.BindPipeline(pipeline);
511
512   BindTextures(commandBuffer, boundTextures);
513
514   BuildUniformIndexMap(bufferIndex, node, size, *program);
515
516   WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size);
517
518   bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
519                       // @todo We should detect this case much earlier to prevent unnecessary work
520
521   if(mDrawCommands.empty())
522   {
523     drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
524   }
525   else
526   {
527     for(auto& cmd : commands)
528     {
529       mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
530     }
531   }
532
533   mUpdated = false;
534   return drawn;
535 }
536
537 void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
538 {
539   // Check if the map has changed
540   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
541
542   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
543
544   if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
545      node.GetUniformMapChanged(bufferIndex) ||
546      mUniformIndexMap.Count() == 0 ||
547      mShaderChanged)
548   {
549     // Reset shader pointer
550     mShaderChanged = false;
551
552     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
553     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
554
555     auto maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
556     mUniformIndexMap.Clear();                                                          // Clear contents, but keep memory if we don't change size
557     mUniformIndexMap.Resize(maxMaps);
558
559     // Copy uniform map into mUniformIndexMap
560     uint32_t mapIndex = 0;
561     for(; mapIndex < uniformMap.Count(); ++mapIndex)
562     {
563       mUniformIndexMap[mapIndex].propertyValue          = uniformMap[mapIndex].propertyPtr;
564       mUniformIndexMap[mapIndex].uniformName            = uniformMap[mapIndex].uniformName;
565       mUniformIndexMap[mapIndex].uniformNameHash        = uniformMap[mapIndex].uniformNameHash;
566       mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMap[mapIndex].uniformNameHashNoArray;
567       mUniformIndexMap[mapIndex].arrayIndex             = uniformMap[mapIndex].arrayIndex;
568     }
569
570     for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
571     {
572       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
573       auto& name = uniformMapNode[nodeMapIndex].uniformName;
574       bool  found(false);
575       for(uint32_t i = 0; i < uniformMap.Count(); ++i)
576       {
577         if(mUniformIndexMap[i].uniformNameHash == hash &&
578            mUniformIndexMap[i].uniformName == name)
579         {
580           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
581           found                             = true;
582           break;
583         }
584       }
585
586       if(!found)
587       {
588         mUniformIndexMap[mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
589         mUniformIndexMap[mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
590         mUniformIndexMap[mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
591         mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
592         mUniformIndexMap[mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
593         ++mapIndex;
594       }
595     }
596
597     mUniformIndexMap.Resize(mapIndex);
598   }
599 }
600
601 void Renderer::WriteUniformBuffer(
602   BufferIndex                          bufferIndex,
603   Graphics::CommandBuffer&             commandBuffer,
604   Program*                             program,
605   const SceneGraph::RenderInstruction& instruction,
606   const SceneGraph::NodeDataProvider&  node,
607   const Matrix&                        modelMatrix,
608   const Matrix&                        modelViewMatrix,
609   const Matrix&                        viewMatrix,
610   const Matrix&                        projectionMatrix,
611   const Vector3&                       size)
612 {
613   // Create the UBO
614   uint32_t uboOffset{0u};
615
616   auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
617
618   uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired;
619
620   // Create uniform buffer view from uniform buffer
621   Graphics::UniquePtr<Render::UniformBufferView> uboView{nullptr};
622   if(uniformBlockAllocationBytes)
623   {
624     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex);
625
626     uboView = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
627   }
628
629   // update the uniform buffer
630   // pass shared UBO and offset, return new offset for next item to be used
631   // don't process bindings if there are no uniform buffers allocated
632   if(uboView)
633   {
634     auto uboCount = reflection.GetUniformBlockCount();
635     mUniformBufferBindings.resize(uboCount);
636
637     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
638
639     mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset);
640
641     // Write default uniforms
642     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, modelMatrix);
643     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, viewMatrix);
644     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, projectionMatrix);
645     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, modelViewMatrix);
646
647     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
648     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
649     {
650       Matrix modelViewProjectionMatrix(false);
651       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
652       WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix);
653     }
654
655     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
656     if(normalUniformInfo && !normalUniformInfo->name.empty())
657     {
658       Matrix3 normalMatrix(modelViewMatrix);
659       normalMatrix.Invert();
660       normalMatrix.Transpose();
661       WriteDefaultUniform(normalUniformInfo, *uboView, normalMatrix);
662     }
663
664     Vector4        finalColor;                               ///< Applied renderer's opacity color
665     const Vector4& color = node.GetRenderColor(bufferIndex); ///< Actor's original color
666     if(mPremultipliedAlphaEnabled)
667     {
668       const float& alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
669       finalColor         = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
670     }
671     else
672     {
673       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
674     }
675     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, finalColor);
676     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::ACTOR_COLOR), *uboView, color);
677
678     // Write uniforms from the uniform map
679     FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex);
680
681     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
682     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, size);
683
684     commandBuffer.BindUniformBuffers(*bindings);
685   }
686 }
687
688 template<class T>
689 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data)
690 {
691   if(uniformInfo && !uniformInfo->name.empty())
692   {
693     WriteUniform(ubo, *uniformInfo, data);
694     return true;
695   }
696   return false;
697 }
698
699 template<class T>
700 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data)
701 {
702   WriteUniform(ubo, uniformInfo, &data, sizeof(T));
703 }
704
705 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
706 {
707   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
708 }
709
710 void Renderer::FillUniformBuffer(Program&                                      program,
711                                  const SceneGraph::RenderInstruction&          instruction,
712                                  Render::UniformBufferView&                    ubo,
713                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
714                                  uint32_t&                                     offset,
715                                  BufferIndex                                   updateBufferIndex)
716 {
717   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
718   auto  uboCount   = reflection.GetUniformBlockCount();
719
720   // Setup bindings
721   uint32_t dataOffset = offset;
722   for(auto i = 0u; i < uboCount; ++i)
723   {
724     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
725     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
726
727     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
728     mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset);
729
730     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
731                                        end  = mUniformIndexMap.End();
732         iter != end;
733         ++iter)
734     {
735       auto& uniform    = *iter;
736       int   arrayIndex = uniform.arrayIndex;
737
738       if(!uniform.uniformFunc)
739       {
740         auto uniformInfo  = Graphics::UniformInfo{};
741         auto uniformFound = program.GetUniform(uniform.uniformName.GetCString(),
742                                                uniform.uniformNameHashNoArray ? uniform.uniformNameHashNoArray
743                                                                               : uniform.uniformNameHash,
744                                                uniformInfo);
745
746         uniform.uniformOffset   = uniformInfo.offset;
747         uniform.uniformLocation = uniformInfo.location;
748
749         if(uniformFound)
750         {
751           auto       dst      = ubo.GetOffset() + uniformInfo.offset;
752           const auto typeSize = GetPropertyValueSizeForUniform((*iter).propertyValue->GetType());
753           const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
754           const auto func     = GetPropertyValueGetter((*iter).propertyValue->GetType());
755
756           ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
757                     typeSize,
758                     dest);
759
760           uniform.uniformSize = typeSize;
761           uniform.uniformFunc = func;
762         }
763       }
764       else
765       {
766         auto       dst      = ubo.GetOffset() + uniform.uniformOffset;
767         const auto typeSize = uniform.uniformSize;
768         const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
769         const auto func     = uniform.uniformFunc;
770
771         ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
772                   typeSize,
773                   dest);
774       }
775     }
776   }
777   // write output bindings
778   outBindings = &mUniformBufferBindings;
779
780   // Update offset
781   offset = dataOffset;
782 }
783
784 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
785 {
786   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
787   sortAttributes.geometry = mGeometry;
788 }
789
790 void Renderer::SetShaderChanged(bool value)
791 {
792   mShaderChanged = value;
793 }
794
795 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
796 {
797   if(mUpdated)
798   {
799     mUpdated = false;
800     return true;
801   }
802
803   if(mShaderChanged || mGeometry->AttributesChanged())
804   {
805     return true;
806   }
807
808   auto* textures = mRenderDataProvider->GetTextures();
809   if(textures)
810   {
811     for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter)
812     {
813       auto texture = *iter;
814       if(texture && texture->IsNativeImage())
815       {
816         return true;
817       }
818     }
819   }
820
821   uint64_t                               hash           = 0xc70f6907UL;
822   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
823   for(const auto& uniformProperty : uniformMapNode)
824   {
825     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
826   }
827
828   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
829   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
830   for(const auto& uniformProperty : uniformMap)
831   {
832     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
833   }
834
835   if(mUniformsHash != hash)
836   {
837     mUniformsHash = hash;
838     return true;
839   }
840
841   return false;
842 }
843
844 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
845   Program&                                             program,
846   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
847   const SceneGraph::NodeDataProvider&                  node,
848   bool                                                 blend)
849 {
850   if(mGeometry->AttributesChanged())
851   {
852     mUpdated = true;
853   }
854
855   // Prepare query info
856   PipelineCacheQueryInfo queryInfo{};
857   queryInfo.program               = &program;
858   queryInfo.renderer              = this;
859   queryInfo.geometry              = mGeometry;
860   queryInfo.blendingEnabled       = blend;
861   queryInfo.blendingOptions       = &mBlendingOptions;
862   queryInfo.alphaPremultiplied    = mPremultipliedAlphaEnabled;
863   queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed();
864
865   auto pipelineResult = mPipelineCache->GetPipeline(queryInfo, true);
866
867   // should be never null?
868   return *pipelineResult.pipeline;
869 }
870
871 } // namespace Render
872
873 } // namespace Dali::Internal