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