Revert "Correctly aging renderer uniformMap"
[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/render-sampler.h>
29 #include <dali/internal/render/renderers/render-texture.h>
30 #include <dali/internal/render/renderers/render-vertex-buffer.h>
31 #include <dali/internal/render/renderers/shader-cache.h>
32 #include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
33 #include <dali/internal/render/renderers/uniform-buffer-view.h>
34 #include <dali/internal/render/shaders/program.h>
35 #include <dali/internal/render/shaders/render-shader.h>
36 #include <dali/internal/update/common/uniform-map.h>
37 #include <dali/internal/render/renderers/pipeline-cache.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:{ return sizeof(bool);}
97     case Property::Type::FLOAT:{ return sizeof(float);}
98     case Property::Type::INTEGER:{ return sizeof(int);}
99     case Property::Type::VECTOR2:{ return sizeof(Vector2);}
100     case Property::Type::VECTOR3:{ return sizeof(Vector3);}
101     case Property::Type::VECTOR4:{ return sizeof(Vector4);}
102     case Property::Type::MATRIX3:{ return sizeof(Matrix3);}
103     case Property::Type::MATRIX:{ return sizeof(Matrix);}
104     default:
105     {
106       return 0;
107     }
108   };
109 }
110
111 /**
112  * Helper function to calculate the correct alignment of data for uniform buffers
113  * @param dataSize size of uniform buffer
114  * @return aligned offset of data
115  */
116 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
117 {
118   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
119 }
120
121 } // namespace
122
123 namespace Render
124 {
125 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
126                         Render::Geometry*               geometry,
127                         uint32_t                        blendingBitmask,
128                         const Vector4&                  blendColor,
129                         FaceCullingMode::Type           faceCullingMode,
130                         bool                            preMultipliedAlphaEnabled,
131                         DepthWriteMode::Type            depthWriteMode,
132                         DepthTestMode::Type             depthTestMode,
133                         DepthFunction::Type             depthFunction,
134                         StencilParameters&              stencilParameters)
135 {
136   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
137 }
138
139 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
140                    Render::Geometry*               geometry,
141                    uint32_t                        blendingBitmask,
142                    const Vector4&                  blendColor,
143                    FaceCullingMode::Type           faceCullingMode,
144                    bool                            preMultipliedAlphaEnabled,
145                    DepthWriteMode::Type            depthWriteMode,
146                    DepthTestMode::Type             depthTestMode,
147                    DepthFunction::Type             depthFunction,
148                    StencilParameters&              stencilParameters)
149 : mGraphicsController(nullptr),
150   mRenderDataProvider(dataProvider),
151   mGeometry(geometry),
152   mProgramCache(nullptr),
153   mUniformIndexMap(),
154   mUniformsHash(),
155   mStencilParameters(stencilParameters),
156   mBlendingOptions(),
157   mIndexedDrawFirstElement(0),
158   mIndexedDrawElementsCount(0),
159   mDepthFunction(depthFunction),
160   mFaceCullingMode(faceCullingMode),
161   mDepthWriteMode(depthWriteMode),
162   mDepthTestMode(depthTestMode),
163   mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled),
164   mShaderChanged(false),
165   mUpdated(true)
166 {
167   if(blendingBitmask != 0u)
168   {
169     mBlendingOptions.SetBitmask(blendingBitmask);
170   }
171
172   mBlendingOptions.SetBlendColor(blendColor);
173 }
174
175 void Renderer::Initialize(Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache, Render::UniformBufferManager& uniformBufferManager, Render::PipelineCache& pipelineCache)
176 {
177   mGraphicsController   = &graphicsController;
178   mProgramCache         = &programCache;
179   mShaderCache          = &shaderCache;
180   mUniformBufferManager = &uniformBufferManager;
181   mPipelineCache        = &pipelineCache;
182 }
183
184 Renderer::~Renderer() = default;
185
186 void Renderer::SetGeometry(Render::Geometry* geometry)
187 {
188   mGeometry  = geometry;
189   mUpdated   = true;
190 }
191 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
192 {
193   mDrawCommands.clear();
194   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
195 }
196
197 void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
198 {
199   uint32_t textureUnit = 0;
200
201   std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
202   std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
203
204   std::vector<Graphics::TextureBinding> textureBindings;
205   for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()); ++i) // not expecting more than uint32_t of textures
206   {
207     if(textures[i] && textures[i]->GetGraphicsObject())
208     {
209       // if the sampler exists,
210       //   if it's default, delete the graphics object
211       //   otherwise re-initialize it if dirty
212
213       const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
214                                                               : nullptr);
215
216       boundTextures.PushBack(textures[i]->GetGraphicsObject());
217       const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
218       textureBindings.push_back(textureBinding);
219
220       ++textureUnit;
221     }
222   }
223
224   if(!textureBindings.empty())
225   {
226     commandBuffer.BindTextures(textureBindings);
227   }
228 }
229
230 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
231 {
232   mFaceCullingMode = mode;
233   mUpdated         = true;
234 }
235
236 void Renderer::SetBlendingBitMask(uint32_t bitmask)
237 {
238   mBlendingOptions.SetBitmask(bitmask);
239   mUpdated = true;
240 }
241
242 void Renderer::SetBlendColor(const Vector4& color)
243 {
244   mBlendingOptions.SetBlendColor(color);
245   mUpdated = true;
246 }
247
248 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
249 {
250   mIndexedDrawFirstElement = firstElement;
251   mUpdated                 = true;
252 }
253
254 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
255 {
256   mIndexedDrawElementsCount = elementsCount;
257   mUpdated                  = true;
258 }
259
260 void Renderer::EnablePreMultipliedAlpha(bool enable)
261 {
262   mPremultipliedAlphaEnabled = enable;
263   mUpdated                   = true;
264 }
265
266 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
267 {
268   mDepthWriteMode = depthWriteMode;
269   mUpdated        = true;
270 }
271
272 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
273 {
274   mDepthTestMode = depthTestMode;
275   mUpdated       = true;
276 }
277
278 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
279 {
280   return mDepthWriteMode;
281 }
282
283 DepthTestMode::Type Renderer::GetDepthTestMode() const
284 {
285   return mDepthTestMode;
286 }
287
288 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
289 {
290   mDepthFunction = depthFunction;
291   mUpdated       = true;
292 }
293
294 DepthFunction::Type Renderer::GetDepthFunction() const
295 {
296   return mDepthFunction;
297 }
298
299 void Renderer::SetRenderMode(RenderMode::Type renderMode)
300 {
301   mStencilParameters.renderMode = renderMode;
302   mUpdated                      = true;
303 }
304
305 RenderMode::Type Renderer::GetRenderMode() const
306 {
307   return mStencilParameters.renderMode;
308 }
309
310 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
311 {
312   mStencilParameters.stencilFunction = stencilFunction;
313   mUpdated                           = true;
314 }
315
316 StencilFunction::Type Renderer::GetStencilFunction() const
317 {
318   return mStencilParameters.stencilFunction;
319 }
320
321 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
322 {
323   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
324   mUpdated                               = true;
325 }
326
327 int Renderer::GetStencilFunctionMask() const
328 {
329   return mStencilParameters.stencilFunctionMask;
330 }
331
332 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
333 {
334   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
335   mUpdated                                    = true;
336 }
337
338 int Renderer::GetStencilFunctionReference() const
339 {
340   return mStencilParameters.stencilFunctionReference;
341 }
342
343 void Renderer::SetStencilMask(int stencilMask)
344 {
345   mStencilParameters.stencilMask = stencilMask;
346   mUpdated                       = true;
347 }
348
349 int Renderer::GetStencilMask() const
350 {
351   return mStencilParameters.stencilMask;
352 }
353
354 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
355 {
356   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
357   mUpdated                                  = true;
358 }
359
360 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
361 {
362   return mStencilParameters.stencilOperationOnFail;
363 }
364
365 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
366 {
367   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
368   mUpdated                                   = true;
369 }
370
371 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
372 {
373   return mStencilParameters.stencilOperationOnZFail;
374 }
375
376 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
377 {
378   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
379   mUpdated                                   = true;
380 }
381
382 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
383 {
384   return mStencilParameters.stencilOperationOnZPass;
385 }
386
387 void Renderer::Upload()
388 {
389   mGeometry->Upload(*mGraphicsController);
390 }
391
392 bool Renderer::Render(Graphics::CommandBuffer&                             commandBuffer,
393                       BufferIndex                                          bufferIndex,
394                       const SceneGraph::NodeDataProvider&                  node,
395                       const Matrix&                                        modelMatrix,
396                       const Matrix&                                        modelViewMatrix,
397                       const Matrix&                                        viewMatrix,
398                       const Matrix&                                        projectionMatrix,
399                       const Vector3&                                       size,
400                       bool                                                 blend,
401                       Vector<Graphics::Texture*>&                          boundTextures,
402                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
403                       uint32_t                                             queueIndex)
404 {
405   // Before doing anything test if the call happens in the right queue
406   if(mDrawCommands.empty() && queueIndex > 0)
407   {
408     return false;
409   }
410
411   // Prepare commands
412   std::vector<DevelRenderer::DrawCommand*> commands;
413   for(auto& cmd : mDrawCommands)
414   {
415     if(cmd.queue == queueIndex)
416     {
417       commands.emplace_back(&cmd);
418     }
419   }
420
421   // Have commands but nothing to be drawn - abort
422   if(!mDrawCommands.empty() && commands.empty())
423   {
424     return false;
425   }
426
427   // Set blending mode
428   if(!mDrawCommands.empty())
429   {
430     blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend;
431   }
432
433   // Create Program
434   ShaderDataPtr            shaderData   = mRenderDataProvider->GetShader().GetShaderData();
435
436   Program* program         = Program::New(*mProgramCache,
437                                   shaderData,
438                                   *mGraphicsController);
439   if(!program)
440   {
441     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
442     return false;
443   }
444
445   // If program doesn't have Gfx program object assigned yet, prepare it.
446   if(!program->GetGraphicsProgramPtr())
447   {
448     const std::vector<char> &vertShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
449     const std::vector<char> &fragShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
450     Dali::Graphics::Shader  &vertexShader = mShaderCache->GetShader(
451       vertShader,
452       Graphics::PipelineStage::VERTEX_SHADER,
453       shaderData->GetSourceMode());
454
455     Dali::Graphics::Shader &fragmentShader = mShaderCache->GetShader(
456       fragShader,
457       Graphics::PipelineStage::FRAGMENT_SHADER,
458       shaderData->GetSourceMode());
459
460     std::vector<Graphics::ShaderState> shaderStates{
461       Graphics::ShaderState()
462         .SetShader(vertexShader)
463         .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
464       Graphics::ShaderState()
465         .SetShader(fragmentShader)
466         .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
467
468     auto createInfo = Graphics::ProgramCreateInfo();
469     createInfo.SetShaderState(shaderStates);
470     auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
471     program->SetGraphicsProgram(std::move(graphicsProgram));
472   }
473
474   // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
475   auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
476
477   commandBuffer.BindPipeline(pipeline);
478
479   BindTextures(commandBuffer, boundTextures);
480
481   BuildUniformIndexMap(bufferIndex, node, size, *program);
482
483   WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size);
484
485   bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
486                       // @todo We should detect this case much earlier to prevent unnecessary work
487
488   if(mDrawCommands.empty())
489   {
490     drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
491   }
492   else
493   {
494     for(auto& cmd : commands)
495     {
496       mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
497     }
498   }
499
500   mUpdated = false;
501   return drawn;
502 }
503
504 void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
505 {
506   // Check if the map has changed
507   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
508
509   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
510
511   if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
512      node.GetUniformMapChanged(bufferIndex) ||
513      mUniformIndexMap.Count() == 0 ||
514      mShaderChanged)
515   {
516     // Reset shader pointer
517     mShaderChanged = false;
518
519     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
520     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
521
522     auto maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
523     mUniformIndexMap.Clear();                                                          // Clear contents, but keep memory if we don't change size
524     mUniformIndexMap.Resize(maxMaps);
525
526     // Copy uniform map into mUniformIndexMap
527     uint32_t mapIndex = 0;
528     for(; mapIndex < uniformMap.Count(); ++mapIndex)
529     {
530       mUniformIndexMap[mapIndex].propertyValue          = uniformMap[mapIndex].propertyPtr;
531       mUniformIndexMap[mapIndex].uniformName            = uniformMap[mapIndex].uniformName;
532       mUniformIndexMap[mapIndex].uniformNameHash        = uniformMap[mapIndex].uniformNameHash;
533       mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMap[mapIndex].uniformNameHashNoArray;
534       mUniformIndexMap[mapIndex].arrayIndex             = uniformMap[mapIndex].arrayIndex;
535     }
536
537     for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
538     {
539       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
540       auto& name = uniformMapNode[nodeMapIndex].uniformName;
541       bool  found(false);
542       for(uint32_t i = 0; i < uniformMap.Count(); ++i)
543       {
544         if(mUniformIndexMap[i].uniformNameHash == hash &&
545            mUniformIndexMap[i].uniformName == name)
546         {
547           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
548           found                             = true;
549           break;
550         }
551       }
552
553       if(!found)
554       {
555         mUniformIndexMap[mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
556         mUniformIndexMap[mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
557         mUniformIndexMap[mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
558         mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
559         mUniformIndexMap[mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
560         ++mapIndex;
561       }
562     }
563
564     mUniformIndexMap.Resize(mapIndex);
565   }
566 }
567
568 void Renderer::WriteUniformBuffer(
569   BufferIndex                          bufferIndex,
570   Graphics::CommandBuffer&             commandBuffer,
571   Program*                             program,
572   const SceneGraph::RenderInstruction& instruction,
573   const SceneGraph::NodeDataProvider&  node,
574   const Matrix&                        modelMatrix,
575   const Matrix&                        modelViewMatrix,
576   const Matrix&                        viewMatrix,
577   const Matrix&                        projectionMatrix,
578   const Vector3&                       size)
579 {
580   // Create the UBO
581   uint32_t uboOffset{0u};
582
583   auto &reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
584
585   uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired;
586
587   // Create uniform buffer view from uniform buffer
588   Graphics::UniquePtr<Render::UniformBufferView> uboView{nullptr};
589   if(uniformBlockAllocationBytes)
590   {
591     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex);
592
593     uboView = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
594   }
595
596   // update the uniform buffer
597   // pass shared UBO and offset, return new offset for next item to be used
598   // don't process bindings if there are no uniform buffers allocated
599   if(uboView)
600   {
601     auto uboCount = reflection.GetUniformBlockCount();
602     mUniformBufferBindings.resize(uboCount);
603
604     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
605
606     mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset);
607
608     // Write default uniforms
609     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, modelMatrix);
610     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, viewMatrix);
611     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, projectionMatrix);
612     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, modelViewMatrix);
613
614     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
615     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
616     {
617       Matrix modelViewProjectionMatrix(false);
618       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
619       WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix);
620     }
621
622     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
623     if(normalUniformInfo && !normalUniformInfo->name.empty())
624     {
625       Matrix3 normalMatrix(modelViewMatrix);
626       normalMatrix.Invert();
627       normalMatrix.Transpose();
628       WriteDefaultUniform(normalUniformInfo, *uboView, normalMatrix);
629     }
630
631     Vector4        finalColor;
632     const Vector4& color = node.GetRenderColor(bufferIndex);
633     if(mPremultipliedAlphaEnabled)
634     {
635       float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
636       finalColor  = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
637     }
638     else
639     {
640       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
641     }
642     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, finalColor);
643
644     // Write uniforms from the uniform map
645     FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex);
646
647     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
648     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, size);
649
650     commandBuffer.BindUniformBuffers(*bindings);
651   }
652 }
653
654 template<class T>
655 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data)
656 {
657   if(uniformInfo && !uniformInfo->name.empty())
658   {
659     WriteUniform(ubo, *uniformInfo, data);
660     return true;
661   }
662   return false;
663 }
664
665 template<class T>
666 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data)
667 {
668   WriteUniform(ubo, uniformInfo, &data, sizeof(T));
669 }
670
671 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
672 {
673   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
674 }
675
676 void Renderer::FillUniformBuffer(Program&                                      program,
677                                  const SceneGraph::RenderInstruction&          instruction,
678                                  Render::UniformBufferView&                    ubo,
679                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
680                                  uint32_t&                                     offset,
681                                  BufferIndex                                   updateBufferIndex)
682 {
683   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
684   auto  uboCount   = reflection.GetUniformBlockCount();
685
686   // Setup bindings
687   uint32_t dataOffset = offset;
688   for(auto i = 0u; i < uboCount; ++i)
689   {
690     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
691     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
692
693     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
694     mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset);
695
696     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
697                                        end  = mUniformIndexMap.End();
698         iter != end;
699         ++iter)
700     {
701       // @todo This means parsing the uniform string every frame. Instead, store the array index if present.
702       int arrayIndex = (*iter).arrayIndex;
703
704       auto uniformInfo  = Graphics::UniformInfo{};
705       auto uniformFound = program.GetUniform((*iter).uniformName.GetCString(),
706                                              (*iter).uniformNameHashNoArray ? (*iter).uniformNameHashNoArray
707                                                                             : (*iter).uniformNameHash,
708                                              uniformInfo);
709
710       if(uniformFound)
711       {
712         auto dst = ubo.GetOffset() + uniformInfo.offset;
713         const auto typeSize = GetPropertyValueSizeForUniform( (*iter).propertyValue->GetType() );
714         const auto dest = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
715         const auto func = GetPropertyValueGetter((*iter).propertyValue->GetType());
716         ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
717                   typeSize,
718                   dest);
719       }
720     }
721   }
722   // write output bindings
723   outBindings = &mUniformBufferBindings;
724
725   // Update offset
726   offset = dataOffset;
727 }
728
729 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
730 {
731   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
732   sortAttributes.geometry = mGeometry;
733 }
734
735 void Renderer::SetShaderChanged(bool value)
736 {
737   mShaderChanged = value;
738 }
739
740 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
741 {
742   if(mUpdated)
743   {
744     mUpdated = false;
745     return true;
746   }
747
748   if(mShaderChanged || mGeometry->AttributesChanged())
749   {
750     return true;
751   }
752
753   for(const auto& texture : mRenderDataProvider->GetTextures())
754   {
755     if(texture && texture->IsNativeImage())
756     {
757       return true;
758     }
759   }
760
761   uint64_t                               hash           = 0xc70f6907UL;
762   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
763   for(const auto& uniformProperty : uniformMapNode)
764   {
765     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
766   }
767
768   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
769   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
770   for(const auto& uniformProperty : uniformMap)
771   {
772     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
773   }
774
775   if(mUniformsHash != hash)
776   {
777     mUniformsHash = hash;
778     return true;
779   }
780
781   return false;
782 }
783
784 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
785   Program&                                             program,
786   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
787   const SceneGraph::NodeDataProvider&                  node,
788   bool                                                 blend)
789 {
790   if(mGeometry->AttributesChanged())
791   {
792     mUpdated = true;
793   }
794
795   // Prepare query info
796   PipelineCacheQueryInfo queryInfo{};
797   queryInfo.program = &program;
798   queryInfo.renderer = this;
799   queryInfo.geometry = mGeometry;
800   queryInfo.blendingEnabled = blend;
801   queryInfo.blendingOptions = &mBlendingOptions;
802   queryInfo.alphaPremultiplied = mPremultipliedAlphaEnabled;
803   queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed();
804
805   auto pipelineResult = mPipelineCache->GetPipeline( queryInfo, true );
806
807   // should be never null?
808   return *pipelineResult.pipeline;
809 }
810
811 } // namespace Render
812
813 } // namespace Dali::Internal