From 9555b0941f409b419f996f37b166b2862f97fdb3 Mon Sep 17 00:00:00 2001 From: Adam Bialogonski Date: Fri, 25 Jun 2021 15:18:57 +0100 Subject: [PATCH] Simplified uniform write Change-Id: I9e9871ccdc9a18c7624ce97ef9611cdf072bd58c --- dali/internal/render/renderers/render-renderer.cpp | 164 ++++++++++----------- dali/internal/render/shaders/program.cpp | 19 +++ dali/internal/render/shaders/program.h | 21 +++ 3 files changed, 117 insertions(+), 87 deletions(-) diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp index 27b19ed..6677d91 100644 --- a/dali/internal/render/renderers/render-renderer.cpp +++ b/dali/internal/render/renderers/render-renderer.cpp @@ -39,6 +39,74 @@ namespace Dali::Internal { namespace { +// Helper to get the property value getter by type +typedef const float&(PropertyInputImpl::*FuncGetter )(BufferIndex) const; +constexpr FuncGetter GetPropertyValueGetter(Property::Type type) +{ + switch(type) + { + case Property::BOOLEAN: + { + return FuncGetter(&PropertyInputImpl::GetBoolean); + } + case Property::INTEGER: + { + return FuncGetter(&PropertyInputImpl::GetInteger); + } + case Property::FLOAT: + { + return FuncGetter(&PropertyInputImpl::GetFloat); + } + case Property::VECTOR2: + { + return FuncGetter(&PropertyInputImpl::GetVector2); + } + case Property::VECTOR3: + { + return FuncGetter(&PropertyInputImpl::GetVector3); + } + case Property::VECTOR4: + { + return FuncGetter(&PropertyInputImpl::GetVector4); + } + case Property::MATRIX3: + { + return FuncGetter(&PropertyInputImpl::GetMatrix3); + } + case Property::MATRIX: + { + return FuncGetter(&PropertyInputImpl::GetMatrix); + } + default: + { + return nullptr; + } + } +} + +/** + * Helper function that returns size of uniform datatypes based + * on property type. + */ +constexpr int GetPropertyValueSizeForUniform( Property::Type type ) +{ + switch(type) + { + case Property::Type::BOOLEAN:{ return sizeof(bool);} + case Property::Type::FLOAT:{ return sizeof(float);} + case Property::Type::INTEGER:{ return sizeof(int);} + case Property::Type::VECTOR2:{ return sizeof(Vector2);} + case Property::Type::VECTOR3:{ return sizeof(Vector3);} + case Property::Type::VECTOR4:{ return sizeof(Vector4);} + case Property::Type::MATRIX3:{ return sizeof(Matrix3);} + case Property::Type::MATRIX:{ return sizeof(Matrix);} + default: + { + return 0; + } + }; +} + // Helper to get the vertex input format Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType) { @@ -663,20 +731,11 @@ void Renderer::WriteUniformBuffer( const Vector3& size) { // Create the UBO - uint32_t uniformBlockAllocationBytes{0u}; - uint32_t uniformBlockMaxSize{0u}; uint32_t uboOffset{0u}; - auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram()); - for(auto i = 0u; i < reflection.GetUniformBlockCount(); ++i) - { - auto blockSize = GetUniformBufferDataAlignment(reflection.GetUniformBlockSize(i)); - if(uniformBlockMaxSize < blockSize) - { - uniformBlockMaxSize = blockSize; - } - uniformBlockAllocationBytes += blockSize; - } + auto &reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram()); + + uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired; // Create uniform buffer view from uniform buffer Graphics::UniquePtr uboView{nullptr}; @@ -804,81 +863,12 @@ void Renderer::FillUniformBuffer(Program& p if(uniformFound) { auto dst = ubo.GetOffset() + uniformInfo.offset; - switch((*iter).propertyValue->GetType()) - { - case Property::Type::BOOLEAN: - { - ubo.Write(&(*iter).propertyValue->GetBoolean(updateBufferIndex), - sizeof(bool), - dst + static_cast(sizeof(bool)) * arrayIndex); - break; - } - case Property::Type::INTEGER: - { - ubo.Write(&(*iter).propertyValue->GetInteger(updateBufferIndex), - sizeof(int32_t), - dst + static_cast(sizeof(int32_t)) * arrayIndex); - break; - } - case Property::Type::FLOAT: - { - ubo.Write(&(*iter).propertyValue->GetFloat(updateBufferIndex), - sizeof(float), - dst + static_cast(sizeof(float)) * arrayIndex); - break; - } - case Property::Type::VECTOR2: - { - ubo.Write(&(*iter).propertyValue->GetVector2(updateBufferIndex), - sizeof(Vector2), - dst + static_cast(sizeof(Vector2)) * arrayIndex); - break; - } - case Property::Type::VECTOR3: - { - ubo.Write(&(*iter).propertyValue->GetVector3(updateBufferIndex), - sizeof(Vector3), - dst + static_cast(sizeof(Vector3)) * arrayIndex); - break; - } - case Property::Type::VECTOR4: - { - ubo.Write(&(*iter).propertyValue->GetVector4(updateBufferIndex), - sizeof(Vector4), - dst + static_cast(sizeof(Vector4)) * arrayIndex); - break; - } - case Property::Type::MATRIX: - { - ubo.Write(&(*iter).propertyValue->GetMatrix(updateBufferIndex), - sizeof(Matrix), - dst + static_cast(sizeof(Matrix)) * arrayIndex); - break; - } - case Property::Type::MATRIX3: - { - // @todo: handle data padding properly - // Get padding requirement from Graphics - // - // Vulkan: - // - //const auto& matrix = &(*iter).propertyValue->GetMatrix3(updateBufferIndex); - //for(int i = 0; i < 3; ++i) - //{ - //ubo.Write(&matrix->AsFloat()[i * 3], - // sizeof(float) * 3, - // dst + (i * static_cast(sizeof(Vector4)))); - //} - // GL: - ubo.Write(&(*iter).propertyValue->GetMatrix3(updateBufferIndex), - sizeof(Matrix3), - dst + static_cast(sizeof(Matrix3)) * arrayIndex); - break; - } - default: - { - } - } + const auto typeSize = GetPropertyValueSizeForUniform( (*iter).propertyValue->GetType() ); + const auto dest = dst + static_cast(typeSize) * arrayIndex; + const auto func = GetPropertyValueGetter((*iter).propertyValue->GetType()); + ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex), + typeSize, + dest); } } } diff --git a/dali/internal/render/shaders/program.cpp b/dali/internal/render/shaders/program.cpp index db7c711..3a3c8e6 100644 --- a/dali/internal/render/shaders/program.cpp +++ b/dali/internal/render/shaders/program.cpp @@ -58,6 +58,16 @@ size_t DEFAULT_UNIFORM_HASHTABLE[NUMBER_OF_DEFAULT_UNIFORMS] = CalculateHash(std::string("uSize")), CalculateHash(std::string("uColor"))}; +/** + * Helper function to calculate the correct alignment of data for uniform buffers + * @param dataSize size of uniform buffer + * @return aligned offset of data + */ +inline uint32_t GetUniformBufferDataAlignment(uint32_t dataSize) +{ + return ((dataSize / 256u) + ((dataSize % 256u) ? 1u : 0u)) * 256u; +} + } // namespace // IMPLEMENTATION @@ -162,6 +172,15 @@ void Program::BuildReflection(const Graphics::Reflection& graphicsReflection) item.hasCollision = hashTest[item.hashValue]; } } + + // Calculate size of memory for uniform blocks + mUniformBlockRequirements.totalSizeRequired = 0; + mUniformBlockRequirements.blockCount = graphicsReflection.GetUniformBlockCount(); + for (auto i = 0u; i < mUniformBlockRequirements.blockCount; ++i) + { + auto blockSize = GetUniformBufferDataAlignment(graphicsReflection.GetUniformBlockSize(i)); + mUniformBlockRequirements.totalSizeRequired += blockSize; + } } bool Program::GetUniform(const std::string& name, size_t hashedName, Graphics::UniformInfo& out) const diff --git a/dali/internal/render/shaders/program.h b/dali/internal/render/shaders/program.h index 9802982..05a6e70 100644 --- a/dali/internal/render/shaders/program.h +++ b/dali/internal/render/shaders/program.h @@ -178,6 +178,26 @@ public: */ void BuildReflection(const Graphics::Reflection& graphicsReflection); + /** + * Struct UniformBlockMemoryRequirements + * Contains details of a uniform blocks memory requirements + */ + struct UniformBlockMemoryRequirements + { + uint32_t blockCount; + uint32_t totalSizeRequired; + }; + + /** + * Retrieves uniform blocks requirements + * + * @return Reference to the valid UniformBlockMemoryRequirements struct + */ + [[nodiscard]] const UniformBlockMemoryRequirements& GetUniformBlocksMemoryRequirements() const + { + return mUniformBlockRequirements; + } + private: // Data ProgramCache& mCache; ///< The program cache const Matrix* mProjectionMatrix; ///< currently set projection matrix @@ -194,6 +214,7 @@ private: // Data UniformReflectionContainer mReflection{}; ///< Contains reflection build per program UniformReflectionContainer mReflectionDefaultUniforms{}; ///< Contains default uniforms + UniformBlockMemoryRequirements mUniformBlockRequirements{}; ///< Memory requirements for uniform blocks }; } // namespace Internal -- 2.7.4