Clean up in Aisle #3
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.cpp
1 /*
2  * Copyright (c) 2021 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-program.h>
23 #include <dali/graphics-api/graphics-types.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/internal/common/image-sampler.h>
26 #include <dali/internal/render/common/render-instruction.h>
27 #include <dali/internal/render/data-providers/node-data-provider.h>
28 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
29 #include <dali/internal/render/renderers/render-sampler.h>
30 #include <dali/internal/render/renderers/render-texture.h>
31 #include <dali/internal/render/renderers/render-vertex-buffer.h>
32 #include <dali/internal/render/renderers/shader-cache.h>
33 #include <dali/internal/render/shaders/program.h>
34 #include <dali/internal/render/shaders/render-shader.h>
35 #include <dali/internal/update/common/uniform-map.h>
36
37 namespace Dali
38 {
39 namespace Internal
40 {
41 namespace
42 {
43 // Size of uniform buffer page used when resizing
44 constexpr uint32_t UBO_PAGE_SIZE = 8192u;
45
46 // UBO allocation threshold below which the UBO will shrink
47 constexpr auto UBO_SHRINK_THRESHOLD = 0.75f;
48
49 // Helper to get the vertex input format
50 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
51 {
52   Dali::Graphics::VertexInputFormat type{};
53
54   switch(propertyType)
55   {
56     case Property::NONE:
57     case Property::STRING:
58     case Property::ARRAY:
59     case Property::MAP:
60     case Property::EXTENTS:   // i4?
61     case Property::RECTANGLE: // i4/f4?
62     case Property::ROTATION:
63     {
64       type = Dali::Graphics::VertexInputFormat::UNDEFINED;
65       break;
66     }
67     case Property::BOOLEAN:
68     {
69       type = Dali::Graphics::VertexInputFormat::UNDEFINED; // type = GL_BYTE; @todo new type for this?
70       break;
71     }
72     case Property::INTEGER:
73     {
74       type = Dali::Graphics::VertexInputFormat::INTEGER; // (short)
75       break;
76     }
77     case Property::FLOAT:
78     {
79       type = Dali::Graphics::VertexInputFormat::FLOAT;
80       break;
81     }
82     case Property::VECTOR2:
83     {
84       type = Dali::Graphics::VertexInputFormat::FVECTOR2;
85       break;
86     }
87     case Property::VECTOR3:
88     {
89       type = Dali::Graphics::VertexInputFormat::FVECTOR3;
90       break;
91     }
92     case Property::VECTOR4:
93     {
94       type = Dali::Graphics::VertexInputFormat::FVECTOR4;
95       break;
96     }
97     case Property::MATRIX3:
98     case Property::MATRIX:
99     {
100       type = Dali::Graphics::VertexInputFormat::FLOAT;
101       break;
102     }
103   }
104
105   return type;
106 }
107
108 constexpr Graphics::CullMode ConvertCullFace(Dali::FaceCullingMode::Type mode)
109 {
110   switch(mode)
111   {
112     case Dali::FaceCullingMode::NONE:
113     {
114       return Graphics::CullMode::NONE;
115     }
116     case Dali::FaceCullingMode::FRONT:
117     {
118       return Graphics::CullMode::FRONT;
119     }
120     case Dali::FaceCullingMode::BACK:
121     {
122       return Graphics::CullMode::BACK;
123     }
124     case Dali::FaceCullingMode::FRONT_AND_BACK:
125     {
126       return Graphics::CullMode::FRONT_AND_BACK;
127     }
128   }
129   return Graphics::CullMode::NONE;
130 }
131
132 constexpr Graphics::BlendFactor ConvertBlendFactor(BlendFactor::Type blendFactor)
133 {
134   switch(blendFactor)
135   {
136     case BlendFactor::ZERO:
137       return Graphics::BlendFactor::ZERO;
138     case BlendFactor::ONE:
139       return Graphics::BlendFactor::ONE;
140     case BlendFactor::SRC_COLOR:
141       return Graphics::BlendFactor::SRC_COLOR;
142     case BlendFactor::ONE_MINUS_SRC_COLOR:
143       return Graphics::BlendFactor::ONE_MINUS_SRC_COLOR;
144     case BlendFactor::SRC_ALPHA:
145       return Graphics::BlendFactor::SRC_ALPHA;
146     case BlendFactor::ONE_MINUS_SRC_ALPHA:
147       return Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA;
148     case BlendFactor::DST_ALPHA:
149       return Graphics::BlendFactor::DST_ALPHA;
150     case BlendFactor::ONE_MINUS_DST_ALPHA:
151       return Graphics::BlendFactor::ONE_MINUS_DST_ALPHA;
152     case BlendFactor::DST_COLOR:
153       return Graphics::BlendFactor::DST_COLOR;
154     case BlendFactor::ONE_MINUS_DST_COLOR:
155       return Graphics::BlendFactor::ONE_MINUS_DST_COLOR;
156     case BlendFactor::SRC_ALPHA_SATURATE:
157       return Graphics::BlendFactor::SRC_ALPHA_SATURATE;
158     case BlendFactor::CONSTANT_COLOR:
159       return Graphics::BlendFactor::CONSTANT_COLOR;
160     case BlendFactor::ONE_MINUS_CONSTANT_COLOR:
161       return Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR;
162     case BlendFactor::CONSTANT_ALPHA:
163       return Graphics::BlendFactor::CONSTANT_ALPHA;
164     case BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
165       return Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA;
166   }
167   return Graphics::BlendFactor{};
168 }
169
170 constexpr Graphics::BlendOp ConvertBlendEquation(DevelBlendEquation::Type blendEquation)
171 {
172   switch(blendEquation)
173   {
174     case DevelBlendEquation::ADD:
175       return Graphics::BlendOp::ADD;
176     case DevelBlendEquation::SUBTRACT:
177       return Graphics::BlendOp::SUBTRACT;
178     case DevelBlendEquation::REVERSE_SUBTRACT:
179       return Graphics::BlendOp::REVERSE_SUBTRACT;
180     case DevelBlendEquation::COLOR:
181     case DevelBlendEquation::COLOR_BURN:
182     case DevelBlendEquation::COLOR_DODGE:
183     case DevelBlendEquation::DARKEN:
184     case DevelBlendEquation::DIFFERENCE:
185     case DevelBlendEquation::EXCLUSION:
186     case DevelBlendEquation::HARD_LIGHT:
187     case DevelBlendEquation::HUE:
188     case DevelBlendEquation::LIGHTEN:
189     case DevelBlendEquation::LUMINOSITY:
190     case DevelBlendEquation::MAX:
191     case DevelBlendEquation::MIN:
192     case DevelBlendEquation::MULTIPLY:
193     case DevelBlendEquation::OVERLAY:
194     case DevelBlendEquation::SATURATION:
195     case DevelBlendEquation::SCREEN:
196     case DevelBlendEquation::SOFT_LIGHT:
197       return Graphics::BlendOp{};
198   }
199   return Graphics::BlendOp{};
200 }
201
202 /**
203  * Helper function to calculate the correct alignment of data for uniform buffers
204  * @param dataSize size of uniform buffer
205  * @return aligned offset of data
206  */
207 inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
208 {
209   return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
210 }
211
212 } // namespace
213
214 namespace Render
215 {
216 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
217                         Render::Geometry*               geometry,
218                         uint32_t                        blendingBitmask,
219                         const Vector4&                  blendColor,
220                         FaceCullingMode::Type           faceCullingMode,
221                         bool                            preMultipliedAlphaEnabled,
222                         DepthWriteMode::Type            depthWriteMode,
223                         DepthTestMode::Type             depthTestMode,
224                         DepthFunction::Type             depthFunction,
225                         StencilParameters&              stencilParameters)
226 {
227   return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
228 }
229
230 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
231                    Render::Geometry*               geometry,
232                    uint32_t                        blendingBitmask,
233                    const Vector4&                  blendColor,
234                    FaceCullingMode::Type           faceCullingMode,
235                    bool                            preMultipliedAlphaEnabled,
236                    DepthWriteMode::Type            depthWriteMode,
237                    DepthTestMode::Type             depthTestMode,
238                    DepthFunction::Type             depthFunction,
239                    StencilParameters&              stencilParameters)
240 : mGraphicsController(nullptr),
241   mRenderDataProvider(dataProvider),
242   mGeometry(geometry),
243   mProgramCache(nullptr),
244   mUniformIndexMap(),
245   mAttributeLocations(),
246   mUniformsHash(),
247   mStencilParameters(stencilParameters),
248   mBlendingOptions(),
249   mIndexedDrawFirstElement(0),
250   mIndexedDrawElementsCount(0),
251   mDepthFunction(depthFunction),
252   mFaceCullingMode(faceCullingMode),
253   mDepthWriteMode(depthWriteMode),
254   mDepthTestMode(depthTestMode),
255   mUpdateAttributeLocations(true),
256   mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled),
257   mShaderChanged(false),
258   mUpdated(true)
259 {
260   if(blendingBitmask != 0u)
261   {
262     mBlendingOptions.SetBitmask(blendingBitmask);
263   }
264
265   mBlendingOptions.SetBlendColor(blendColor);
266 }
267
268 void Renderer::Initialize(Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache, Render::UniformBufferManager& uniformBufferManager)
269 {
270   mGraphicsController   = &graphicsController;
271   mProgramCache         = &programCache;
272   mShaderCache          = &shaderCache;
273   mUniformBufferManager = &uniformBufferManager;
274 }
275
276 Renderer::~Renderer() = default;
277
278 void Renderer::SetGeometry(Render::Geometry* geometry)
279 {
280   mGeometry                 = geometry;
281   mUpdateAttributeLocations = true;
282 }
283 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
284 {
285   mDrawCommands.clear();
286   mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
287 }
288
289 void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
290 {
291   uint32_t textureUnit = 0;
292
293   std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
294   std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
295
296   std::vector<Graphics::TextureBinding> textureBindings;
297   for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()); ++i) // not expecting more than uint32_t of textures
298   {
299     if(textures[i] && textures[i]->GetGraphicsObject())
300     {
301       // if the sampler exists,
302       //   if it's default, delete the graphics object
303       //   otherwise re-initialize it if dirty
304
305       const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
306                                                               : nullptr);
307
308       boundTextures.PushBack(textures[i]->GetGraphicsObject());
309       const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
310       textureBindings.push_back(textureBinding);
311
312       ++textureUnit;
313     }
314   }
315
316   if(!textureBindings.empty())
317   {
318     commandBuffer.BindTextures(textureBindings);
319   }
320 }
321
322 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
323 {
324   mFaceCullingMode = mode;
325   mUpdated         = true;
326 }
327
328 void Renderer::SetBlendingBitMask(uint32_t bitmask)
329 {
330   mBlendingOptions.SetBitmask(bitmask);
331   mUpdated = true;
332 }
333
334 void Renderer::SetBlendColor(const Vector4& color)
335 {
336   mBlendingOptions.SetBlendColor(color);
337   mUpdated = true;
338 }
339
340 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
341 {
342   mIndexedDrawFirstElement = firstElement;
343   mUpdated                 = true;
344 }
345
346 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
347 {
348   mIndexedDrawElementsCount = elementsCount;
349   mUpdated                  = true;
350 }
351
352 void Renderer::EnablePreMultipliedAlpha(bool enable)
353 {
354   mPremultipliedAlphaEnabled = enable;
355   mUpdated                   = true;
356 }
357
358 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
359 {
360   mDepthWriteMode = depthWriteMode;
361   mUpdated        = true;
362 }
363
364 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
365 {
366   mDepthTestMode = depthTestMode;
367   mUpdated       = true;
368 }
369
370 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
371 {
372   return mDepthWriteMode;
373 }
374
375 DepthTestMode::Type Renderer::GetDepthTestMode() const
376 {
377   return mDepthTestMode;
378 }
379
380 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
381 {
382   mDepthFunction = depthFunction;
383   mUpdated       = true;
384 }
385
386 DepthFunction::Type Renderer::GetDepthFunction() const
387 {
388   return mDepthFunction;
389 }
390
391 void Renderer::SetRenderMode(RenderMode::Type renderMode)
392 {
393   mStencilParameters.renderMode = renderMode;
394   mUpdated                      = true;
395 }
396
397 RenderMode::Type Renderer::GetRenderMode() const
398 {
399   return mStencilParameters.renderMode;
400 }
401
402 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
403 {
404   mStencilParameters.stencilFunction = stencilFunction;
405   mUpdated                           = true;
406 }
407
408 StencilFunction::Type Renderer::GetStencilFunction() const
409 {
410   return mStencilParameters.stencilFunction;
411 }
412
413 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
414 {
415   mStencilParameters.stencilFunctionMask = stencilFunctionMask;
416   mUpdated                               = true;
417 }
418
419 int Renderer::GetStencilFunctionMask() const
420 {
421   return mStencilParameters.stencilFunctionMask;
422 }
423
424 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
425 {
426   mStencilParameters.stencilFunctionReference = stencilFunctionReference;
427   mUpdated                                    = true;
428 }
429
430 int Renderer::GetStencilFunctionReference() const
431 {
432   return mStencilParameters.stencilFunctionReference;
433 }
434
435 void Renderer::SetStencilMask(int stencilMask)
436 {
437   mStencilParameters.stencilMask = stencilMask;
438   mUpdated                       = true;
439 }
440
441 int Renderer::GetStencilMask() const
442 {
443   return mStencilParameters.stencilMask;
444 }
445
446 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
447 {
448   mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
449   mUpdated                                  = true;
450 }
451
452 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
453 {
454   return mStencilParameters.stencilOperationOnFail;
455 }
456
457 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
458 {
459   mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
460   mUpdated                                   = true;
461 }
462
463 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
464 {
465   return mStencilParameters.stencilOperationOnZFail;
466 }
467
468 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
469 {
470   mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
471   mUpdated                                   = true;
472 }
473
474 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
475 {
476   return mStencilParameters.stencilOperationOnZPass;
477 }
478
479 void Renderer::Upload()
480 {
481   mGeometry->Upload(*mGraphicsController);
482 }
483
484 bool Renderer::Render(Graphics::CommandBuffer&                             commandBuffer,
485                       BufferIndex                                          bufferIndex,
486                       const SceneGraph::NodeDataProvider&                  node,
487                       const Matrix&                                        modelMatrix,
488                       const Matrix&                                        modelViewMatrix,
489                       const Matrix&                                        viewMatrix,
490                       const Matrix&                                        projectionMatrix,
491                       const Vector3&                                       size,
492                       bool                                                 blend,
493                       Vector<Graphics::Texture*>&                          boundTextures,
494                       const Dali::Internal::SceneGraph::RenderInstruction& instruction,
495                       uint32_t                                             queueIndex)
496 {
497   // Before doing anything test if the call happens in the right queue
498   if(mDrawCommands.empty() && queueIndex > 0)
499   {
500     return false;
501   }
502
503   // Prepare commands
504   std::vector<DevelRenderer::DrawCommand*> commands;
505   for(auto& cmd : mDrawCommands)
506   {
507     if(cmd.queue == queueIndex)
508     {
509       commands.emplace_back(&cmd);
510     }
511   }
512
513   // Have commands but nothing to be drawn - abort
514   if(!mDrawCommands.empty() && commands.empty())
515   {
516     return false;
517   }
518
519   // Set blending mode
520   if(!mDrawCommands.empty())
521   {
522     blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend;
523   }
524
525   // Create Program
526   ShaderDataPtr            shaderData   = mRenderDataProvider->GetShader().GetShaderData();
527   const std::vector<char>& vertShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
528   const std::vector<char>& fragShader   = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
529   Dali::Graphics::Shader&  vertexShader = mShaderCache->GetShader(
530     vertShader,
531     Graphics::PipelineStage::VERTEX_SHADER,
532     shaderData->GetSourceMode());
533
534   Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
535     fragShader,
536     Graphics::PipelineStage::FRAGMENT_SHADER,
537     shaderData->GetSourceMode());
538
539   std::vector<Graphics::ShaderState> shaderStates{
540     Graphics::ShaderState()
541       .SetShader(vertexShader)
542       .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
543     Graphics::ShaderState()
544       .SetShader(fragmentShader)
545       .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
546
547   auto createInfo = Graphics::ProgramCreateInfo();
548   createInfo.SetShaderState(shaderStates);
549
550   auto     graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
551   Program* program         = Program::New(*mProgramCache,
552                                   shaderData,
553                                   *mGraphicsController,
554                                   std::move(graphicsProgram));
555
556   if(!program)
557   {
558     DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
559     return false;
560   }
561
562   // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
563   auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
564
565   commandBuffer.BindPipeline(pipeline);
566
567   BindTextures(commandBuffer, boundTextures);
568
569   BuildUniformIndexMap(bufferIndex, node, size, *program);
570
571   WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size);
572
573   bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
574                       // @todo We should detect this case much earlier to prevent unnecessary work
575
576   if(mDrawCommands.empty())
577   {
578     drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
579   }
580   else
581   {
582     for(auto& cmd : commands)
583     {
584       mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
585     }
586   }
587
588   mUpdated = false;
589   return drawn;
590 }
591
592 void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
593 {
594   // Check if the map has changed
595   DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
596
597   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
598
599   if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
600      node.GetUniformMapChanged(bufferIndex) ||
601      mUniformIndexMap.Count() == 0 ||
602      mShaderChanged)
603   {
604     // Reset shader pointer
605     mShaderChanged = false;
606
607     const SceneGraph::CollectedUniformMap& uniformMap     = uniformMapDataProvider.GetUniformMap(bufferIndex);
608     const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
609
610     auto maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
611     mUniformIndexMap.Clear();                                                          // Clear contents, but keep memory if we don't change size
612     mUniformIndexMap.Resize(maxMaps);
613
614     // Copy uniform map into mUniformIndexMap
615     uint32_t mapIndex = 0;
616     for(; mapIndex < uniformMap.Count(); ++mapIndex)
617     {
618       mUniformIndexMap[mapIndex].propertyValue          = uniformMap[mapIndex].propertyPtr;
619       mUniformIndexMap[mapIndex].uniformName            = uniformMap[mapIndex].uniformName;
620       mUniformIndexMap[mapIndex].uniformNameHash        = uniformMap[mapIndex].uniformNameHash;
621       mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMap[mapIndex].uniformNameHashNoArray;
622       mUniformIndexMap[mapIndex].arrayIndex             = uniformMap[mapIndex].arrayIndex;
623     }
624
625     for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
626     {
627       auto  hash = uniformMapNode[nodeMapIndex].uniformNameHash;
628       auto& name = uniformMapNode[nodeMapIndex].uniformName;
629       bool  found(false);
630       for(uint32_t i = 0; i < uniformMap.Count(); ++i)
631       {
632         if(mUniformIndexMap[i].uniformNameHash == hash &&
633            mUniformIndexMap[i].uniformName == name)
634         {
635           mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
636           found                             = true;
637           break;
638         }
639       }
640
641       if(!found)
642       {
643         mUniformIndexMap[mapIndex].propertyValue          = uniformMapNode[nodeMapIndex].propertyPtr;
644         mUniformIndexMap[mapIndex].uniformName            = uniformMapNode[nodeMapIndex].uniformName;
645         mUniformIndexMap[mapIndex].uniformNameHash        = uniformMapNode[nodeMapIndex].uniformNameHash;
646         mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray;
647         mUniformIndexMap[mapIndex].arrayIndex             = uniformMapNode[nodeMapIndex].arrayIndex;
648         ++mapIndex;
649       }
650     }
651
652     mUniformIndexMap.Resize(mapIndex);
653   }
654 }
655
656 void Renderer::WriteUniformBuffer(
657   BufferIndex                          bufferIndex,
658   Graphics::CommandBuffer&             commandBuffer,
659   Program*                             program,
660   const SceneGraph::RenderInstruction& instruction,
661   const SceneGraph::NodeDataProvider&  node,
662   const Matrix&                        modelMatrix,
663   const Matrix&                        modelViewMatrix,
664   const Matrix&                        viewMatrix,
665   const Matrix&                        projectionMatrix,
666   const Vector3&                       size)
667 {
668   // Create the UBO
669   uint32_t uniformBlockAllocationBytes{0u};
670   uint32_t uniformBlockMaxSize{0u};
671   uint32_t uboOffset{0u};
672
673   auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
674   for(auto i = 0u; i < reflection.GetUniformBlockCount(); ++i)
675   {
676     auto blockSize = GetUniformBufferDataAlignment(reflection.GetUniformBlockSize(i));
677     if(uniformBlockMaxSize < blockSize)
678     {
679       uniformBlockMaxSize = blockSize;
680     }
681     uniformBlockAllocationBytes += blockSize;
682   }
683
684   auto pagedAllocation = ((uniformBlockAllocationBytes / UBO_PAGE_SIZE + 1u)) * UBO_PAGE_SIZE;
685
686   // Allocate twice memory as required by the uniform buffers
687   // todo: memory usage backlog to use optimal allocation
688   if(uniformBlockAllocationBytes && !mUniformBuffer[bufferIndex])
689   {
690     mUniformBuffer[bufferIndex] = mUniformBufferManager->AllocateUniformBuffer(pagedAllocation);
691   }
692   else if(uniformBlockAllocationBytes && (mUniformBuffer[bufferIndex]->GetSize() < pagedAllocation ||
693                                           (pagedAllocation < uint32_t(float(mUniformBuffer[bufferIndex]->GetSize()) * UBO_SHRINK_THRESHOLD))))
694   {
695     mUniformBuffer[bufferIndex]->Reserve(pagedAllocation);
696   }
697
698   // Clear UBO
699   if(mUniformBuffer[bufferIndex])
700   {
701     mUniformBuffer[bufferIndex]->Fill(0, 0u, 0u);
702   }
703
704   // update the uniform buffer
705   // pass shared UBO and offset, return new offset for next item to be used
706   // don't process bindings if there are no uniform buffers allocated
707   auto ubo = mUniformBuffer[bufferIndex].get();
708   if(ubo)
709   {
710     auto uboCount = reflection.GetUniformBlockCount();
711     mUniformBufferBindings.resize(uboCount);
712
713     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
714
715     // Write default uniforms
716     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *ubo, *bindings, modelMatrix);
717     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *ubo, *bindings, viewMatrix);
718     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *ubo, *bindings, projectionMatrix);
719     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *ubo, *bindings, modelViewMatrix);
720
721     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
722     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
723     {
724       Matrix modelViewProjectionMatrix(false);
725       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
726       WriteDefaultUniform(mvpUniformInfo, *ubo, *bindings, modelViewProjectionMatrix);
727     }
728
729     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
730     if(normalUniformInfo && !normalUniformInfo->name.empty())
731     {
732       Matrix3 normalMatrix(modelViewMatrix);
733       normalMatrix.Invert();
734       normalMatrix.Transpose();
735       WriteDefaultUniform(normalUniformInfo, *ubo, *bindings, normalMatrix);
736     }
737
738     Vector4        finalColor;
739     const Vector4& color = node.GetRenderColor(bufferIndex);
740     if(mPremultipliedAlphaEnabled)
741     {
742       float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
743       finalColor  = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
744     }
745     else
746     {
747       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
748     }
749     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *ubo, *bindings, finalColor);
750
751     // Write uniforms from the uniform map
752     FillUniformBuffer(*program, instruction, *ubo, bindings, uboOffset, bufferIndex);
753
754     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
755     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *ubo, *bindings, size);
756
757     commandBuffer.BindUniformBuffers(*bindings);
758   }
759 }
760
761 template<class T>
762 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const T& data)
763 {
764   if(uniformInfo && !uniformInfo->name.empty())
765   {
766     WriteUniform(ubo, bindings, *uniformInfo, data);
767     return true;
768   }
769   return false;
770 }
771
772 template<class T>
773 void Renderer::WriteUniform(Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const T& data)
774 {
775   WriteUniform(ubo, bindings, uniformInfo, &data, sizeof(T));
776 }
777
778 void Renderer::WriteUniform(Render::UniformBuffer& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
779 {
780   ubo.Write(data, size, bindings[uniformInfo.bufferIndex].offset + uniformInfo.offset);
781 }
782
783 void Renderer::FillUniformBuffer(Program&                                      program,
784                                  const SceneGraph::RenderInstruction&          instruction,
785                                  Render::UniformBuffer&                        ubo,
786                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
787                                  uint32_t&                                     offset,
788                                  BufferIndex                                   updateBufferIndex)
789 {
790   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
791   auto  uboCount   = reflection.GetUniformBlockCount();
792
793   // Setup bindings
794   uint32_t dataOffset = offset;
795   for(auto i = 0u; i < uboCount; ++i)
796   {
797     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
798     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
799     mUniformBufferBindings[i].offset   = dataOffset;
800
801     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
802     mUniformBufferBindings[i].buffer = ubo.GetBuffer();
803
804     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
805                                        end  = mUniformIndexMap.End();
806         iter != end;
807         ++iter)
808     {
809       // @todo This means parsing the uniform string every frame. Instead, store the array index if present.
810       int arrayIndex = (*iter).arrayIndex;
811
812       auto uniformInfo  = Graphics::UniformInfo{};
813       auto uniformFound = program.GetUniform((*iter).uniformName.GetCString(),
814                                              (*iter).uniformNameHashNoArray ? (*iter).uniformNameHashNoArray
815                                                                             : (*iter).uniformNameHash,
816                                              uniformInfo);
817
818       if(uniformFound)
819       {
820         auto dst = mUniformBufferBindings[uniformInfo.bufferIndex].offset + uniformInfo.offset;
821
822         switch((*iter).propertyValue->GetType())
823         {
824           case Property::Type::BOOLEAN:
825           {
826             ubo.Write(&(*iter).propertyValue->GetBoolean(updateBufferIndex),
827                       sizeof(bool),
828                       dst + static_cast<uint32_t>(sizeof(bool)) * arrayIndex);
829             break;
830           }
831           case Property::Type::INTEGER:
832           {
833             ubo.Write(&(*iter).propertyValue->GetInteger(updateBufferIndex),
834                       sizeof(int32_t),
835                       dst + static_cast<int32_t>(sizeof(int32_t)) * arrayIndex);
836             break;
837           }
838           case Property::Type::FLOAT:
839           {
840             ubo.Write(&(*iter).propertyValue->GetFloat(updateBufferIndex),
841                       sizeof(float),
842                       dst + static_cast<uint32_t>(sizeof(float)) * arrayIndex);
843             break;
844           }
845           case Property::Type::VECTOR2:
846           {
847             ubo.Write(&(*iter).propertyValue->GetVector2(updateBufferIndex),
848                       sizeof(Vector2),
849                       dst + static_cast<uint32_t>(sizeof(Vector2)) * arrayIndex);
850             break;
851           }
852           case Property::Type::VECTOR3:
853           {
854             ubo.Write(&(*iter).propertyValue->GetVector3(updateBufferIndex),
855                       sizeof(Vector3),
856                       dst + static_cast<uint32_t>(sizeof(Vector3)) * arrayIndex);
857             break;
858           }
859           case Property::Type::VECTOR4:
860           {
861             ubo.Write(&(*iter).propertyValue->GetVector4(updateBufferIndex),
862                       sizeof(Vector4),
863                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
864             break;
865           }
866           case Property::Type::MATRIX:
867           {
868             ubo.Write(&(*iter).propertyValue->GetMatrix(updateBufferIndex),
869                       sizeof(Matrix),
870                       dst + static_cast<uint32_t>(sizeof(Matrix)) * arrayIndex);
871             break;
872           }
873           case Property::Type::MATRIX3:
874           {
875             // todo: handle data padding properly
876             // Vulkan:
877             //
878             //const auto& matrix = &(*iter).propertyValue->GetMatrix3(updateBufferIndex);
879             //for(int i = 0; i < 3; ++i)
880             //{
881             //ubo.Write(&matrix->AsFloat()[i * 3],
882             //          sizeof(float) * 3,
883             //          dst + (i * static_cast<uint32_t>(sizeof(Vector4))));
884             //}
885             // GL:
886             ubo.Write(&(*iter).propertyValue->GetMatrix3(updateBufferIndex),
887                       sizeof(Matrix3),
888                       dst + static_cast<uint32_t>(sizeof(Matrix3)) * arrayIndex);
889             break;
890           }
891           default:
892           {
893           }
894         }
895       }
896     }
897   }
898   // write output bindings
899   outBindings = &mUniformBufferBindings;
900
901   // Update offset
902   offset = dataOffset;
903 }
904
905 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
906 {
907   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
908   sortAttributes.geometry = mGeometry;
909 }
910
911 void Renderer::SetShaderChanged(bool value)
912 {
913   mShaderChanged = value;
914 }
915
916 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
917 {
918   if(mUpdated)
919   {
920     mUpdated = false;
921     return true;
922   }
923
924   if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
925   {
926     return true;
927   }
928
929   for(const auto& texture : mRenderDataProvider->GetTextures())
930   {
931     if(texture && texture->IsNativeImage())
932     {
933       return true;
934     }
935   }
936
937   uint64_t                               hash           = 0xc70f6907UL;
938   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
939   for(const auto& uniformProperty : uniformMapNode)
940   {
941     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
942   }
943
944   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
945   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
946   for(const auto& uniformProperty : uniformMap)
947   {
948     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
949   }
950
951   if(mUniformsHash != hash)
952   {
953     mUniformsHash = hash;
954     return true;
955   }
956
957   return false;
958 }
959
960 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
961   Program&                                             program,
962   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
963   const SceneGraph::NodeDataProvider&                  node,
964   bool                                                 blend)
965 {
966   Graphics::InputAssemblyState inputAssemblyState{};
967   Graphics::VertexInputState   vertexInputState{};
968   Graphics::ProgramState       programState{};
969   uint32_t                     bindingIndex{0u};
970
971   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
972   {
973     mAttributeLocations.Clear();
974     mUpdateAttributeLocations = true;
975   }
976
977   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
978
979   /**
980    * Bind Attributes
981    */
982   uint32_t base = 0;
983   for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
984   {
985     const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
986
987     vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
988                                                  Graphics::VertexInputRate::PER_VERTEX);
989
990     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
991     for(uint32_t i = 0; i < attributeCount; ++i)
992     {
993       if(mUpdateAttributeLocations)
994       {
995         auto    attributeName = vertexBuffer->GetAttributeName(i);
996         int32_t pLocation     = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
997         if(-1 == pLocation)
998         {
999           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
1000         }
1001         mAttributeLocations.PushBack(pLocation);
1002       }
1003
1004       auto location = static_cast<uint32_t>(mAttributeLocations[base + i]);
1005
1006       vertexInputState.attributes.emplace_back(location,
1007                                                bindingIndex,
1008                                                vertexFormat.components[i].offset,
1009                                                GetPropertyVertexFormat(vertexFormat.components[i].type));
1010     }
1011     base += attributeCount;
1012     ++bindingIndex;
1013   }
1014   mUpdateAttributeLocations = false;
1015
1016   // Get the topology
1017   inputAssemblyState.SetTopology(mGeometry->GetTopology());
1018
1019   // Get the program
1020   programState.SetProgram(program.GetGraphicsProgram());
1021
1022   Graphics::RasterizationState rasterizationState{};
1023
1024   //Set cull face  mode
1025   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
1026   if(cam->GetReflectionUsed())
1027   {
1028     auto adjFaceCullingMode = mFaceCullingMode;
1029     switch(mFaceCullingMode)
1030     {
1031       case FaceCullingMode::Type::FRONT:
1032       {
1033         adjFaceCullingMode = FaceCullingMode::Type::BACK;
1034         break;
1035       }
1036       case FaceCullingMode::Type::BACK:
1037       {
1038         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
1039         break;
1040       }
1041       default:
1042       {
1043         // nothing to do, leave culling as it is
1044       }
1045     }
1046     rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
1047   }
1048   else
1049   {
1050     rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
1051   }
1052
1053   rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
1054
1055   /**
1056    * Set Polygon mode
1057    */
1058   switch(mGeometry->GetTopology())
1059   {
1060     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
1061     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
1062     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
1063       rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
1064       break;
1065     case Graphics::PrimitiveTopology::LINE_LIST:
1066     case Graphics::PrimitiveTopology::LINE_LOOP:
1067     case Graphics::PrimitiveTopology::LINE_STRIP:
1068       rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
1069       break;
1070     case Graphics::PrimitiveTopology::POINT_LIST:
1071       rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
1072       break;
1073   }
1074
1075   // @todo Add blend barrier to the Graphics API if we are using advanced
1076   // blending options. Command?
1077
1078   Graphics::ColorBlendState colorBlendState{};
1079   colorBlendState.SetBlendEnable(false);
1080
1081   if(blend)
1082   {
1083     colorBlendState.SetBlendEnable(true);
1084
1085     Graphics::BlendOp rgbOp   = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1086     Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1087     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipliedAlphaEnabled)
1088     {
1089       if(rgbOp != alphaOp)
1090       {
1091         DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1092         alphaOp = rgbOp;
1093       }
1094     }
1095
1096     colorBlendState
1097       .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1098       .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1099       .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1100       .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1101       .SetColorBlendOp(rgbOp)
1102       .SetAlphaBlendOp(alphaOp);
1103
1104     // Blend color is optional and rarely used
1105     auto* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1106     if(blendColor)
1107     {
1108       colorBlendState.SetBlendConstants(blendColor->AsFloat());
1109     }
1110   }
1111
1112   mUpdated = true;
1113
1114   // Create the pipeline
1115   Graphics::PipelineCreateInfo createInfo;
1116   createInfo
1117     .SetInputAssemblyState(&inputAssemblyState)
1118     .SetVertexInputState(&vertexInputState)
1119     .SetRasterizationState(&rasterizationState)
1120     .SetColorBlendState(&colorBlendState)
1121     .SetProgramState(&programState);
1122
1123   // Store a pipeline per renderer per render (renderer can be owned by multiple nodes,
1124   // and re-drawn in multiple instructions).
1125   // @todo This is only needed because ColorBlend state can change. Fixme!
1126   // This is ameliorated by the fact that implementation caches pipelines, and we're only storing
1127   // handles.
1128   auto            hash           = HashedPipeline::GetHash(&node, &instruction, blend);
1129   HashedPipeline* hashedPipeline = nullptr;
1130   for(auto& element : mGraphicsPipelines)
1131   {
1132     if(element.mHash == hash)
1133     {
1134       hashedPipeline = &element;
1135       break;
1136     }
1137   }
1138
1139   if(hashedPipeline != nullptr)
1140   {
1141     hashedPipeline->mGraphicsPipeline = mGraphicsController->CreatePipeline(
1142       createInfo,
1143       std::move(hashedPipeline->mGraphicsPipeline));
1144   }
1145   else
1146   {
1147     mGraphicsPipelines.emplace_back();
1148     mGraphicsPipelines.back().mHash             = hash;
1149     mGraphicsPipelines.back().mGraphicsPipeline = mGraphicsController->CreatePipeline(createInfo, nullptr);
1150     hashedPipeline                              = &mGraphicsPipelines.back();
1151   }
1152   return *hashedPipeline->mGraphicsPipeline.get();
1153 }
1154
1155 } // namespace Render
1156
1157 } // namespace Internal
1158
1159 } // namespace Dali