Merge "Fixed an issue the triple tap did not work." into devel/master
[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/shaders/program.h>
33 #include <dali/internal/render/shaders/render-shader.h>
34 #include <dali/internal/update/common/uniform-map.h>
35 #include <dali/internal/render/renderers/uniform-buffer-view.h>
36 #include <dali/internal/render/renderers/uniform-buffer-view-pool.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
649 void Renderer::WriteUniformBuffer(
650   BufferIndex                          bufferIndex,
651   Graphics::CommandBuffer&             commandBuffer,
652   Program*                             program,
653   const SceneGraph::RenderInstruction& instruction,
654   const SceneGraph::NodeDataProvider&  node,
655   const Matrix&                        modelMatrix,
656   const Matrix&                        modelViewMatrix,
657   const Matrix&                        viewMatrix,
658   const Matrix&                        projectionMatrix,
659   const Vector3&                       size)
660 {
661   // Create the UBO
662   uint32_t uniformBlockAllocationBytes{0u};
663   uint32_t uniformBlockMaxSize{0u};
664   uint32_t uboOffset{0u};
665
666   auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
667   for(auto i = 0u; i < reflection.GetUniformBlockCount(); ++i)
668   {
669     auto blockSize = GetUniformBufferDataAlignment(reflection.GetUniformBlockSize(i));
670     if(uniformBlockMaxSize < blockSize)
671     {
672       uniformBlockMaxSize = blockSize;
673     }
674     uniformBlockAllocationBytes += blockSize;
675   }
676
677   // Create uniform buffer view from uniform buffer
678   Graphics::UniquePtr<Render::UniformBufferView> uboView {nullptr};
679   if(uniformBlockAllocationBytes)
680   {
681     auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool( bufferIndex );
682
683     uboView = uboPoolView->CreateUniformBufferView( uniformBlockAllocationBytes );
684   }
685
686   // update the uniform buffer
687   // pass shared UBO and offset, return new offset for next item to be used
688   // don't process bindings if there are no uniform buffers allocated
689   if(uboView)
690   {
691     auto uboCount = reflection.GetUniformBlockCount();
692     mUniformBufferBindings.resize(uboCount);
693
694     std::vector<Graphics::UniformBufferBinding>* bindings{&mUniformBufferBindings};
695
696     mUniformBufferBindings[0].buffer = uboView->GetBuffer( &mUniformBufferBindings[0].offset );
697
698     // Write default uniforms
699     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, *bindings, modelMatrix);
700     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, *bindings, viewMatrix);
701     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, *bindings, projectionMatrix);
702     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, *bindings, modelViewMatrix);
703
704     auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX);
705     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
706     {
707       Matrix modelViewProjectionMatrix(false);
708       Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
709       WriteDefaultUniform(mvpUniformInfo, *uboView, *bindings, modelViewProjectionMatrix);
710     }
711
712     auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX);
713     if(normalUniformInfo && !normalUniformInfo->name.empty())
714     {
715       Matrix3 normalMatrix(modelViewMatrix);
716       normalMatrix.Invert();
717       normalMatrix.Transpose();
718       WriteDefaultUniform(normalUniformInfo, *uboView, *bindings, normalMatrix);
719     }
720
721     Vector4        finalColor;
722     const Vector4& color = node.GetRenderColor(bufferIndex);
723     if(mPremultipliedAlphaEnabled)
724     {
725       float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
726       finalColor  = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha);
727     }
728     else
729     {
730       finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
731     }
732     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, *bindings, finalColor);
733
734     // Write uniforms from the uniform map
735     FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex);
736
737     // Write uSize in the end, as it shouldn't be overridable by dynamic properties.
738     WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, *bindings, size);
739
740     commandBuffer.BindUniformBuffers(*bindings);
741   }
742 }
743
744 template<class T>
745 bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const T& data)
746 {
747   if(uniformInfo && !uniformInfo->name.empty())
748   {
749     WriteUniform(ubo, bindings, *uniformInfo, data);
750     return true;
751   }
752   return false;
753 }
754
755 template<class T>
756 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const T& data)
757 {
758   WriteUniform(ubo, bindings, uniformInfo, &data, sizeof(T));
759 }
760
761 void Renderer::WriteUniform(Render::UniformBufferView& ubo, const std::vector<Graphics::UniformBufferBinding>& bindings, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size)
762 {
763   ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset);
764 }
765
766 void Renderer::FillUniformBuffer(Program&                                      program,
767                                  const SceneGraph::RenderInstruction&          instruction,
768                                  Render::UniformBufferView&                    ubo,
769                                  std::vector<Graphics::UniformBufferBinding>*& outBindings,
770                                  uint32_t&                                     offset,
771                                  BufferIndex                                   updateBufferIndex)
772 {
773   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
774   auto  uboCount   = reflection.GetUniformBlockCount();
775
776   // Setup bindings
777   uint32_t dataOffset = offset;
778   for(auto i = 0u; i < uboCount; ++i)
779   {
780     mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i);
781     mUniformBufferBindings[i].binding  = reflection.GetUniformBlockBinding(i);
782
783     dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize);
784     mUniformBufferBindings[i].buffer = ubo.GetBuffer( &mUniformBufferBindings[i].offset );
785
786     for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
787                                        end  = mUniformIndexMap.End();
788         iter != end;
789         ++iter)
790     {
791       // @todo This means parsing the uniform string every frame. Instead, store the array index if present.
792       int arrayIndex = (*iter).arrayIndex;
793
794       auto uniformInfo  = Graphics::UniformInfo{};
795       auto uniformFound = program.GetUniform((*iter).uniformName.GetCString(),
796                                              (*iter).uniformNameHashNoArray ? (*iter).uniformNameHashNoArray
797                                                                             : (*iter).uniformNameHash,
798                                              uniformInfo);
799
800       if(uniformFound)
801       {
802         auto dst = ubo.GetOffset() + uniformInfo.offset;
803         switch((*iter).propertyValue->GetType())
804         {
805           case Property::Type::BOOLEAN:
806           {
807             ubo.Write(&(*iter).propertyValue->GetBoolean(updateBufferIndex),
808                       sizeof(bool),
809                       dst + static_cast<uint32_t>(sizeof(bool)) * arrayIndex);
810             break;
811           }
812           case Property::Type::INTEGER:
813           {
814             ubo.Write(&(*iter).propertyValue->GetInteger(updateBufferIndex),
815                       sizeof(int32_t),
816                       dst + static_cast<int32_t>(sizeof(int32_t)) * arrayIndex);
817             break;
818           }
819           case Property::Type::FLOAT:
820           {
821             ubo.Write(&(*iter).propertyValue->GetFloat(updateBufferIndex),
822                       sizeof(float),
823                       dst + static_cast<uint32_t>(sizeof(float)) * arrayIndex);
824             break;
825           }
826           case Property::Type::VECTOR2:
827           {
828             ubo.Write(&(*iter).propertyValue->GetVector2(updateBufferIndex),
829                       sizeof(Vector2),
830                       dst + static_cast<uint32_t>(sizeof(Vector2)) * arrayIndex);
831             break;
832           }
833           case Property::Type::VECTOR3:
834           {
835             ubo.Write(&(*iter).propertyValue->GetVector3(updateBufferIndex),
836                       sizeof(Vector3),
837                       dst + static_cast<uint32_t>(sizeof(Vector3)) * arrayIndex);
838             break;
839           }
840           case Property::Type::VECTOR4:
841           {
842             ubo.Write(&(*iter).propertyValue->GetVector4(updateBufferIndex),
843                       sizeof(Vector4),
844                       dst + static_cast<uint32_t>(sizeof(Vector4)) * arrayIndex);
845             break;
846           }
847           case Property::Type::MATRIX:
848           {
849             ubo.Write(&(*iter).propertyValue->GetMatrix(updateBufferIndex),
850                       sizeof(Matrix),
851                       dst + static_cast<uint32_t>(sizeof(Matrix)) * arrayIndex);
852             break;
853           }
854           case Property::Type::MATRIX3:
855           {
856             // todo: handle data padding properly
857             // Vulkan:
858             //
859             //const auto& matrix = &(*iter).propertyValue->GetMatrix3(updateBufferIndex);
860             //for(int i = 0; i < 3; ++i)
861             //{
862             //ubo.Write(&matrix->AsFloat()[i * 3],
863             //          sizeof(float) * 3,
864             //          dst + (i * static_cast<uint32_t>(sizeof(Vector4))));
865             //}
866             // GL:
867             ubo.Write(&(*iter).propertyValue->GetMatrix3(updateBufferIndex),
868                       sizeof(Matrix3),
869                       dst + static_cast<uint32_t>(sizeof(Matrix3)) * arrayIndex);
870             break;
871           }
872           default:
873           {
874           }
875         }
876       }
877     }
878   }
879   // write output bindings
880   outBindings = &mUniformBufferBindings;
881
882   // Update offset
883   offset = dataOffset;
884 }
885
886 void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
887 {
888   sortAttributes.shader   = &(mRenderDataProvider->GetShader());
889   sortAttributes.geometry = mGeometry;
890 }
891
892 void Renderer::SetShaderChanged(bool value)
893 {
894   mShaderChanged = value;
895 }
896
897 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
898 {
899   if(mUpdated)
900   {
901     mUpdated = false;
902     return true;
903   }
904
905   if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
906   {
907     return true;
908   }
909
910   for(const auto& texture : mRenderDataProvider->GetTextures())
911   {
912     if(texture && texture->IsNativeImage())
913     {
914       return true;
915     }
916   }
917
918   uint64_t                               hash           = 0xc70f6907UL;
919   const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
920   for(const auto& uniformProperty : uniformMapNode)
921   {
922     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
923   }
924
925   const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
926   const SceneGraph::CollectedUniformMap&    uniformMap             = uniformMapDataProvider.GetUniformMap(bufferIndex);
927   for(const auto& uniformProperty : uniformMap)
928   {
929     hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
930   }
931
932   if(mUniformsHash != hash)
933   {
934     mUniformsHash = hash;
935     return true;
936   }
937
938   return false;
939 }
940
941 Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
942   Program&                                             program,
943   const Dali::Internal::SceneGraph::RenderInstruction& instruction,
944   const SceneGraph::NodeDataProvider&                  node,
945   bool                                                 blend)
946 {
947   Graphics::InputAssemblyState inputAssemblyState{};
948   Graphics::VertexInputState   vertexInputState{};
949   Graphics::ProgramState       programState{};
950   uint32_t                     bindingIndex{0u};
951
952   if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
953   {
954     mAttributeLocations.Clear();
955     mUpdateAttributeLocations = true;
956   }
957
958   auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
959
960   /**
961    * Bind Attributes
962    */
963   uint32_t base = 0;
964   for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
965   {
966     const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
967
968     vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
969                                                  Graphics::VertexInputRate::PER_VERTEX);
970
971     const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
972     for(uint32_t i = 0; i < attributeCount; ++i)
973     {
974       if(mUpdateAttributeLocations)
975       {
976         auto    attributeName = vertexBuffer->GetAttributeName(i);
977         int32_t pLocation     = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
978         if(-1 == pLocation)
979         {
980           DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
981         }
982         mAttributeLocations.PushBack(pLocation);
983       }
984
985       auto location = static_cast<uint32_t>(mAttributeLocations[base + i]);
986
987       vertexInputState.attributes.emplace_back(location,
988                                                bindingIndex,
989                                                vertexFormat.components[i].offset,
990                                                GetPropertyVertexFormat(vertexFormat.components[i].type));
991     }
992     base += attributeCount;
993     ++bindingIndex;
994   }
995   mUpdateAttributeLocations = false;
996
997   // Get the topology
998   inputAssemblyState.SetTopology(mGeometry->GetTopology());
999
1000   // Get the program
1001   programState.SetProgram(program.GetGraphicsProgram());
1002
1003   Graphics::RasterizationState rasterizationState{};
1004
1005   //Set cull face  mode
1006   const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
1007   if(cam->GetReflectionUsed())
1008   {
1009     auto adjFaceCullingMode = mFaceCullingMode;
1010     switch(mFaceCullingMode)
1011     {
1012       case FaceCullingMode::Type::FRONT:
1013       {
1014         adjFaceCullingMode = FaceCullingMode::Type::BACK;
1015         break;
1016       }
1017       case FaceCullingMode::Type::BACK:
1018       {
1019         adjFaceCullingMode = FaceCullingMode::Type::FRONT;
1020         break;
1021       }
1022       default:
1023       {
1024         // nothing to do, leave culling as it is
1025       }
1026     }
1027     rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
1028   }
1029   else
1030   {
1031     rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
1032   }
1033
1034   rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
1035
1036   /**
1037    * Set Polygon mode
1038    */
1039   switch(mGeometry->GetTopology())
1040   {
1041     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
1042     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
1043     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
1044       rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
1045       break;
1046     case Graphics::PrimitiveTopology::LINE_LIST:
1047     case Graphics::PrimitiveTopology::LINE_LOOP:
1048     case Graphics::PrimitiveTopology::LINE_STRIP:
1049       rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
1050       break;
1051     case Graphics::PrimitiveTopology::POINT_LIST:
1052       rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
1053       break;
1054   }
1055
1056   // @todo Add blend barrier to the Graphics API if we are using advanced
1057   // blending options. Command?
1058
1059   Graphics::ColorBlendState colorBlendState{};
1060   colorBlendState.SetBlendEnable(false);
1061
1062   if(blend)
1063   {
1064     colorBlendState.SetBlendEnable(true);
1065
1066     Graphics::BlendOp rgbOp   = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1067     Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1068     if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipliedAlphaEnabled)
1069     {
1070       if(rgbOp != alphaOp)
1071       {
1072         DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1073         alphaOp = rgbOp;
1074       }
1075     }
1076
1077     colorBlendState
1078       .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1079       .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1080       .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1081       .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1082       .SetColorBlendOp(rgbOp)
1083       .SetAlphaBlendOp(alphaOp);
1084
1085     // Blend color is optional and rarely used
1086     auto* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1087     if(blendColor)
1088     {
1089       colorBlendState.SetBlendConstants(blendColor->AsFloat());
1090     }
1091   }
1092
1093   mUpdated = true;
1094
1095   // Create the pipeline
1096   Graphics::PipelineCreateInfo createInfo;
1097   createInfo
1098     .SetInputAssemblyState(&inputAssemblyState)
1099     .SetVertexInputState(&vertexInputState)
1100     .SetRasterizationState(&rasterizationState)
1101     .SetColorBlendState(&colorBlendState)
1102     .SetProgramState(&programState);
1103
1104   // Store a pipeline per renderer per render (renderer can be owned by multiple nodes,
1105   // and re-drawn in multiple instructions).
1106   // @todo This is only needed because ColorBlend state can change. Fixme!
1107   // This is ameliorated by the fact that implementation caches pipelines, and we're only storing
1108   // handles.
1109   auto            hash           = HashedPipeline::GetHash(&node, &instruction, blend);
1110   HashedPipeline* hashedPipeline = nullptr;
1111   for(auto& element : mGraphicsPipelines)
1112   {
1113     if(element.mHash == hash)
1114     {
1115       hashedPipeline = &element;
1116       break;
1117     }
1118   }
1119
1120   if(hashedPipeline != nullptr)
1121   {
1122     hashedPipeline->mGraphicsPipeline = mGraphicsController->CreatePipeline(
1123       createInfo,
1124       std::move(hashedPipeline->mGraphicsPipeline));
1125   }
1126   else
1127   {
1128     mGraphicsPipelines.emplace_back();
1129     mGraphicsPipelines.back().mHash             = hash;
1130     mGraphicsPipelines.back().mGraphicsPipeline = mGraphicsController->CreatePipeline(createInfo, nullptr);
1131     hashedPipeline                              = &mGraphicsPipelines.back();
1132   }
1133   return *hashedPipeline->mGraphicsPipeline.get();
1134 }
1135
1136 } // namespace Render
1137
1138 } // namespace Dali