Migrated Render::Texture to use memory pool
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/renderers/render-renderer.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/graphics-api/graphics-types.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/internal/common/image-sampler.h>
25 #include <dali/internal/common/matrix-utils.h>
26 #include <dali/internal/event/rendering/texture-impl.h>
27 #include <dali/internal/render/common/render-instruction.h>
28 #include <dali/internal/render/data-providers/node-data-provider.h>
29 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
30 #include <dali/internal/render/renderers/pipeline-cache.h>
31 #include <dali/internal/render/renderers/render-sampler.h>
32 #include <dali/internal/render/renderers/render-texture.h>
33 #include <dali/internal/render/renderers/render-vertex-buffer.h>
34 #include <dali/internal/render/renderers/shader-cache.h>
35 #include <dali/internal/render/renderers/uniform-buffer-view-pool.h>
36 #include <dali/internal/render/renderers/uniform-buffer-view.h>
37 #include <dali/internal/render/shaders/program.h>
38 #include <dali/internal/render/shaders/render-shader.h>
39 #include <dali/internal/update/common/uniform-map.h>
40 #include <dali/public-api/signals/render-callback.h>
41
42 namespace Dali::Internal
43 {
44 namespace
45 {
46 // Helper to get the property value getter by type
47 typedef const float& (PropertyInputImpl::*FuncGetter)(BufferIndex) const;
48 constexpr FuncGetter GetPropertyValueGetter(Property::Type type)
49 {
50   switch(type)
51   {
52     case Property::BOOLEAN:
53     {
54       return FuncGetter(&PropertyInputImpl::GetBoolean);
55     }
56     case Property::INTEGER:
57     {
58       return FuncGetter(&PropertyInputImpl::GetInteger);
59     }
60     case Property::FLOAT:
61     {
62       return FuncGetter(&PropertyInputImpl::GetFloat);
63     }
64     case Property::VECTOR2:
65     {
66       return FuncGetter(&PropertyInputImpl::GetVector2);
67     }
68     case Property::VECTOR3:
69     {
70       return FuncGetter(&PropertyInputImpl::GetVector3);
71     }
72     case Property::VECTOR4:
73     {
74       return FuncGetter(&PropertyInputImpl::GetVector4);
75     }
76     case Property::MATRIX3:
77     {
78       return FuncGetter(&PropertyInputImpl::GetMatrix3);
79     }
80     case Property::MATRIX:
81     {
82       return FuncGetter(&PropertyInputImpl::GetMatrix);
83     }
84     default:
85     {
86       return nullptr;
87     }
88   }
89 }
90
91 /**
92  * Helper function that returns size of uniform datatypes based
93  * on property type.
94  */
95 constexpr int GetPropertyValueSizeForUniform(Property::Type type)
96 {
97   switch(type)
98   {
99     case Property::Type::BOOLEAN:
100     {
101       return sizeof(bool);
102     }
103     case Property::Type::FLOAT:
104     {
105       return sizeof(float);
106     }
107     case Property::Type::INTEGER:
108     {
109       return sizeof(int);
110     }
111     case Property::Type::VECTOR2:
112     {
113       return sizeof(Vector2);
114     }
115     case Property::Type::VECTOR3:
116     {
117       return sizeof(Vector3);
118     }
119     case Property::Type::VECTOR4:
120     {
121       return sizeof(Vector4);
122     }
123     case Property::Type::MATRIX3:
124     {
125       return sizeof(Matrix3);
126     }
127     case Property::Type::MATRIX:
128     {
129       return sizeof(Matrix);
130     }
131     default:
132     {
133       return 0;
134     }
135   };
136 }
137
138 /**
139  * Helper function to calculate the correct alignment of data for uniform buffers
140  * @param dataSize size of uniform buffer
141  * @return aligned offset of data
142  */
143 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
144 {
145   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
146 }
147
148 } // namespace
149
150 namespace Render
151 {
152 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
153                         Render::Geometry*               geometry,
154                         uint32_t                        blendingBitmask,
155                         const Vector4&                  blendColor,
156                         FaceCullingMode::Type           faceCullingMode,
157                         bool                            preMultipliedAlphaEnabled,
158                         DepthWriteMode::Type            depthWriteMode,
159                         DepthTestMode::Type             depthTestMode,
160                         DepthFunction::Type             depthFunction,
161                         StencilParameters&              stencilParameters)
162 {
163   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
164 }
165
166 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
167                    Render::Geometry*               geometry,
168                    uint32_t                        blendingBitmask,
169                    const Vector4&                  blendColor,
170                    FaceCullingMode::Type           faceCullingMode,
171                    bool                            preMultipliedAlphaEnabled,
172                    DepthWriteMode::Type            depthWriteMode,
173                    DepthTestMode::Type             depthTestMode,
174                    DepthFunction::Type             depthFunction,
175                    StencilParameters&              stencilParameters)
176 : mGraphicsController(nullptr),
177   mRenderDataProvider(dataProvider),
178   mGeometry(geometry),
179   mProgramCache(nullptr),
180   mStencilParameters(stencilParameters),
181   mBlendingOptions(),
182   mIndexedDrawFirstElement(0),
183   mIndexedDrawElementsCount(0),
184   mDepthFunction(depthFunction),
185   mFaceCullingMode(faceCullingMode),
186   mDepthWriteMode(depthWriteMode),
187   mDepthTestMode(depthTestMode),
188   mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled),
189   mShaderChanged(false)
190 {
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 }
214 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
215 {
216   mDrawCommands.clear();
217   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
218 }
219
220 void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
221 {
222   uint32_t textureUnit = 0;
223
224   auto textures(mRenderDataProvider->GetTextures());
225   auto samplers(mRenderDataProvider->GetSamplers());
226
227   std::vector<Graphics::TextureBinding> textureBindings;
228
229   if(textures != nullptr)
230   {
231     const std::uint32_t texturesCount(static_cast<std::uint32_t>(textures->Count()));
232     textureBindings.reserve(texturesCount);
233
234     for(uint32_t i = 0; i < texturesCount; ++i) // not expecting more than uint32_t of textures
235     {
236       if((*textures)[i] && (*textures)[i]->GetGraphicsObject())
237       {
238         Graphics::Texture* graphicsTexture = (*textures)[i]->GetGraphicsObject();
239         // if the sampler exists,
240         //   if it's default, delete the graphics object
241         //   otherwise re-initialize it if dirty
242
243         const Graphics::Sampler* graphicsSampler = samplers ? ((*samplers)[i] ? (*samplers)[i]->GetGraphicsObject()
244                                                                               : nullptr)
245                                                             : nullptr;
246
247         boundTextures.PushBack(graphicsTexture);
248         const Graphics::TextureBinding textureBinding{graphicsTexture, graphicsSampler, textureUnit};
249         textureBindings.push_back(textureBinding);
250
251         ++textureUnit;
252       }
253     }
254   }
255
256   if(!textureBindings.empty())
257   {
258     commandBuffer.BindTextures(textureBindings);
259   }
260 }
261
262 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
263 {
264   mFaceCullingMode = mode;
265 }
266
267 void Renderer::SetBlendingBitMask(uint32_t bitmask)
268 {
269   mBlendingOptions.SetBitmask(bitmask);
270 }
271
272 void Renderer::SetBlendColor(const Vector4& color)
273 {
274   mBlendingOptions.SetBlendColor(color);
275 }
276
277 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
278 {
279   mIndexedDrawFirstElement = firstElement;
280 }
281
282 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
283 {
284   mIndexedDrawElementsCount = elementsCount;
285 }
286
287 void Renderer::EnablePreMultipliedAlpha(bool enable)
288 {
289   mPremultipliedAlphaEnabled = enable;
290 }
291
292 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
293 {
294   mDepthWriteMode = depthWriteMode;
295 }
296
297 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
298 {
299   mDepthTestMode = depthTestMode;
300 }
301
302 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
303 {
304   return mDepthWriteMode;
305 }
306
307 DepthTestMode::Type Renderer::GetDepthTestMode() const
308 {
309   return mDepthTestMode;
310 }
311
312 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
313 {
314   mDepthFunction = depthFunction;
315 }
316
317 DepthFunction::Type Renderer::GetDepthFunction() const
318 {
319   return mDepthFunction;
320 }
321
322 void Renderer::SetRenderMode(RenderMode::Type renderMode)
323 {
324   mStencilParameters.renderMode = renderMode;
325 }
326
327 RenderMode::Type Renderer::GetRenderMode() const
328 {
329   return mStencilParameters.renderMode;
330 }
331
332 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
333 {
334   mStencilParameters.stencilFunction = stencilFunction;
335 }
336
337 StencilFunction::Type Renderer::GetStencilFunction() const
338 {
339   return mStencilParameters.stencilFunction;
340 }
341
342 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
343 {
344   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
345 }
346
347 int Renderer::GetStencilFunctionMask() const
348 {
349   return mStencilParameters.stencilFunctionMask;
350 }
351
352 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
353 {
354   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
355 }
356
357 int Renderer::GetStencilFunctionReference() const
358 {
359   return mStencilParameters.stencilFunctionReference;
360 }
361
362 void Renderer::SetStencilMask(int stencilMask)
363 {
364   mStencilParameters.stencilMask = stencilMask;
365 }
366
367 int Renderer::GetStencilMask() const
368 {
369   return mStencilParameters.stencilMask;
370 }
371
372 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
373 {
374   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
375 }
376
377 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
378 {
379   return mStencilParameters.stencilOperationOnFail;
380 }
381
382 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
383 {
384   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
385 }
386
387 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
388 {
389   return mStencilParameters.stencilOperationOnZFail;
390 }
391
392 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
393 {
394   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
395 }
396
397 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
398 {
399   return mStencilParameters.stencilOperationOnZPass;
400 }
401
402 void Renderer::Upload()
403 {
404   mGeometry->Upload(*mGraphicsController);
405 }
406
407 bool Renderer::Render(Graphics::CommandBuffer&                             commandBuffer,
408                       BufferIndex                                          bufferIndex,
409                       const SceneGraph::NodeDataProvider&                  node,
410                       const Matrix&                                        modelMatrix,
411                       const Matrix&                                        modelViewMatrix,
412                       const Matrix&                                        viewMatrix,
413                       const Matrix&                                        projectionMatrix,
414                       const Vector3&                                       size,
415                       bool                                                 blend,
416                       Vector<Graphics::Texture*>&                          boundTextures,
417                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
418                       uint32_t                                             queueIndex)
419 {
420   // Before doing anything test if the call happens in the right queue
421   if(mDrawCommands.empty() && queueIndex > 0)
422   {
423     return false;
424   }
425
426   // Check if there is render callback
427   if(mRenderCallback)
428   {
429     if(!mRenderCallbackInput)
430     {
431       mRenderCallbackInput = std::unique_ptr<RenderCallbackInput>(new RenderCallbackInput);
432     }
433
434     Graphics::DrawNativeInfo info{};
435     info.api      = Graphics::DrawNativeAPI::GLES;
436     info.callback = &static_cast<Dali::CallbackBase&>(*mRenderCallback);
437     info.userData = mRenderCallbackInput.get();
438
439     // Set storage for the context to be used
440     info.glesNativeInfo.eglSharedContextStoragePointer = &mRenderCallbackInput->eglContext;
441     info.reserved                                      = nullptr;
442
443     auto& textureResources = mRenderCallback->GetTextureResources();
444
445     if(!textureResources.empty())
446     {
447       mRenderCallbackTextureBindings.clear();
448       mRenderCallbackInput->textureBindings.resize(textureResources.size());
449       auto i = 0u;
450       for(auto& texture : textureResources)
451       {
452         auto& textureImpl     = GetImplementation(texture);
453         auto  graphicsTexture = textureImpl.GetRenderTextureKey()->GetGraphicsObject();
454
455         auto properties = mGraphicsController->GetTextureProperties(*graphicsTexture);
456
457         mRenderCallbackTextureBindings.emplace_back(graphicsTexture);
458         mRenderCallbackInput->textureBindings[i++] = properties.nativeHandle;
459       }
460       info.textureCount = mRenderCallbackTextureBindings.size();
461       info.textureList  = mRenderCallbackTextureBindings.data();
462     }
463
464     // pass render callback input
465     mRenderCallbackInput->size       = size;
466     mRenderCallbackInput->projection = projectionMatrix;
467
468     MatrixUtils::Multiply(mRenderCallbackInput->mvp, modelViewMatrix, projectionMatrix);
469
470     // submit draw
471     commandBuffer.DrawNative(&info);
472     return true;
473   }
474
475   // Prepare commands
476   std::vector<DevelRenderer::DrawCommand*> commands;
477   for(auto& cmd : mDrawCommands)
478   {
479     if(cmd.queue == queueIndex)
480     {
481       commands.emplace_back(&cmd);
482     }
483   }
484
485   // Have commands but nothing to be drawn - abort
486   if(!mDrawCommands.empty() && commands.empty())
487   {
488     return false;
489   }
490
491   // Set blending mode
492   if(!mDrawCommands.empty())
493   {
494     blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend;
495   }
496
497   // Create Program
498   ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
499
500   Program* program = Program::New(*mProgramCache,
501                                   shaderData,
502                                   *mGraphicsController);
503   if(!program)
504   {
505     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<const void*>(&mRenderDataProvider->GetShader()));
506     return false;
507   }
508
509   // If program doesn't have Gfx program object assigned yet, prepare it.
510   if(!program->GetGraphicsProgramPtr())
511   {
512     const std::vector<char>& vertShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
513     const std::vector<char>& fragShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
514     Dali::Graphics::Shader&  vertexShader = mShaderCache->GetShader(
515       vertShader,
516       Graphics::PipelineStage::VERTEX_SHADER,
517       shaderData->GetSourceMode());
518
519     Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
520       fragShader,
521       Graphics::PipelineStage::FRAGMENT_SHADER,
522       shaderData->GetSourceMode());
523
524     std::vector<Graphics::ShaderState> shaderStates{
525       Graphics::ShaderState()
526         .SetShader(vertexShader)
527         .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
528       Graphics::ShaderState()
529         .SetShader(fragmentShader)
530         .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
531
532     auto createInfo = Graphics::ProgramCreateInfo();
533     createInfo.SetShaderState(shaderStates);
534     auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
535     program->SetGraphicsProgram(std::move(graphicsProgram));
536   }
537
538   // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
539   auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
540
541   commandBuffer.BindPipeline(pipeline);
542
543   BindTextures(commandBuffer, boundTextures);
544
545   std::size_t nodeIndex = BuildUniformIndexMap(bufferIndex, node, size, *program);
546
547   WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size, nodeIndex);
548
549   bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
550                       // @todo We should detect this case much earlier to prevent unnecessary work
551
552   if(mDrawCommands.empty())
553   {
554     drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
555   }
556   else
557   {
558     for(auto& cmd : commands)
559     {
560       mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
561     }
562   }
563
564   return drawn;
565 }
566
567 std::size_t Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
568 {
569   // Check if the map has changed
570   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
571
572   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
573   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetCollectedUniformMap();
574   const SceneGraph::UniformMap&             uniformMapNode         = node.GetNodeUniformMap();
575
576   bool updateMaps;
577
578   // Usual case is to only have 1 node, however we do allow multiple nodes to reuse the same
579   // renderer, so we have to cache uniform map per render item (node / renderer pair).
580
581   // Specially, if node don't have uniformMap, we mark nodePtr as nullptr.
582   // So, all nodes without uniformMap will share same UniformIndexMap, contains only render data providers.
583   const auto nodePtr = uniformMapNode.Count() ? &node : nullptr;
584
585   const auto nodeChangeCounter          = nodePtr ? uniformMapNode.GetChangeCounter() : 0;
586   const auto renderItemMapChangeCounter = uniformMap.GetChangeCounter();
587
588   auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [nodePtr](RenderItemLookup& element) { return element.node == nodePtr; });
589
590   std::size_t renderItemMapIndex;
591   if(iter == mNodeIndexMap.end())
592   {
593     renderItemMapIndex = mUniformIndexMaps.size();
594     RenderItemLookup renderItemLookup;
595     renderItemLookup.node                       = nodePtr;
596     renderItemLookup.index                      = renderItemMapIndex;
597     renderItemLookup.nodeChangeCounter          = nodeChangeCounter;
598     renderItemLookup.renderItemMapChangeCounter = renderItemMapChangeCounter;
599     mNodeIndexMap.emplace_back(renderItemLookup);
600
601     updateMaps = true;
602     mUniformIndexMaps.resize(mUniformIndexMaps.size() + 1);
603   }
604   else
605   {
606     renderItemMapIndex = iter->index;
607
608     updateMaps = (nodeChangeCounter != iter->nodeChangeCounter) ||
609                  (renderItemMapChangeCounter != iter->renderItemMapChangeCounter) ||
610                  (mUniformIndexMaps[renderItemMapIndex].size() == 0);
611
612     iter->nodeChangeCounter          = nodeChangeCounter;
613     iter->renderItemMapChangeCounter = renderItemMapChangeCounter;
614   }
615
616   if(updateMaps || mShaderChanged)
617   {
618     // Reset shader pointer
619     mShaderChanged = false;
620
621     const uint32_t mapCount     = uniformMap.Count();
622     const uint32_t mapNodeCount = uniformMapNode.Count();
623
624     mUniformIndexMaps[renderItemMapIndex].clear(); // Clear contents, but keep memory if we don't change size
625     mUniformIndexMaps[renderItemMapIndex].resize(mapCount + mapNodeCount);
626
627     // Copy uniform map into mUniformIndexMap
628     uint32_t mapIndex = 0;
629     for(; mapIndex < mapCount; ++mapIndex)
630     {
631       mUniformIndexMaps[renderItemMapIndex][mapIndex].propertyValue          = uniformMap.mUniformMap[mapIndex].propertyPtr;
632       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformName            = uniformMap.mUniformMap[mapIndex].uniformName;
633       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHash        = uniformMap.mUniformMap[mapIndex].uniformNameHash;
634       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHashNoArray = uniformMap.mUniformMap[mapIndex].uniformNameHashNoArray;
635       mUniformIndexMaps[renderItemMapIndex][mapIndex].arrayIndex             = uniformMap.mUniformMap[mapIndex].arrayIndex;
636     }
637
638     for(uint32_t nodeMapIndex = 0; nodeMapIndex < mapNodeCount; ++nodeMapIndex)
639     {
640       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
641       auto& name = uniformMapNode[nodeMapIndex].uniformName;
642       bool  found(false);
643       for(uint32_t i = 0; i < mapCount; ++i)
644       {
645         if(mUniformIndexMaps[renderItemMapIndex][i].uniformNameHash == hash &&
646            mUniformIndexMaps[renderItemMapIndex][i].uniformName == name)
647         {
648           mUniformIndexMaps[renderItemMapIndex][i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
649           found                                                  = true;
650           break;
651         }
652       }
653
654       if(!found)
655       {
656         mUniformIndexMaps[renderItemMapIndex][mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
657         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
658         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
659         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
660         mUniformIndexMaps[renderItemMapIndex][mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
661         ++mapIndex;
662       }
663     }
664
665     mUniformIndexMaps[renderItemMapIndex].resize(mapIndex);
666   }
667   return renderItemMapIndex;
668 }
669
670 void Renderer::WriteUniformBuffer(
671   BufferIndex                          bufferIndex,
672   Graphics::CommandBuffer&             commandBuffer,
673   Program*                             program,
674   const SceneGraph::RenderInstruction& instruction,
675   const SceneGraph::NodeDataProvider&  node,
676   const Matrix&                        modelMatrix,
677   const Matrix&                        modelViewMatrix,
678   const Matrix&                        viewMatrix,
679   const Matrix&                        projectionMatrix,
680   const Vector3&                       size,
681   std::size_t                          nodeIndex)
682 {
683   // Create the UBO
684   uint32_t uboOffset{0u};
685
686   auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
687
688   uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired;
689
690   // Create uniform buffer view from uniform buffer
691   Graphics::UniquePtr<Render::UniformBufferView> uboView{nullptr};
692   if(uniformBlockAllocationBytes)
693   {
694     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex);
695     uboView          = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes);
696   }
697
698   // update the uniform buffer
699   // pass shared UBO and offset, return new offset for next item to be used
700   // don't process bindings if there are no uniform buffers allocated
701   if(uboView)
702   {
703     auto uboCount = reflection.GetUniformBlockCount();
704     mUniformBufferBindings.resize(uboCount);
705
706     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
707
708     mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset);
709
710     // Write default uniforms
711     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, modelMatrix);
712     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, viewMatrix);
713     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, projectionMatrix);
714     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, modelViewMatrix);
715
716     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
717     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
718     {
719       Matrix modelViewProjectionMatrix(false);
720       MatrixUtils::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
721       WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix);
722     }
723
724     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
725     if(normalUniformInfo && !normalUniformInfo->name.empty())
726     {
727       Matrix3 normalMatrix(modelViewMatrix);
728       normalMatrix.Invert();
729       normalMatrix.Transpose();
730       WriteDefaultUniform(normalUniformInfo, *uboView, normalMatrix);
731     }
732
733     Vector4        finalColor;                               ///< Applied renderer's opacity color
734     const Vector4& color = node.GetRenderColor(bufferIndex); ///< Actor's original color
735     if(mPremultipliedAlphaEnabled)
736     {
737       const float& alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
738       finalColor         = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
739     }
740     else
741     {
742       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
743     }
744     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, finalColor);
745     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::ACTOR_COLOR), *uboView, color);
746
747     // Write uniforms from the uniform map
748     FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex, nodeIndex);
749
750     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
751     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, size);
752
753     commandBuffer.BindUniformBuffers(*bindings);
754   }
755 }
756
757 template<class T>
758 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data)
759 {
760   if(uniformInfo && !uniformInfo->name.empty())
761   {
762     WriteUniform(ubo, *uniformInfo, data);
763     return true;
764   }
765   return false;
766 }
767
768 template<class T>
769 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data)
770 {
771   WriteUniform(ubo, uniformInfo, &data, sizeof(T));
772 }
773
774 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
775 {
776   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
777 }
778
779 void Renderer::FillUniformBuffer(Program&                                      program,
780                                  const SceneGraph::RenderInstruction&          instruction,
781                                  Render::UniformBufferView&                    ubo,
782                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
783                                  uint32_t&                                     offset,
784                                  BufferIndex                                   updateBufferIndex,
785                                  std::size_t                                   nodeIndex)
786 {
787   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
788   auto  uboCount   = reflection.GetUniformBlockCount();
789
790   // Setup bindings
791   uint32_t dataOffset = offset;
792   for(auto i = 0u; i < uboCount; ++i)
793   {
794     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
795     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
796
797     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
798     mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset);
799
800     for(auto iter = mUniformIndexMaps[nodeIndex].begin(),
801              end  = mUniformIndexMaps[nodeIndex].end();
802         iter != end;
803         ++iter)
804     {
805       auto& uniform    = *iter;
806       int   arrayIndex = uniform.arrayIndex;
807
808       if(!uniform.uniformFunc)
809       {
810         auto uniformInfo  = Graphics::UniformInfo{};
811         auto uniformFound = program.GetUniform(uniform.uniformName.GetStringView(),
812                                                uniform.uniformNameHash,
813                                                uniform.uniformNameHashNoArray,
814                                                uniformInfo);
815
816         uniform.uniformOffset   = uniformInfo.offset;
817         uniform.uniformLocation = uniformInfo.location;
818
819         if(uniformFound)
820         {
821           auto       dst      = ubo.GetOffset() + uniformInfo.offset;
822           const auto typeSize = GetPropertyValueSizeForUniform((*iter).propertyValue->GetType());
823           const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
824           const auto func     = GetPropertyValueGetter((*iter).propertyValue->GetType());
825
826           ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
827                     typeSize,
828                     dest);
829
830           uniform.uniformSize = typeSize;
831           uniform.uniformFunc = func;
832         }
833       }
834       else
835       {
836         auto       dst      = ubo.GetOffset() + uniform.uniformOffset;
837         const auto typeSize = uniform.uniformSize;
838         const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
839         const auto func     = uniform.uniformFunc;
840
841         ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex),
842                   typeSize,
843                   dest);
844       }
845     }
846   }
847   // write output bindings
848   outBindings = &mUniformBufferBindings;
849
850   // Update offset
851   offset = dataOffset;
852 }
853
854 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
855 {
856   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
857   sortAttributes.geometry = mGeometry;
858 }
859
860 void Renderer::SetShaderChanged(bool value)
861 {
862   mShaderChanged = value;
863 }
864
865 bool Renderer::Updated(BufferIndex bufferIndex)
866 {
867   if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged() || mRenderDataProvider->IsUpdated())
868   {
869     return true;
870   }
871
872   auto* textures = mRenderDataProvider->GetTextures();
873   if(textures)
874   {
875     for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter)
876     {
877       auto texture = *iter;
878       if(texture && texture->Updated())
879       {
880         return true;
881       }
882     }
883   }
884   return false;
885 }
886
887 Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) const noexcept
888 {
889   return mRenderDataProvider->GetVisualTransformedUpdateArea(bufferIndex, originalUpdateArea);
890 }
891
892 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
893   Program&                                             program,
894   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
895   const SceneGraph::NodeDataProvider&                  node,
896   bool                                                 blend)
897 {
898   // Prepare query info
899   PipelineCacheQueryInfo queryInfo{};
900   queryInfo.program               = &program;
901   queryInfo.renderer              = this;
902   queryInfo.geometry              = mGeometry;
903   queryInfo.blendingEnabled       = blend;
904   queryInfo.blendingOptions       = &mBlendingOptions;
905   queryInfo.alphaPremultiplied    = mPremultipliedAlphaEnabled;
906   queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed();
907
908   auto pipelineResult = mPipelineCache->GetPipeline(queryInfo, true);
909
910   // should be never null?
911   return *pipelineResult.pipeline;
912 }
913
914 void Renderer::SetRenderCallback(RenderCallback* callback)
915 {
916   mRenderCallback = callback;
917 }
918
919 } // namespace Render
920
921 } // namespace Dali::Internal