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