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