[dali_2.3.23] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2024 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/uniform-buffer-view.h>
36 #include <dali/internal/render/renderers/uniform-buffer.h>
37 #include <dali/internal/render/shaders/program.h>
38 #include <dali/internal/render/shaders/render-shader.h>
39 #include <dali/internal/update/common/uniform-map.h>
40 #include <dali/public-api/signals/render-callback.h>
41
42 namespace Dali::Internal
43 {
44 Dali::Matrix* testMVP;
45 uint32_t      mvpBufferIndex;
46
47 namespace
48 {
49 /**
50  * Helper function to calculate the correct alignment of data for uniform buffers
51  * @param dataSize size of uniform buffer
52  * @return aligned offset of data
53  */
54 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
55 {
56   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
57 }
58
59 /**
60  * @brief Store latest bound RenderGeometry, and help that we can skip duplicated vertex attributes bind.
61  *
62  * @param[in] geometry Current geometry to be used, or nullptr if render finished
63  * @return True if we can reuse latest bound vertex attributes. False otherwise.
64  */
65 inline bool ReuseLatestBoundVertexAttributes(const Render::Geometry* geometry)
66 {
67   static const Render::Geometry* gLatestVertexBoundGeometry = nullptr;
68   if(gLatestVertexBoundGeometry == geometry)
69   {
70     return true;
71   }
72   gLatestVertexBoundGeometry = geometry;
73   return false;
74 }
75
76 } // namespace
77
78 namespace Render
79 {
80 namespace
81 {
82 MemoryPoolObjectAllocator<Renderer>& GetRenderRendererMemoryPool()
83 {
84   static MemoryPoolObjectAllocator<Renderer> gRenderRendererMemoryPool;
85   return gRenderRendererMemoryPool;
86 }
87 } // namespace
88
89 void Renderer::PrepareCommandBuffer()
90 {
91   // Reset latest geometry informations, So we can bind the first of geometry.
92   ReuseLatestBoundVertexAttributes(nullptr);
93
94   // todo : Fill here as many caches as we can store for reduce the number of command buffers
95 }
96
97 RendererKey Renderer::NewKey(SceneGraph::RenderDataProvider* dataProvider,
98                              Render::Geometry*               geometry,
99                              uint32_t                        blendingBitmask,
100                              const Vector4&                  blendColor,
101                              FaceCullingMode::Type           faceCullingMode,
102                              bool                            preMultipliedAlphaEnabled,
103                              DepthWriteMode::Type            depthWriteMode,
104                              DepthTestMode::Type             depthTestMode,
105                              DepthFunction::Type             depthFunction,
106                              StencilParameters&              stencilParameters)
107 {
108   void* ptr = GetRenderRendererMemoryPool().AllocateRawThreadSafe();
109   auto  key = GetRenderRendererMemoryPool().GetKeyFromPtr(static_cast<Renderer*>(ptr));
110
111   // Use placement new to construct renderer.
112   new(ptr) Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
113   return RendererKey(key);
114 }
115
116 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
117                    Render::Geometry*               geometry,
118                    uint32_t                        blendingBitmask,
119                    const Vector4&                  blendColor,
120                    FaceCullingMode::Type           faceCullingMode,
121                    bool                            preMultipliedAlphaEnabled,
122                    DepthWriteMode::Type            depthWriteMode,
123                    DepthTestMode::Type             depthTestMode,
124                    DepthFunction::Type             depthFunction,
125                    StencilParameters&              stencilParameters)
126 : mGraphicsController(nullptr),
127   mRenderDataProvider(dataProvider),
128   mGeometry(geometry),
129   mProgramCache(nullptr),
130   mStencilParameters(stencilParameters),
131   mBlendingOptions(),
132   mIndexedDrawFirstElement(0),
133   mIndexedDrawElementsCount(0),
134   mDepthFunction(depthFunction),
135   mFaceCullingMode(faceCullingMode),
136   mDepthWriteMode(depthWriteMode),
137   mDepthTestMode(depthTestMode),
138   mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled),
139   mShaderChanged(false),
140   mPipelineCached(false)
141 {
142   if(blendingBitmask != 0u)
143   {
144     mBlendingOptions.SetBitmask(blendingBitmask);
145   }
146
147   mBlendingOptions.SetBlendColor(blendColor);
148 }
149
150 void Renderer::Initialize(Graphics::Controller& graphicsController, ProgramCache& programCache, Render::UniformBufferManager& uniformBufferManager, Render::PipelineCache& pipelineCache)
151 {
152   mGraphicsController   = &graphicsController;
153   mProgramCache         = &programCache;
154   mUniformBufferManager = &uniformBufferManager;
155   mPipelineCache        = &pipelineCache;
156 }
157
158 Renderer::~Renderer()
159 {
160   // Reset old pipeline
161   if(DALI_LIKELY(mPipelineCached))
162   {
163     mPipelineCache->ResetPipeline(mPipeline);
164     mPipelineCached = false;
165   }
166 }
167
168 void Renderer::operator delete(void* ptr)
169 {
170   GetRenderRendererMemoryPool().FreeThreadSafe(static_cast<Renderer*>(ptr));
171 }
172
173 Renderer* Renderer::Get(RendererKey::KeyType rendererKey)
174 {
175   return GetRenderRendererMemoryPool().GetPtrFromKey(rendererKey);
176 }
177
178 void Renderer::SetGeometry(Render::Geometry* geometry)
179 {
180   mGeometry = geometry;
181 }
182
183 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
184 {
185   mDrawCommands.clear();
186   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
187 }
188
189 bool Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer)
190 {
191   uint32_t textureUnit = 0;
192
193   auto textures(mRenderDataProvider->GetTextures());
194   auto samplers(mRenderDataProvider->GetSamplers());
195
196   std::vector<Graphics::TextureBinding> textureBindings;
197
198   if(textures != nullptr)
199   {
200     const std::uint32_t texturesCount(static_cast<std::uint32_t>(textures->Count()));
201     textureBindings.reserve(texturesCount);
202
203     for(uint32_t i = 0; i < texturesCount; ++i) // not expecting more than uint32_t of textures
204     {
205       if((*textures)[i] && (*textures)[i]->GetGraphicsObject())
206       {
207         Graphics::Texture* graphicsTexture = (*textures)[i]->GetGraphicsObject();
208         // if the sampler exists,
209         //   if it's default, delete the graphics object
210         //   otherwise re-initialize it if dirty
211
212         const Graphics::Sampler* graphicsSampler = samplers ? ((i < (*samplers).Size() && (*samplers)[i]) ? (*samplers)[i]->GetGraphicsObject()
213                                                                                                           : nullptr)
214                                                             : nullptr;
215
216         const Graphics::TextureBinding textureBinding{graphicsTexture, graphicsSampler, textureUnit};
217         textureBindings.push_back(textureBinding);
218
219         ++textureUnit;
220       }
221       else
222       {
223         // Texture is not prepared yet. We should not render now.
224         return false;
225       }
226     }
227   }
228
229   if(!textureBindings.empty())
230   {
231     commandBuffer.BindTextures(textureBindings);
232   }
233
234   return true;
235 }
236
237 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
238 {
239   mFaceCullingMode = mode;
240 }
241
242 void Renderer::SetBlendingBitMask(uint32_t bitmask)
243 {
244   mBlendingOptions.SetBitmask(bitmask);
245 }
246
247 void Renderer::SetBlendColor(const Vector4& color)
248 {
249   mBlendingOptions.SetBlendColor(color);
250 }
251
252 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
253 {
254   mIndexedDrawFirstElement = firstElement;
255 }
256
257 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
258 {
259   mIndexedDrawElementsCount = elementsCount;
260 }
261
262 void Renderer::EnablePreMultipliedAlpha(bool enable)
263 {
264   mPremultipliedAlphaEnabled = enable;
265 }
266
267 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
268 {
269   mDepthWriteMode = depthWriteMode;
270 }
271
272 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
273 {
274   mDepthTestMode = depthTestMode;
275 }
276
277 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
278 {
279   return mDepthWriteMode;
280 }
281
282 DepthTestMode::Type Renderer::GetDepthTestMode() const
283 {
284   return mDepthTestMode;
285 }
286
287 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
288 {
289   mDepthFunction = depthFunction;
290 }
291
292 DepthFunction::Type Renderer::GetDepthFunction() const
293 {
294   return mDepthFunction;
295 }
296
297 void Renderer::SetRenderMode(RenderMode::Type renderMode)
298 {
299   mStencilParameters.renderMode = renderMode;
300 }
301
302 RenderMode::Type Renderer::GetRenderMode() const
303 {
304   return mStencilParameters.renderMode;
305 }
306
307 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
308 {
309   mStencilParameters.stencilFunction = stencilFunction;
310 }
311
312 StencilFunction::Type Renderer::GetStencilFunction() const
313 {
314   return mStencilParameters.stencilFunction;
315 }
316
317 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
318 {
319   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
320 }
321
322 int Renderer::GetStencilFunctionMask() const
323 {
324   return mStencilParameters.stencilFunctionMask;
325 }
326
327 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
328 {
329   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
330 }
331
332 int Renderer::GetStencilFunctionReference() const
333 {
334   return mStencilParameters.stencilFunctionReference;
335 }
336
337 void Renderer::SetStencilMask(int stencilMask)
338 {
339   mStencilParameters.stencilMask = stencilMask;
340 }
341
342 int Renderer::GetStencilMask() const
343 {
344   return mStencilParameters.stencilMask;
345 }
346
347 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
348 {
349   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
350 }
351
352 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
353 {
354   return mStencilParameters.stencilOperationOnFail;
355 }
356
357 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
358 {
359   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
360 }
361
362 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
363 {
364   return mStencilParameters.stencilOperationOnZFail;
365 }
366
367 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
368 {
369   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
370 }
371
372 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
373 {
374   return mStencilParameters.stencilOperationOnZPass;
375 }
376
377 void Renderer::Upload()
378 {
379   mGeometry->Upload(*mGraphicsController);
380 }
381
382 bool Renderer::NeedsProgram() const
383 {
384   // Our access to shader is currently through the RenderDataProvider, which
385   // returns a reference to the shader (as at the time, we couldn't have empty
386   // renderers). We prefer to keep this as a reference. So, we don't use it
387   // here. Instead, we use the mGeometry pointer to decide if this is an empty
388   // renderer.
389   return (!mRenderCallback && mGeometry != nullptr);
390 }
391
392 Program* Renderer::PrepareProgram(const SceneGraph::RenderInstruction& instruction)
393 {
394   // Create Program
395   const SceneGraph::Shader& shader = mRenderDataProvider->GetShader();
396
397   const ShaderDataPtr& shaderData = shader.GetShaderData(instruction.mRenderPassTag);
398   if(!shaderData)
399   {
400     DALI_LOG_ERROR("Failed to get shader data.\n");
401     mCurrentProgram = nullptr;
402     return nullptr;
403   }
404
405   Program* program = Program::New(*mProgramCache,
406                                   shaderData,
407                                   *mGraphicsController);
408   if(!program)
409   {
410     DALI_LOG_ERROR("Failed to create program for shader at address %p.\n", reinterpret_cast<const void*>(&shader));
411     mCurrentProgram = nullptr;
412     return nullptr;
413   }
414
415   // If program doesn't have Gfx program object assigned yet, prepare it.
416   if(!program->GetGraphicsProgramPtr())
417   {
418     Graphics::ShaderCreateInfo vertexShaderCreateInfo;
419     vertexShaderCreateInfo.SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
420     vertexShaderCreateInfo.SetSourceMode(shaderData->GetSourceMode());
421     const std::vector<char>& vertexShaderSrc = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
422     vertexShaderCreateInfo.SetSourceSize(vertexShaderSrc.size());
423     vertexShaderCreateInfo.SetSourceData(static_cast<const void*>(vertexShaderSrc.data()));
424     vertexShaderCreateInfo.SetShaderVersion(shaderData->GetVertexShaderVersion());
425     auto vertexShader = mGraphicsController->CreateShader(vertexShaderCreateInfo, nullptr);
426
427     Graphics::ShaderCreateInfo fragmentShaderCreateInfo;
428     fragmentShaderCreateInfo.SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
429     fragmentShaderCreateInfo.SetSourceMode(shaderData->GetSourceMode());
430     const std::vector<char>& fragmentShaderSrc = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
431     fragmentShaderCreateInfo.SetSourceSize(fragmentShaderSrc.size());
432     fragmentShaderCreateInfo.SetSourceData(static_cast<const void*>(fragmentShaderSrc.data()));
433     fragmentShaderCreateInfo.SetShaderVersion(shaderData->GetFragmentShaderVersion());
434     auto fragmentShader = mGraphicsController->CreateShader(fragmentShaderCreateInfo, nullptr);
435
436     std::vector<Graphics::ShaderState> shaderStates{
437       Graphics::ShaderState()
438         .SetShader(*vertexShader.get())
439         .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
440       Graphics::ShaderState()
441         .SetShader(*fragmentShader.get())
442         .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
443
444     auto createInfo = Graphics::ProgramCreateInfo();
445     createInfo.SetShaderState(shaderStates);
446     createInfo.SetName(shaderData->GetName());
447     auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
448     program->SetGraphicsProgram(std::move(graphicsProgram), *mUniformBufferManager); // generates reflection
449   }
450
451   // Set prefetched program to be used during rendering
452   mCurrentProgram = program;
453   return mCurrentProgram;
454 }
455
456 bool Renderer::Render(Graphics::CommandBuffer&                             commandBuffer,
457                       BufferIndex                                          bufferIndex,
458                       const SceneGraph::NodeDataProvider&                  node,
459                       const Matrix&                                        modelMatrix,
460                       const Matrix&                                        modelViewMatrix,
461                       const Matrix&                                        viewMatrix,
462                       const Matrix&                                        projectionMatrix,
463                       const Vector3&                                       scale,
464                       const Vector3&                                       size,
465                       bool                                                 blend,
466                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
467                       uint32_t                                             queueIndex)
468 {
469   // Before doing anything test if the call happens in the right queue
470   if(mDrawCommands.empty() && queueIndex > 0)
471   {
472     return false;
473   }
474
475   // Check if there is render callback
476   if(mRenderCallback)
477   {
478     if(!mRenderCallbackInput)
479     {
480       mRenderCallbackInput = std::unique_ptr<RenderCallbackInput>(new RenderCallbackInput);
481     }
482
483     bool isolatedNotDirect = (mRenderCallback->GetExecutionMode() == RenderCallback::ExecutionMode::ISOLATED);
484
485     Graphics::DrawNativeInfo info{};
486     info.api      = Graphics::DrawNativeAPI::GLES;
487     info.callback = &static_cast<Dali::CallbackBase&>(*mRenderCallback);
488     info.userData = mRenderCallbackInput.get();
489
490     // Tell custom renderer whether code executes in isolation or is injected directly and may alter
491     // state or DALi rendering pipeline
492     mRenderCallbackInput->usingOwnEglContext = isolatedNotDirect;
493     // Set storage for the context to be used
494     info.glesNativeInfo.eglSharedContextStoragePointer = &mRenderCallbackInput->eglContext;
495     info.executionMode                                 = isolatedNotDirect ? Graphics::DrawNativeExecutionMode::ISOLATED : Graphics::DrawNativeExecutionMode::DIRECT;
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->view       = viewMatrix;
522     mRenderCallbackInput->projection = projectionMatrix;
523
524     MatrixUtils::MultiplyProjectionMatrix(mRenderCallbackInput->mvp, modelViewMatrix, projectionMatrix);
525
526     // submit draw
527     commandBuffer.DrawNative(&info);
528     return true;
529   }
530
531   // Prepare commands
532   std::vector<DevelRenderer::DrawCommand*> commands;
533   for(auto& cmd : mDrawCommands)
534   {
535     if(cmd.queue == queueIndex)
536     {
537       commands.emplace_back(&cmd);
538     }
539   }
540
541   // Have commands but nothing to be drawn - abort
542   if(!mDrawCommands.empty() && commands.empty())
543   {
544     return false;
545   }
546
547   // Set blending mode
548   if(!mDrawCommands.empty())
549   {
550     blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend;
551   }
552
553   bool drawn = false;
554
555   // Check all textures are prepared first.
556   if(!BindTextures(commandBuffer))
557   {
558     return drawn;
559   }
560
561   // We should have a shader here (as only RenderCallback has no shader, and that's been early out)
562   Program* program = PrepareProgram(instruction);
563   if(program)
564   {
565     // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
566     auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
567
568     commandBuffer.BindPipeline(pipeline);
569
570     if(queueIndex == 0)
571     {
572       std::size_t nodeIndex = BuildUniformIndexMap(bufferIndex, node, *program);
573       WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, scale, size, nodeIndex);
574     }
575     // @todo We should detect this case much earlier to prevent unnecessary work
576     // Reuse latest bound vertex attributes location, or Bind buffers to attribute locations.
577     if(ReuseLatestBoundVertexAttributes(mGeometry) || mGeometry->BindVertexAttributes(commandBuffer))
578     {
579       uint32_t instanceCount = mRenderDataProvider->GetInstanceCount();
580
581       if(mDrawCommands.empty())
582       {
583         drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount, instanceCount);
584       }
585       else
586       {
587         for(auto& cmd : commands)
588         {
589           drawn |= mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount, instanceCount);
590         }
591       }
592     }
593     else
594     {
595       // BindVertexAttributes failed. Reset cached geometry.
596       ReuseLatestBoundVertexAttributes(nullptr);
597     }
598   }
599
600   return drawn;
601 }
602
603 std::size_t Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, Program& program)
604 {
605   // Check if the map has changed
606   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
607
608   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMapDataProvider();
609   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetCollectedUniformMap();
610   const SceneGraph::UniformMap&             uniformMapNode         = node.GetNodeUniformMap();
611
612   bool updateMaps;
613
614   // Usual case is to only have 1 node, however we do allow multiple nodes to reuse the same
615   // renderer, so we have to cache uniform map per render item (node / renderer pair).
616
617   // Specially, if node don't have uniformMap, we mark nodePtr as nullptr.
618   // So, all nodes without uniformMap will share same UniformIndexMap, contains only render data providers.
619   const auto nodePtr    = uniformMapNode.Count() ? &node : nullptr;
620   const auto programPtr = &program;
621
622   const auto nodeChangeCounter          = nodePtr ? uniformMapNode.GetChangeCounter() : 0;
623   const auto renderItemMapChangeCounter = uniformMap.GetChangeCounter();
624
625   auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [nodePtr, programPtr](RenderItemLookup& element) { return (element.node == nodePtr && element.program == programPtr); });
626
627   std::size_t renderItemMapIndex;
628   if(iter == mNodeIndexMap.end())
629   {
630     renderItemMapIndex = mUniformIndexMaps.size();
631     RenderItemLookup renderItemLookup;
632     renderItemLookup.node                       = nodePtr;
633     renderItemLookup.program                    = programPtr;
634     renderItemLookup.index                      = renderItemMapIndex;
635     renderItemLookup.nodeChangeCounter          = nodeChangeCounter;
636     renderItemLookup.renderItemMapChangeCounter = renderItemMapChangeCounter;
637     mNodeIndexMap.emplace_back(renderItemLookup);
638
639     updateMaps = true;
640     mUniformIndexMaps.resize(mUniformIndexMaps.size() + 1);
641   }
642   else
643   {
644     renderItemMapIndex = iter->index;
645
646     updateMaps = (nodeChangeCounter != iter->nodeChangeCounter) ||
647                  (renderItemMapChangeCounter != iter->renderItemMapChangeCounter) ||
648                  (mUniformIndexMaps[renderItemMapIndex].size() == 0);
649
650     iter->nodeChangeCounter          = nodeChangeCounter;
651     iter->renderItemMapChangeCounter = renderItemMapChangeCounter;
652   }
653
654   if(updateMaps || mShaderChanged)
655   {
656     // Reset shader pointer
657     mShaderChanged = false;
658
659     const uint32_t mapCount     = uniformMap.Count();
660     const uint32_t mapNodeCount = uniformMapNode.Count();
661
662     mUniformIndexMaps[renderItemMapIndex].clear(); // Clear contents, but keep memory if we don't change size
663     mUniformIndexMaps[renderItemMapIndex].resize(mapCount + mapNodeCount);
664
665     // Copy uniform map into mUniformIndexMap
666     uint32_t mapIndex = 0;
667     for(; mapIndex < mapCount; ++mapIndex)
668     {
669       mUniformIndexMaps[renderItemMapIndex][mapIndex].propertyValue          = uniformMap.mUniformMap[mapIndex].propertyPtr;
670       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformName            = uniformMap.mUniformMap[mapIndex].uniformName;
671       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHash        = uniformMap.mUniformMap[mapIndex].uniformNameHash;
672       mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHashNoArray = uniformMap.mUniformMap[mapIndex].uniformNameHashNoArray;
673       mUniformIndexMaps[renderItemMapIndex][mapIndex].arrayIndex             = uniformMap.mUniformMap[mapIndex].arrayIndex;
674     }
675
676     for(uint32_t nodeMapIndex = 0; nodeMapIndex < mapNodeCount; ++nodeMapIndex)
677     {
678       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
679       auto& name = uniformMapNode[nodeMapIndex].uniformName;
680       bool  found(false);
681       for(uint32_t i = 0; i < mapCount; ++i)
682       {
683         if(mUniformIndexMaps[renderItemMapIndex][i].uniformNameHash == hash &&
684            mUniformIndexMaps[renderItemMapIndex][i].uniformName == name)
685         {
686           mUniformIndexMaps[renderItemMapIndex][i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
687           found                                                  = true;
688           break;
689         }
690       }
691
692       if(!found)
693       {
694         mUniformIndexMaps[renderItemMapIndex][mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
695         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
696         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
697         mUniformIndexMaps[renderItemMapIndex][mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
698         mUniformIndexMaps[renderItemMapIndex][mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
699         ++mapIndex;
700       }
701     }
702
703     mUniformIndexMaps[renderItemMapIndex].resize(mapIndex);
704   }
705   return renderItemMapIndex;
706 }
707
708 void Renderer::WriteUniformBuffer(
709   BufferIndex                          bufferIndex,
710   Graphics::CommandBuffer&             commandBuffer,
711   Program*                             program,
712   const SceneGraph::RenderInstruction& instruction,
713   const SceneGraph::NodeDataProvider&  node,
714   const Matrix&                        modelMatrix,
715   const Matrix&                        modelViewMatrix,
716   const Matrix&                        viewMatrix,
717   const Matrix&                        projectionMatrix,
718   const Vector3&                       scale,
719   const Vector3&                       size,
720   std::size_t                          nodeIndex)
721 {
722   auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
723
724   const auto& programRequirements = program->GetUniformBlocksMemoryRequirements();
725
726   // Allocate UBO view per each block (include standalone block)
727   auto blockCount = programRequirements.blockCount;
728
729   std::vector<std::unique_ptr<UniformBufferView>> uboViews;
730   uboViews.resize(blockCount);
731
732   // Prepare bindings
733   auto uboCount = reflection.GetUniformBlockCount();
734   mUniformBufferBindings.resize(uboCount);
735
736   for(auto i = 0u; i < blockCount; ++i)
737   {
738     bool standaloneUniforms = (i == 0);
739     if(programRequirements.blockSize[i])
740     {
741       auto uniformBufferView             = mUniformBufferManager->CreateUniformBufferView(programRequirements.blockSize[i], standaloneUniforms);
742       mUniformBufferBindings[i].buffer   = uniformBufferView->GetBuffer();
743       mUniformBufferBindings[i].offset   = uniformBufferView->GetOffset();
744       mUniformBufferBindings[i].binding  = standaloneUniforms ? 0 : i - 1;
745       mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
746       uboViews[i].reset(uniformBufferView.release());
747     }
748   }
749
750   // update the uniform buffer
751   // pass shared UBO and offset, return new offset for next item to be used
752   // don't process bindings if there are no uniform buffers allocated
753   if(!uboViews.empty())
754   {
755     // Write default uniforms
756     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), uboViews, modelMatrix);
757     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), uboViews, viewMatrix);
758     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), uboViews, projectionMatrix);
759     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), uboViews, modelViewMatrix);
760
761     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
762     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
763     {
764       Matrix modelViewProjectionMatrix(false);
765       MatrixUtils::MultiplyProjectionMatrix(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
766       WriteDefaultUniformV2(mvpUniformInfo, uboViews, modelViewProjectionMatrix);
767     }
768
769     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
770     if(normalUniformInfo && !normalUniformInfo->name.empty())
771     {
772       Matrix3 normalMatrix(modelViewMatrix);
773       normalMatrix.Invert();
774       normalMatrix.Transpose();
775       WriteDefaultUniformV2(normalUniformInfo, uboViews, normalMatrix);
776     }
777
778     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::SCALE), uboViews, scale);
779
780     Vector4        finalColor;                               ///< Applied renderer's opacity color
781     const Vector4& color = node.GetRenderColor(bufferIndex); ///< Actor's original color
782     if(mPremultipliedAlphaEnabled)
783     {
784       const float& alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
785       finalColor         = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
786     }
787     else
788     {
789       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
790     }
791     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), uboViews, finalColor);
792     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::ACTOR_COLOR), uboViews, color);
793
794     // Write uniforms from the uniform map
795     FillUniformBuffer(*program, instruction, uboViews, bufferIndex, nodeIndex);
796
797     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
798     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), uboViews, size);
799
800     commandBuffer.BindUniformBuffers(mUniformBufferBindings);
801   }
802 }
803
804 template<class T>
805 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data)
806 {
807   if(uniformInfo && !uniformInfo->name.empty())
808   {
809     WriteUniform(ubo, *uniformInfo, data);
810     return true;
811   }
812   return false;
813 }
814
815 template<class T>
816 bool Renderer::WriteDefaultUniformV2(const Graphics::UniformInfo* uniformInfo, const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews, const T& data)
817 {
818   if(uniformInfo && !uniformInfo->name.empty())
819   {
820     WriteUniform(*uboViews[uniformInfo->bufferIndex], *uniformInfo, data);
821     return true;
822   }
823   return false;
824 }
825
826 template<class T>
827 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data)
828 {
829   WriteUniform(ubo, uniformInfo, &data, sizeof(T));
830 }
831
832 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
833 {
834   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
835 }
836
837 void Renderer::FillUniformBuffer(Program&                                                       program,
838                                  const SceneGraph::RenderInstruction&                           instruction,
839                                  const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews,
840                                  BufferIndex                                                    updateBufferIndex,
841                                  std::size_t                                                    nodeIndex)
842 {
843   for(auto& iter : mUniformIndexMaps[nodeIndex])
844   {
845     auto& uniform    = iter;
846     int   arrayIndex = uniform.arrayIndex;
847     if(!uniform.initialized)
848     {
849       auto uniformInfo  = Graphics::UniformInfo{};
850       auto uniformFound = program.GetUniform(uniform.uniformName.GetStringView(),
851                                              uniform.uniformNameHash,
852                                              uniform.uniformNameHashNoArray,
853                                              uniformInfo);
854
855       UniformBufferView* ubo = nullptr;
856       if(uniformFound)
857       {
858         ubo = uboViews[uniformInfo.bufferIndex].get();
859       }
860       else
861       {
862         continue;
863       }
864
865       uniform.uniformOffset     = uniformInfo.offset;
866       uniform.uniformLocation   = uniformInfo.location;
867       uniform.uniformBlockIndex = uniformInfo.bufferIndex;
868       uniform.initialized       = true;
869
870       auto       dst      = ubo->GetOffset() + uniformInfo.offset;
871       const auto typeSize = iter.propertyValue->GetValueSize();
872       const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
873
874       ubo->Write(iter.propertyValue->GetValueAddress(updateBufferIndex),
875                  typeSize,
876                  dest);
877     }
878     else
879     {
880       UniformBufferView* ubo = uboViews[uniform.uniformBlockIndex].get();
881
882       auto       dst      = ubo->GetOffset() + uniform.uniformOffset;
883       const auto typeSize = iter.propertyValue->GetValueSize();
884       const auto dest     = dst + static_cast<uint32_t>(typeSize) * arrayIndex;
885
886       ubo->Write(iter.propertyValue->GetValueAddress(updateBufferIndex),
887                  typeSize,
888                  dest);
889     }
890   }
891 }
892
893 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
894 {
895   sortAttributes.shader   = &mRenderDataProvider->GetShader();
896   sortAttributes.geometry = mGeometry;
897 }
898
899 void Renderer::SetShaderChanged(bool value)
900 {
901   mShaderChanged = value;
902 }
903
904 bool Renderer::Updated()
905 {
906   if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged() || mRenderDataProvider->IsUpdated())
907   {
908     return true;
909   }
910
911   auto* textures = mRenderDataProvider->GetTextures();
912   if(textures)
913   {
914     for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter)
915     {
916       auto texture = *iter;
917       if(texture && texture->Updated())
918       {
919         return true;
920       }
921     }
922   }
923   return false;
924 }
925
926 Vector4 Renderer::GetVisualTransformedUpdateArea(BufferIndex bufferIndex, const Vector4& originalUpdateArea) const noexcept
927 {
928   return mRenderDataProvider->GetVisualTransformedUpdateArea(bufferIndex, originalUpdateArea);
929 }
930
931 void Renderer::DetachFromNodeDataProvider(const SceneGraph::NodeDataProvider& node)
932 {
933   // All nodes without uniformMap will share same UniformIndexMap, contains only render data providers.
934   // It is special case so we don't need to remove index map in this case. Fast out.
935   if(node.GetNodeUniformMap().Count() == 0u)
936   {
937     return;
938   }
939
940   // Remove mNodeIndexMap and mUniformIndexMaps.
941   auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [&node](RenderItemLookup& element) { return element.node == &node; });
942   while(iter != mNodeIndexMap.end())
943   {
944     // Swap between end of mUniformIndexMaps and removed.
945     auto nodeIndex           = iter->index;
946     auto uniformIndexMapSize = mUniformIndexMaps.size();
947
948     // Remove node index map.
949     mNodeIndexMap.erase(iter);
950
951     if(nodeIndex + 1 != uniformIndexMapSize)
952     {
953       std::swap(mUniformIndexMaps[nodeIndex], mUniformIndexMaps[uniformIndexMapSize - 1u]);
954       // Change node index map.
955       for(auto&& renderItemLookup : mNodeIndexMap)
956       {
957         if(renderItemLookup.index == uniformIndexMapSize - 1u)
958         {
959           renderItemLookup.index = nodeIndex;
960           break;
961         }
962       }
963     }
964
965     // Remove uniform index maps.
966     mUniformIndexMaps.pop_back();
967
968     iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [&node](RenderItemLookup& element) { return element.node == &node; });
969   }
970 }
971
972 Vector4 Renderer::GetTextureUpdateArea() const noexcept
973 {
974   Vector4 result = Vector4::ZERO;
975
976   auto* textures = mRenderDataProvider->GetTextures();
977   if(textures)
978   {
979     Rect<uint16_t> updatedArea{};
980     uint16_t       width = 0, height = 0;
981     for(auto iter = textures->Begin(), end = textures->End(); iter < end; ++iter)
982     {
983       if(*iter)
984       {
985         Rect<uint16_t> area = (*iter)->GetUpdatedArea();
986         if(updatedArea.IsEmpty())
987         {
988           updatedArea = area;
989
990           // Assume all texture sizes are same
991           width  = (*iter)->GetWidth();
992           height = (*iter)->GetHeight();
993         }
994         else
995         {
996           // Merge
997           updatedArea.Merge(area);
998         }
999         if(updatedArea.width == width && updatedArea.height == height)
1000         {
1001           break; // full area
1002         }
1003       }
1004     }
1005     result = Vector4(updatedArea.x - width / 2.0f + updatedArea.width / 2.0f, updatedArea.y - height / 2.0f + updatedArea.height / 2.0f, updatedArea.width, updatedArea.height);
1006   }
1007   return result;
1008 }
1009
1010 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
1011   Program&                                             program,
1012   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
1013   const SceneGraph::NodeDataProvider&                  node,
1014   bool                                                 blend)
1015 {
1016   // Prepare query info
1017   PipelineCacheQueryInfo queryInfo{};
1018   queryInfo.program               = &program;
1019   queryInfo.renderer              = this;
1020   queryInfo.geometry              = mGeometry;
1021   queryInfo.blendingEnabled       = blend;
1022   queryInfo.blendingOptions       = &mBlendingOptions;
1023   queryInfo.alphaPremultiplied    = mPremultipliedAlphaEnabled;
1024   queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed();
1025
1026   queryInfo.GenerateHash();
1027
1028   // Reset old pipeline
1029   if(DALI_LIKELY(mPipelineCached))
1030   {
1031     mPipelineCache->ResetPipeline(mPipeline);
1032     mPipelineCached = false;
1033   }
1034
1035   // Find or generate new pipeline.
1036   auto pipelineResult = mPipelineCache->GetPipeline(queryInfo, true);
1037
1038   mPipeline       = pipelineResult.level2;
1039   mPipelineCached = true;
1040
1041   // should be never null?
1042   return *pipelineResult.pipeline;
1043 }
1044
1045 void Renderer::SetRenderCallback(RenderCallback* callback)
1046 {
1047   mRenderCallback = callback;
1048 }
1049
1050 } // namespace Render
1051
1052 } // namespace Dali::Internal