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