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