Fix INTEGER_OVERFLOW coverity issues
[platform/core/uifw/dali-core.git] / dali / internal / render / shaders / program.cpp
index 4cfbcb4..c149767 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
 #include <dali/integration-api/debug.h>
 #include <dali/internal/common/shader-data.h>
 #include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/renderers/uniform-buffer-manager.h>
 #include <dali/internal/render/shaders/program-cache.h>
 #include <dali/public-api/common/constants.h>
 #include <dali/public-api/common/dali-common.h>
@@ -55,6 +56,7 @@ size_t DEFAULT_UNIFORM_HASHTABLE[NUMBER_OF_DEFAULT_UNIFORMS] =
     CalculateHash(std::string("uModelView")),
     CalculateHash(std::string("uNormalMatrix")),
     CalculateHash(std::string("uProjection")),
+    CalculateHash(std::string("uScale")),
     CalculateHash(std::string("uSize")),
     CalculateHash(std::string("uColor")),
     CalculateHash(std::string("uActorColor"))};
@@ -62,18 +64,18 @@ size_t DEFAULT_UNIFORM_HASHTABLE[NUMBER_OF_DEFAULT_UNIFORMS] =
 /**
  * Helper function to calculate the correct alignment of data for uniform buffers
  * @param dataSize size of uniform buffer
- * @return aligned offset of data
+ * @return size of data aligned to given size
  */
-inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize)
+inline uint32_t AlignSize(uint32_t dataSize, uint32_t alignSize)
 {
-  return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u;
+  return ((dataSize / alignSize) + ((dataSize % alignSize) ? 1u : 0u)) * alignSize;
 }
 
 } // namespace
 
 // IMPLEMENTATION
 
-Program* Program::New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController)
+Program* Program::New(ProgramCache& cache, const Internal::ShaderDataPtr& shaderData, Graphics::Controller& gfxController)
 {
   size_t shaderHash = shaderData->GetHashValue();
 
@@ -83,6 +85,8 @@ Program* Program::New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, G
   {
     // program not found so create it
     program = new Program(cache, shaderData, gfxController);
+
+    DALI_LOG_INFO(Debug::Filter::gShader, Debug::Verbose, "Program::New() created a unique program:\n  VertexShader:\n%s\n\n  FragShader:\n%s\n", shaderData->GetVertexShader(), shaderData->GetFragmentShader());
     cache.AddProgram(shaderHash, program);
   }
 
@@ -91,17 +95,15 @@ Program* Program::New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, G
 
 Program::Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& controller)
 : mCache(cache),
-  mProjectionMatrix(nullptr),
-  mViewMatrix(nullptr),
   mGfxProgram(nullptr),
   mGfxController(controller),
-  mProgramData(shaderData)
+  mProgramData(std::move(shaderData))
 {
 }
 
 Program::~Program() = default;
 
-void Program::BuildReflection(const Graphics::Reflection& graphicsReflection)
+void Program::BuildReflection(const Graphics::Reflection& graphicsReflection, Render::UniformBufferManager& uniformBufferManager)
 {
   mReflectionDefaultUniforms.clear();
   mReflectionDefaultUniforms.resize(NUMBER_OF_DEFAULT_UNIFORMS);
@@ -143,7 +145,7 @@ void Program::BuildReflection(const Graphics::Reflection& graphicsReflection)
   }
 
   // add samplers
-  auto samplers = graphicsReflection.GetSamplers();
+  auto samplers = graphicsReflection.GetSamplers(); // Only holds first element of arrays without [].
   for(const auto& sampler : samplers)
   {
     mReflection.emplace_back(ReflectionUniformInfo{CalculateHash(sampler.name), false, sampler});
@@ -174,20 +176,36 @@ void Program::BuildReflection(const Graphics::Reflection& graphicsReflection)
     }
   }
 
