9c8dd47c889d317e1cd966adaff9894a4697b417
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/renderers/render-renderer.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/graphics-api/graphics-types.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/internal/common/image-sampler.h>
25 #include <dali/internal/render/common/render-instruction.h>
26 #include <dali/internal/render/data-providers/node-data-provider.h>
27 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
28 #include <dali/internal/render/renderers/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     for(uint32_t i = 0; i < static_cast<uint32_t>(textures->Count()); ++i) // not expecting more than uint32_t of textures
233     {
234       if((*textures)[i] && (*textures)[i]->GetGraphicsObject())
235       {
236         // if the sampler exists,
237         //   if it's default, delete the graphics object
238         //   otherwise re-initialize it if dirty
239
240         const Graphics::Sampler* graphicsSampler = samplers ? ((*samplers)[i] ? (*samplers)[i]->GetGraphicsObject()
241                                                                               : nullptr)
242                                                             : nullptr;
243
244         boundTextures.PushBack((*textures)[i]->GetGraphicsObject());
245         const Graphics::TextureBinding textureBinding{(*textures)[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
246         textureBindings.push_back(textureBinding);
247
248         ++textureUnit;
249       }
250     }
251   }
252
253   if(!textureBindings.empty())
254   {
255     commandBuffer.BindTextures(textureBindings);
256   }
257 }
258
259 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
260 {
261   mFaceCullingMode = mode;
262   mUpdated         = true;
263 }
264
265 void Renderer::SetBlendingBitMask(uint32_t bitmask)
266 {
267   mBlendingOptions.SetBitmask(bitmask);
268   mUpdated = true;
269 }
270
271 void Renderer::SetBlendColor(const Vector4& color)
272 {
273   mBlendingOptions.SetBlendColor(color);
274   mUpdated = true;
275 }
276
277 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
278 {
279   mIndexedDrawFirstElement = firstElement;
280   mUpdated                 = true;
281 }
282
283 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
284 {
285   mIndexedDrawElementsCount = elementsCount;
286   mUpdated                  = true;
287 }
288
289 void Renderer::EnablePreMultipliedAlpha(bool enable)
290 {
291   mPremultipliedAlphaEnabled = enable;
292   mUpdated                   = true;
293 }
294
295 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
296 {
297   mDepthWriteMode = depthWriteMode;
298   mUpdated        = true;
299 }
300
301 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
302 {
303   mDepthTestMode = depthTestMode;
304   mUpdated       = true;
305 }
306
307 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
308 {
309   return mDepthWriteMode;
310 }
311
312 DepthTestMode::Type Renderer::GetDepthTestMode() const
313 {
314   return mDepthTestMode;
315 }
316
317 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
318 {
319   mDepthFunction = depthFunction;
320   mUpdated       = true;
321 }
322
323 DepthFunction::Type Renderer::GetDepthFunction() const
324 {
325   return mDepthFunction;
326 }
327
328 void Renderer::SetRenderMode(RenderMode::Type renderMode)
329 {
330   mStencilParameters.renderMode = renderMode;
331   mUpdated                      = true;
332 }
333
334 RenderMode::Type Renderer::GetRenderMode() const
335 {
336   return mStencilParameters.renderMode;
337 }
338
339 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
340 {
341   mStencilParameters.stencilFunction = stencilFunction;
342   mUpdated                           = true;
343 }
344
345 StencilFunction::Type Renderer::GetStencilFunction() const
346 {
347   return mStencilParameters.stencilFunction;
348 }
349
350 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
351 {
352   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
353   mUpdated                               = true;
354 }
355
356 int Renderer::GetStencilFunctionMask() const
357 {
358   return mStencilParameters.stencilFunctionMask;
359 }
360
361 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
362 {
363   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
364   mUpdated                                    = true;
365 }
366
367 int Renderer::GetStencilFunctionReference() const
368 {
369   return mStencilParameters.stencilFunctionReference;
370 }
371
372 void Renderer::SetStencilMask(int stencilMask)
373 {
374   mStencilParameters.stencilMask = stencilMask;
375   mUpdated                       = true;
376 }
377
378 int Renderer::GetStencilMask() const
379 {
380   return mStencilParameters.stencilMask;
381 }
382
383 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
384 {
385   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
386   mUpdated                                  = true;
387 }
388
389 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
390 {
391   return mStencilParameters.stencilOperationOnFail;
392 }
393
394 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
395 {
396   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
397   mUpdated                                   = true;
398 }
399
400 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
401 {
402   return mStencilParameters.stencilOperationOnZFail;
403 }
404
405 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
406 {
407   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
408   mUpdated                                   = true;
409 }
410
411 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
412 {
413   return mStencilParameters.stencilOperationOnZPass;
414 }
415
416 void Renderer::Upload()
417 {
418   mGeometry->Upload(*mGraphicsController);
419 }
420
421 bool Renderer::Render(Graphics::CommandBuffer&                             commandBuffer,
422                       BufferIndex                                          bufferIndex,
423                       const SceneGraph::NodeDataProvider&                  node,
424                       const Matrix&                                        modelMatrix,
425                       const Matrix&                                        modelViewMatrix,
426                       const Matrix&                                        viewMatrix,
427                       const Matrix&                                        projectionMatrix,
428                       const Vector3&                                       size,
429                       bool                                                 blend,
430                       Vector<Graphics::Texture*>&                          boundTextures,
431                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
432                       uint32_t                                             queueIndex)
433 {
434   // Before doing anything test if the call happens in the right queue
435   if(mDrawCommands.empty() && queueIndex > 0)
436   {
437     return false;
438   }
439
440   // Prepare commands
441   std::vector<DevelRenderer::DrawCommand*> commands;
442   for(auto& cmd : mDrawCommands)
443   {
444     if(cmd.queue == queueIndex)
445     {
446       commands.emplace_back(&cmd);
447     }
448   }
449
450   // Have commands but nothing to be drawn - abort
451   if(!mDrawCommands.empty() && commands.empty())
452   {
453     return false;
454   }
455
456   // Set blending mode
457   if(!mDrawCommands.empty())
458   {
459     blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend;
460   }
461
462   // Create Program
463   ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
464
465   Program* program = Program::New(*mProgramCache,
466                                   shaderData,
467                                   *mGraphicsController);
468   if(!program)
469   {
470     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<const void*>(&mRenderDataProvider->GetShader()));
471     return false;
472   }
473
474   // If program doesn't have Gfx program object assigned yet, prepare it.
475   if(!program->GetGraphicsProgramPtr())
476   {
477     const std::vector<char>& vertShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
478     const std::vector<char>& fragShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
479     Dali::Graphics::Shader&  vertexShader = mShaderCache->GetShader(
480       vertShader,
481       Graphics::PipelineStage::VERTEX_SHADER,
482       shaderData->GetSourceMode());
483
484     Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
485       fragShader,
486       Graphics::PipelineStage::FRAGMENT_SHADER,
487       shaderData->GetSourceMode());
488
489     std::vector<Graphics::ShaderState> shaderStates{
490       Graphics::ShaderState()
491         .SetShader(vertexShader)
492         .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
493       Graphics::ShaderState()
494         .SetShader(fragmentShader)
495         .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
496
497     auto createInfo = Graphics::ProgramCreateInfo();
498     createInfo.SetShaderState(shaderStates);
499     auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
500     program->SetGraphicsProgram(std::move(graphicsProgram));
501   }
502
503   // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
504   auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
505
506   commandBuffer.BindPipeline(pipeline);
507
508   BindTextures(commandBuffer, boundTextures);
509
510   BuildUniformIndexMap(bufferIndex, node, size, *program);
511
512   WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size);
513
514   bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
515                       // @todo We should detect this case much earlier to prevent unnecessary work
516
517   if(mDrawCommands.empty())
518   {
519     drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
520   }
521   else
522   {
523     for(auto& cmd : commands)
524     {
525       mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
526     }
527   }
528
529   mUpdated = false;
530   return drawn;
531 }
532
533 void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
534 {
535   // Check if the map has changed
536   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
537
538   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
539
540   if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
541      node.GetUniformMapChanged(bufferIndex) ||
542      mUniformIndexMap.Count() == 0 ||
543      mShaderChanged)
544   {
545     // Reset shader pointer
546     mShaderChanged = false;
547
548     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
549     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
550
551     auto maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
552     mUniformIndexMap.Clear();                                                          // Clear contents, but keep memory if we don't change size
553     mUniformIndexMap.Resize(maxMaps);
554
555     // Copy uniform map into mUniformIndexMap
556     uint32_t mapIndex = 0;
557     for(; mapIndex < uniformMap.Count(); ++mapIndex)
558     {
559       mUniformIndexMap[mapIndex].propertyValue          = uniformMap[mapIndex].propertyPtr;
560       mUniformIndexMap[mapIndex].uniformName            = uniformMap[mapIndex].uniformName;
561       mUniformIndexMap[mapIndex].uniformNameHash        = uniformMap[mapIndex].uniformNameHash;
562       mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMap[mapIndex].uniformNameHashNoArray;
563       mUniformIndexMap[mapIndex].arrayIndex             = uniformMap[mapIndex].arrayIndex;
564     }
565
566     for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
567     {
568       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
569       auto& name = uniformMapNode[nodeMapIndex].uniformName;
570       bool  found(false);
571       for(uint32_t i = 0; i < uniformMap.Count(); ++i)
572       {
573         if(mUniformIndexMap[i].uniformNameHash == hash &&
574            mUniformIndexMap[i].uniformName == name)
575         {
576           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
577           found                             = true;
578           break;
579         }
580       }
581
582       if(!found)
583       {
584         mUniformIndexMap[mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
585         mUniformIndexMap[mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
586         mUniformIndexMap[mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
587         mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
588         mUniformIndexMap[mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
589         ++mapIndex;
590       }
591     }
592
593     mUniformIndexMap.Resize(mapIndex);
594   }
595 }
596
597 void Renderer::WriteUniformBuffer(
598   BufferIndex                          bufferIndex,
599   Graphics::CommandBuffer&             commandBuffer,
600   Program*                             program,
601   const SceneGraph::RenderInstruction& instruction,
602   const SceneGraph::NodeDataProvider&  node,
603   const Matrix&                        modelMatrix,
604   const Matrix&                        modelViewMatrix,
605   const Matrix&                        viewMatrix,
606   const Matrix&                        projectionMatrix,
607   const Vector3&                       size)
608 {
609   // Create the UBO
610   uint32_t uboOffset{0u};
611
612   auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
613
614   uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired;
615
616   // Create uniform buffer view from uniform buffer
617   Graphics::UniquePtr<Render::UniformBufferView> uboView{nullptr};
618   if(uniformBlockAllocationBytes)
619   {
620     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex);
621
622     uboView = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
623   }
624
625   // update the uniform buffer
626   // pass shared UBO and offset, return new offset for next item to be used
627   // don't process bindings if there are no uniform buffers allocated
628   if(uboView)
629   {
630     auto uboCount = reflection.GetUniformBlockCount();
631     mUniformBufferBindings.resize(uboCount);
632
633     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
634
635     mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset);
636
637     // Write default uniforms
638     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, modelMatrix);
639     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, viewMatrix);
640     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, projectionMatrix);
641     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, modelViewMatrix);
642
643     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
644     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
645     {
646       Matrix modelViewProjectionMatrix(false);
647       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
648       WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix);
649     }
650
651     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
652     if(normalUniformInfo && !normalUniformInfo->name.empty())
653     {
654       Matrix3 normalMatrix(modelViewMatrix);
655       normalMatrix.Invert();
656       normalMatrix.Transpose();
657       WriteDefaultUniform(normalUniformInfo, *uboView, normalMatrix);
658     }
659
660     Vector4        finalColor;                               ///< Applied renderer's opacity color
661     const Vector4& color = node.GetRenderColor(bufferIndex); ///< Actor's original color
662     if(mPremultipliedAlphaEnabled)
663     {
664       const float& alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
665       finalColor         = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
666     }
667     else
668     {
669       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
670     }
671     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, finalColor);
672     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::ACTOR_COLOR), *uboView, color);
673
674     // Write uniforms from the uniform map
675     FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex);
676
677     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
678     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, size);
679
680     commandBuffer.BindUniformBuffers(*bindings);
681   }
682 }
683
684 template<class T>
685 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data)
686 {
687   if(uniformInfo && !uniformInfo->name.empty())
688   {
689     WriteUniform(ubo, *uniformInfo, data);
690     return true;
691   }
692   return false;
693 }
694
695 template<class T>
696 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data)
697 {
698   WriteUniform(ubo, uniformInfo, &data, sizeof(T));
699 }
700
701 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
702 {
703   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
704 }
705
706 void Renderer::FillUniformBuffer(Program&                                      program,
707                                  const SceneGraph::RenderInstruction&          instruction,
708                                  Render::UniformBufferView&                    ubo,
709                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
710                                  uint32_t&                                     offset,
711                                  BufferIndex                                   updateBufferIndex)
712 {
713   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
714   auto  uboCount   = reflection.GetUniformBlockCount();
715
716   // Setup bindings
717   uint32_t dataOffset = offset;
718   for(auto i = 0u; i < uboCount; ++i)
719   {
720     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
721     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
722
723     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
724     mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset);
725
726     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
727                                        end  = mUniformIndexMap.End();
728         iter != end;
729         ++iter)
730     {
731       auto& uniform    = *iter;
732       int   arrayIndex = uniform.arrayIndex;
733
734       if(!uniform.uniformFunc)
735       {
736         auto uniformInfo  = Graphics::UniformInfo{};
737         auto uniformFound = program.GetUniform(uniform.uniformName.GetCString(),
738                                                uniform.uniformNameHashNoArray ? uniform.uniformNameHashNoArray
739                                                                               : uniform.uniformNameHash,
740                                                uniformInfo);
741
742         uniform.uniformOffset   = uniformInfo.offset;
743         uniform.uniformLocation = uniformInfo.location;
744
745         if(uniformFound)
746         {
747           auto       dst      = ubo.GetOffset() + uniformInfo.offset;
748           const auto typeSize = GetPropertyValueSizeForUniform((*iter).propertyValue->GetType());
749           const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
750           const auto func     = GetPropertyValueGetter((*iter).propertyValue->GetType());
751
752           ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
753                     typeSize,
754                     dest);
755
756           uniform.uniformSize = typeSize;
757           uniform.uniformFunc = func;
758         }
759       }
760       else
761       {
762         auto       dst      = ubo.GetOffset() + uniform.uniformOffset;
763         const auto typeSize = uniform.uniformSize;
764         const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
765         const auto func     = uniform.uniformFunc;
766
767         ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
768                   typeSize,
769                   dest);
770       }
771     }
772   }
773   // write output bindings
774   outBindings = &mUniformBufferBindings;
775
776   // Update offset
777   offset = dataOffset;
778 }
779
780 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
781 {
782   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
783   sortAttributes.geometry = mGeometry;
784 }
785
786 void Renderer::SetShaderChanged(bool value)
787 {
788   mShaderChanged = value;
789 }
790
791 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
792 {
793   if(mUpdated)
794   {
795     mUpdated = false;
796     return true;
797   }
798
799   if(mShaderChanged || mGeometry->AttributesChanged())
800   {
801     return true;
802   }
803
804   auto* textures = mRenderDataProvider->GetTextures();
805   if(textures)
806   {
807     for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter)
808     {
809       auto texture = *iter;
810       if(texture && texture->IsNativeImage())
811       {
812         return true;
813       }
814     }
815   }
816
817   uint64_t                               hash           = 0xc70f6907UL;
818   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
819   for(const auto& uniformProperty : uniformMapNode)
820   {
821     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
822   }
823
824   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
825   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
826   for(const auto& uniformProperty : uniformMap)
827   {
828     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
829   }
830
831   if(mUniformsHash != hash)
832   {
833     mUniformsHash = hash;
834     return true;
835   }
836
837   return false;
838 }
839
840 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
841   Program&                                             program,
842   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
843   const SceneGraph::NodeDataProvider&                  node,
844   bool                                                 blend)
845 {
846   if(mGeometry->AttributesChanged())
847   {
848     mUpdated = true;
849   }
850
851   // Prepare query info
852   PipelineCacheQueryInfo queryInfo{};
853   queryInfo.program               = &program;
854   queryInfo.renderer              = this;
855   queryInfo.geometry              = mGeometry;
856   queryInfo.blendingEnabled       = blend;
857   queryInfo.blendingOptions       = &mBlendingOptions;
858   queryInfo.alphaPremultiplied    = mPremultipliedAlphaEnabled;
859   queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed();
860
861   auto pipelineResult = mPipelineCache->GetPipeline(queryInfo, true);
862
863   // should be never null?
864   return *pipelineResult.pipeline;
865 }
866
867 } // namespace Render
868
869 } // namespace Dali::Internal