Uniform data cached locally in the uniform map
[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   // @todo Temporary workaround to reduce workload each frame. Find a better way.
568   auto& sceneGraphRenderer = const_cast<SceneGraph::Renderer&>(static_cast<const SceneGraph::Renderer&>(uniformMapDataProvider));
569   sceneGraphRenderer.AgeUniformMap();
570 }
571
572 void Renderer::WriteUniformBuffer(
573   BufferIndex                          bufferIndex,
574   Graphics::CommandBuffer&             commandBuffer,
575   Program*                             program,
576   const SceneGraph::RenderInstruction& instruction,
577   const SceneGraph::NodeDataProvider&  node,
578   const Matrix&                        modelMatrix,
579   const Matrix&                        modelViewMatrix,
580   const Matrix&                        viewMatrix,
581   const Matrix&                        projectionMatrix,
582   const Vector3&                       size)
583 {
584   // Create the UBO
585   uint32_t uboOffset{0u};
586
587   auto &reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
588
589   uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired;
590
591   // Create uniform buffer view from uniform buffer
592   Graphics::UniquePtr<Render::UniformBufferView> uboView{nullptr};
593   if(uniformBlockAllocationBytes)
594   {
595     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex);
596
597     uboView = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
598   }
599
600   // update the uniform buffer
601   // pass shared UBO and offset, return new offset for next item to be used
602   // don't process bindings if there are no uniform buffers allocated
603   if(uboView)
604   {
605     auto uboCount = reflection.GetUniformBlockCount();
606     mUniformBufferBindings.resize(uboCount);
607
608     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
609
610     mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset);
611
612     // Write default uniforms
613     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, modelMatrix);
614     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, viewMatrix);
615     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, projectionMatrix);
616     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, modelViewMatrix);
617
618     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
619     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
620     {
621       Matrix modelViewProjectionMatrix(false);
622       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
623       WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix);
624     }
625
626     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
627     if(normalUniformInfo && !normalUniformInfo->name.empty())
628     {
629       Matrix3 normalMatrix(modelViewMatrix);
630       normalMatrix.Invert();
631       normalMatrix.Transpose();
632       WriteDefaultUniform(normalUniformInfo, *uboView, normalMatrix);
633     }
634
635     Vector4        finalColor;
636     const Vector4& color = node.GetRenderColor(bufferIndex);
637     if(mPremultipliedAlphaEnabled)
638     {
639       float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
640       finalColor  = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
641     }
642     else
643     {
644       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
645     }
646     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, finalColor);
647
648     // Write uniforms from the uniform map
649     FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex);
650
651     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
652     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, size);
653
654     commandBuffer.BindUniformBuffers(*bindings);
655   }
656 }
657
658 template<class T>
659 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data)
660 {
661   if(uniformInfo && !uniformInfo->name.empty())
662   {
663     WriteUniform(ubo, *uniformInfo, data);
664     return true;
665   }
666   return false;
667 }
668
669 template<class T>
670 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data)
671 {
672   WriteUniform(ubo, uniformInfo, &data, sizeof(T));
673 }
674
675 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
676 {
677   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
678 }
679
680 void Renderer::FillUniformBuffer(Program&                                      program,
681                                  const SceneGraph::RenderInstruction&          instruction,
682                                  Render::UniformBufferView&                    ubo,
683                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
684                                  uint32_t&                                     offset,
685                                  BufferIndex                                   updateBufferIndex)
686 {
687   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
688   auto  uboCount   = reflection.GetUniformBlockCount();
689
690   // Setup bindings
691   uint32_t dataOffset = offset;
692   for(auto i = 0u; i < uboCount; ++i)
693   {
694     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
695     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
696
697     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
698     mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset);
699
700     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
701                                        end  = mUniformIndexMap.End();
702         iter != end;
703         ++iter)
704     {
705       auto& uniform = *iter;
706       int arrayIndex = uniform.arrayIndex;
707
708       if(!uniform.uniformFunc)
709       {
710         auto uniformInfo  = Graphics::UniformInfo{};
711         auto uniformFound = program.GetUniform(uniform.uniformName.GetCString(),
712                                                uniform.uniformNameHashNoArray ? uniform.uniformNameHashNoArray
713                                                                               : uniform.uniformNameHash,
714                                                uniformInfo);
715
716         uniform.uniformOffset   = uniformInfo.offset;
717         uniform.uniformLocation = uniformInfo.location;
718
719         if (uniformFound)
720         {
721           auto       dst      = ubo.GetOffset() + uniformInfo.offset;
722           const auto typeSize = GetPropertyValueSizeForUniform((*iter).propertyValue->GetType());
723           const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
724           const auto func     = GetPropertyValueGetter((*iter).propertyValue->GetType());
725
726           ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
727                     typeSize,
728                     dest);
729
730           uniform.uniformSize = typeSize;
731           uniform.uniformFunc = func;
732         }
733       }
734       else
735       {
736         auto       dst      = ubo.GetOffset() + uniform.uniformOffset;
737         const auto typeSize = uniform.uniformSize;
738         const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
739         const auto func     = uniform.uniformFunc;
740
741
742         ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
743                   typeSize,
744                   dest);
745       }
746     }
747   }
748   // write output bindings
749   outBindings = &mUniformBufferBindings;
750
751   // Update offset
752   offset = dataOffset;
753 }
754
755 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
756 {
757   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
758   sortAttributes.geometry = mGeometry;
759 }
760
761 void Renderer::SetShaderChanged(bool value)
762 {
763   mShaderChanged = value;
764 }
765
766 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
767 {
768   if(mUpdated)
769   {
770     mUpdated = false;
771     return true;
772   }
773
774   if(mShaderChanged || mGeometry->AttributesChanged())
775   {
776     return true;
777   }
778
779   for(const auto& texture : mRenderDataProvider->GetTextures())
780   {
781     if(texture && texture->IsNativeImage())
782     {
783       return true;
784     }
785   }
786
787   uint64_t                               hash           = 0xc70f6907UL;
788   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
789   for(const auto& uniformProperty : uniformMapNode)
790   {
791     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
792   }
793
794   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
795   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
796   for(const auto& uniformProperty : uniformMap)
797   {
798     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
799   }
800
801   if(mUniformsHash != hash)
802   {
803     mUniformsHash = hash;
804     return true;
805   }
806
807   return false;
808 }
809
810 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
811   Program&                                             program,
812   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
813   const SceneGraph::NodeDataProvider&                  node,
814   bool                                                 blend)
815 {
816   if(mGeometry->AttributesChanged())
817   {
818     mUpdated = true;
819   }
820
821   // Prepare query info
822   PipelineCacheQueryInfo queryInfo{};
823   queryInfo.program = &program;
824   queryInfo.renderer = this;
825   queryInfo.geometry = mGeometry;
826   queryInfo.blendingEnabled = blend;
827   queryInfo.blendingOptions = &mBlendingOptions;
828   queryInfo.alphaPremultiplied = mPremultipliedAlphaEnabled;
829   queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed();
830
831   auto pipelineResult = mPipelineCache->GetPipeline( queryInfo, true );
832
833   // should be never null?
834   return *pipelineResult.pipeline;
835 }
836
837 } // namespace Render
838
839 } // namespace Dali::Internal