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