-  // Calculate size of memory for uniform blocks
-  mUniformBlockRequirements.totalSizeRequired = 0;
-  mUniformBlockRequirements.blockCount        = graphicsReflection.GetUniformBlockCount();
-  for(auto i = 0u; i < mUniformBlockRequirements.blockCount; ++i)
+  mUniformBlockMemoryRequirements.blockSize.resize(uniformBlockCount);
+  mUniformBlockMemoryRequirements.blockSizeAligned.resize(uniformBlockCount);
+  mUniformBlockMemoryRequirements.blockCount           = uniformBlockCount;
+  mUniformBlockMemoryRequirements.totalSizeRequired    = 0u;
+  mUniformBlockMemoryRequirements.totalCpuSizeRequired = 0u;
+  mUniformBlockMemoryRequirements.totalGpuSizeRequired = 0u;
+
+  for(auto i = 0u; i < uniformBlockCount; ++i)
   {
-    auto blockSize = GetUniformBufferDataAlignment(graphicsReflection.GetUniformBlockSize(i));
-    mUniformBlockRequirements.totalSizeRequired += blockSize;
+    Graphics::UniformBlockInfo uboInfo;
+    graphicsReflection.GetUniformBlock(i, uboInfo);
+    bool standaloneUniformBlock = (i == 0);
+
+    auto     blockSize        = graphicsReflection.GetUniformBlockSize(i);
+    uint32_t blockAlignment   = uniformBufferManager.GetUniformBlockAlignment(standaloneUniformBlock);
+    auto     alignedBlockSize = AlignSize(blockSize, blockAlignment);
+
+    mUniformBlockMemoryRequirements.blockSize[i]        = blockSize;
+    mUniformBlockMemoryRequirements.blockSizeAligned[i] = alignedBlockSize;
+
+    mUniformBlockMemoryRequirements.totalSizeRequired += alignedBlockSize;
+    mUniformBlockMemoryRequirements.totalCpuSizeRequired += (standaloneUniformBlock) ? alignedBlockSize : 0;
+    mUniformBlockMemoryRequirements.totalGpuSizeRequired += (standaloneUniformBlock) ? 0 : alignedBlockSize;
   }
 }
 
-void Program::SetGraphicsProgram(Graphics::UniquePtr<Graphics::Program>&& program)
+void Program::SetGraphicsProgram(Graphics::UniquePtr<Graphics::Program>&& program, Render::UniformBufferManager& uniformBufferManager)
 {
   mGfxProgram = std::move(program);
-  BuildReflection(mGfxController.GetProgramReflection(*mGfxProgram.get()));
+  BuildReflection(mGfxController.GetProgramReflection(*mGfxProgram.get()), uniformBufferManager);
 }
 
 bool Program::GetUniform(const std::string_view& name, Hash hashedName, Hash hashedNameNoArray, Graphics::UniformInfo& out) const
@@ -207,11 +225,17 @@ bool Program::GetUniform(const std::string_view& name, Hash hashedName, Hash has
   Hash             hash  = hashedName;
   std::string_view match = name;
 
+  int arrayIndex = 0;
+
   if(!name.empty() && name.back() == ']')
   {
-    hash     = hashedNameNoArray;
     auto pos = name.rfind("[");
-    match    = name.substr(0, pos - 1); // Remove subscript
+    if(pos != std::string::npos)
+    {
+      hash       = hashedNameNoArray;
+      match      = name.substr(0, pos); // Remove subscript
+      arrayIndex = atoi(&name[pos + 1]);
+    }
   }
 
   for(const ReflectionUniformInfo& item : mReflection)
@@ -221,6 +245,16 @@ bool Program::GetUniform(const std::string_view& name, Hash hashedName, Hash has
       if(!item.hasCollision || item.uniformInfo.name == match)
       {
         out = item.uniformInfo;
+
+        // Array out of bounds
+        if(item.uniformInfo.elementCount > 0 && arrayIndex >= int(item.uniformInfo.elementCount))
+        {
+          DALI_LOG_ERROR("Uniform %s, array index out of bound [%d >= %d]!\n",
+                         item.uniformInfo.name.c_str(),
+                         int(arrayIndex),
+                         int(item.uniformInfo.elementCount));
+          return false;
+        }
         return true;
       }
       else