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