X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Frenderers%2Frender-renderer.cpp;h=6681a5413deb2e545fa25f916ef387b32c3ae40f;hb=54b75aaa551d5b39fe4a361516737def605cd2d0;hp=1ffc12f8fb334ecc5fff0aa9c113f80f7a96c4a2;hpb=a05fa34fccfbb3382ceb9e85062b7686b09e98d0;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp index 1ffc12f..6681a54 100644 --- a/dali/internal/render/renderers/render-renderer.cpp +++ b/dali/internal/render/renderers/render-renderer.cpp @@ -19,84 +19,103 @@ #include // INTERNAL INCLUDES +#include +#include #include #include #include #include -#include #include #include +#include +#include +#include +#include #include -#include +#include +#include +#include -namespace Dali -{ -namespace Internal +namespace Dali::Internal { namespace { -/** - * Helper to set view and projection matrices once per program - * @param program to set the matrices to - * @param modelMatrix to set - * @param viewMatrix to set - * @param projectionMatrix to set - * @param modelViewMatrix to set - * @param modelViewProjectionMatrix to set - */ -inline void SetMatrices(Program& program, - const Matrix& modelMatrix, - const Matrix& viewMatrix, - const Matrix& projectionMatrix, - const Matrix& modelViewMatrix) -{ - GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX); - if(Program::UNIFORM_UNKNOWN != loc) - { - program.SetUniformMatrix4fv(loc, 1, modelMatrix.AsFloat()); - } - loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX); - if(Program::UNIFORM_UNKNOWN != loc) +// Helper to get the property value getter by type +typedef const float&(PropertyInputImpl::*FuncGetter )(BufferIndex) const; +constexpr FuncGetter GetPropertyValueGetter(Property::Type type) +{ + switch(type) { - if(program.GetViewMatrix() != &viewMatrix) + case Property::BOOLEAN: { - program.SetViewMatrix(&viewMatrix); - program.SetUniformMatrix4fv(loc, 1, viewMatrix.AsFloat()); + return FuncGetter(&PropertyInputImpl::GetBoolean); } - } - // set projection matrix if program has not yet received it this frame or if it is dirty - loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX); - if(Program::UNIFORM_UNKNOWN != loc) - { - if(program.GetProjectionMatrix() != &projectionMatrix) + case Property::INTEGER: { - program.SetProjectionMatrix(&projectionMatrix); - program.SetUniformMatrix4fv(loc, 1, projectionMatrix.AsFloat()); + 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; } } - loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX); - if(Program::UNIFORM_UNKNOWN != loc) - { - program.SetUniformMatrix4fv(loc, 1, modelViewMatrix.AsFloat()); - } +} - loc = program.GetUniformLocation(Program::UNIFORM_MVP_MATRIX); - if(Program::UNIFORM_UNKNOWN != loc) +/** + * Helper function that returns size of uniform datatypes based + * on property type. + */ +constexpr int GetPropertyValueSizeForUniform( Property::Type type ) +{ + switch(type) { - Matrix modelViewProjectionMatrix(false); - Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix); - program.SetUniformMatrix4fv(loc, 1, modelViewProjectionMatrix.AsFloat()); - } + 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; + } + }; +} - loc = program.GetUniformLocation(Program::UNIFORM_NORMAL_MATRIX); - if(Program::UNIFORM_UNKNOWN != loc) - { - Matrix3 normalMatrix; - normalMatrix = modelViewMatrix; - normalMatrix.Invert(); - normalMatrix.Transpose(); - program.SetUniformMatrix3fv(loc, 1, normalMatrix.AsFloat()); - } +/** + * 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 @@ -127,12 +146,11 @@ Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider, DepthTestMode::Type depthTestMode, DepthFunction::Type depthFunction, StencilParameters& stencilParameters) -: mRenderDataProvider(dataProvider), - mContext(nullptr), +: mGraphicsController(nullptr), + mRenderDataProvider(dataProvider), mGeometry(geometry), mProgramCache(nullptr), mUniformIndexMap(), - mAttributesLocation(), mUniformsHash(), mStencilParameters(stencilParameters), mBlendingOptions(), @@ -142,8 +160,7 @@ Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider, mFaceCullingMode(faceCullingMode), mDepthWriteMode(depthWriteMode), mDepthTestMode(depthTestMode), - mUpdateAttributesLocation(true), - mPremultipledAlphaEnabled(preMultipliedAlphaEnabled), + mPremultipliedAlphaEnabled(preMultipliedAlphaEnabled), mShaderChanged(false), mUpdated(true) { @@ -155,18 +172,21 @@ Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider, mBlendingOptions.SetBlendColor(blendColor); } -void Renderer::Initialize(Context& context, ProgramCache& programCache) +void Renderer::Initialize(Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache, Render::UniformBufferManager& uniformBufferManager, Render::PipelineCache& pipelineCache) { - mContext = &context; - mProgramCache = &programCache; + mGraphicsController = &graphicsController; + mProgramCache = &programCache; + mShaderCache = &shaderCache; + mUniformBufferManager = &uniformBufferManager; + mPipelineCache = &pipelineCache; } Renderer::~Renderer() = default; void Renderer::SetGeometry(Render::Geometry* geometry) { - mGeometry = geometry; - mUpdateAttributesLocation = true; + mGeometry = geometry; + mUpdated = true; } void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size) { @@ -174,220 +194,37 @@ void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size); } -void Renderer::SetBlending(Context& context, bool blend) -{ - context.SetBlend(blend); - if(blend) - { - // Blend color is optional and rarely used - const Vector4* blendColor = mBlendingOptions.GetBlendColor(); - if(blendColor) - { - context.SetCustomBlendColor(*blendColor); - } - else - { - context.SetDefaultBlendColor(); - } - - // Set blend source & destination factors - context.BlendFuncSeparate(mBlendingOptions.GetBlendSrcFactorRgb(), - mBlendingOptions.GetBlendDestFactorRgb(), - mBlendingOptions.GetBlendSrcFactorAlpha(), - mBlendingOptions.GetBlendDestFactorAlpha()); - - // Set blend equations - Dali::DevelBlendEquation::Type rgbEquation = mBlendingOptions.GetBlendEquationRgb(); - Dali::DevelBlendEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha(); - - if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled) - { - if(rgbEquation != alphaEquation) - { - DALI_LOG_ERROR("Advanced Blend Equation have to be appried by using BlendEquation.\n"); - } - context.BlendEquation(rgbEquation); - } - else - { - context.BlendEquationSeparate(rgbEquation, alphaEquation); - } - } - - mUpdated = true; -} - -void Renderer::GlContextDestroyed() +void Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer, Vector& boundTextures) { - mGeometry->GlContextDestroyed(); -} - -void Renderer::GlCleanup() -{ -} - -void Renderer::SetUniforms(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program) -{ - // Check if the map has changed - DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available"); - - const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap(); - - if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) || - node.GetUniformMapChanged(bufferIndex) || - mUniformIndexMap.Count() == 0 || - mShaderChanged) - { - // Reset shader pointer - mShaderChanged = false; - - const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex); - const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex); - - uint32_t maxMaps = static_cast(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough - mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size - mUniformIndexMap.Resize(maxMaps); - - uint32_t mapIndex = 0; - for(; mapIndex < uniformMap.Count(); ++mapIndex) - { - mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr; - mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform(uniformMap[mapIndex].uniformName); - } - - for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex) - { - uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName); - bool found(false); - for(uint32_t i = 0; i < uniformMap.Count(); ++i) - { - if(mUniformIndexMap[i].uniformIndex == uniformIndex) - { - mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr; - found = true; - break; - } - } - - if(!found) - { - mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr; - mUniformIndexMap[mapIndex].uniformIndex = uniformIndex; - ++mapIndex; - } - } - - mUniformIndexMap.Resize(mapIndex); - } - - // Set uniforms in local map - for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(), - end = mUniformIndexMap.End(); - iter != end; - ++iter) - { - SetUniformFromProperty(bufferIndex, program, *iter); - } + uint32_t textureUnit = 0; - GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE); - if(-1 != sizeLoc) - { - program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z); - } -} + std::vector& samplers(mRenderDataProvider->GetSamplers()); + std::vector& textures(mRenderDataProvider->GetTextures()); -void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map) -{ - GLint location = program.GetUniformLocation(map.uniformIndex); - if(Program::UNIFORM_UNKNOWN != location) + std::vector textureBindings; + for(uint32_t i = 0; i < static_cast(textures.size()); ++i) // not expecting more than uint32_t of textures { - // switch based on property type to use correct GL uniform setter - switch(map.propertyValue->GetType()) + if(textures[i] && textures[i]->GetGraphicsObject()) { - case Property::INTEGER: - { - program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex)); - break; - } - case Property::FLOAT: - { - program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex)); - break; - } - case Property::VECTOR2: - { - Vector2 value(map.propertyValue->GetVector2(bufferIndex)); - program.SetUniform2f(location, value.x, value.y); - break; - } - - case Property::VECTOR3: - { - Vector3 value(map.propertyValue->GetVector3(bufferIndex)); - program.SetUniform3f(location, value.x, value.y, value.z); - break; - } - - case Property::VECTOR4: - { - Vector4 value(map.propertyValue->GetVector4(bufferIndex)); - program.SetUniform4f(location, value.x, value.y, value.z, value.w); - break; - } + // if the sampler exists, + // if it's default, delete the graphics object + // otherwise re-initialize it if dirty - case Property::ROTATION: - { - Quaternion value(map.propertyValue->GetQuaternion(bufferIndex)); - program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w); - break; - } + const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject() + : nullptr); - case Property::MATRIX: - { - const Matrix& value = map.propertyValue->GetMatrix(bufferIndex); - program.SetUniformMatrix4fv(location, 1, value.AsFloat()); - break; - } + boundTextures.PushBack(textures[i]->GetGraphicsObject()); + const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit}; + textureBindings.push_back(textureBinding); - case Property::MATRIX3: - { - const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex); - program.SetUniformMatrix3fv(location, 1, value.AsFloat()); - break; - } - - default: - { - // Other property types are ignored - break; - } + ++textureUnit; } } -} -bool Renderer::BindTextures(Context& context, Program& program, Vector& boundTextures) -{ - uint32_t textureUnit = 0; - bool result = true; - - GLint uniformLocation(-1); - std::vector& samplers(mRenderDataProvider->GetSamplers()); - std::vector& textures(mRenderDataProvider->GetTextures()); - for(uint32_t i = 0; i < static_cast(textures.size()) && result; ++i) // not expecting more than uint32_t of textures + if(!textureBindings.empty()) { - if(textures[i]) - { - result = textures[i]->Bind(context, textureUnit, samplers[i]); - boundTextures.PushBack(textures[i]->GetId()); - if(result && program.GetSamplerUniformLocation(i, uniformLocation)) - { - program.SetUniform1i(uniformLocation, textureUnit); - ++textureUnit; - } - } + commandBuffer.BindTextures(textureBindings); } - - return result; } void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode) @@ -422,8 +259,8 @@ void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount) void Renderer::EnablePreMultipliedAlpha(bool enable) { - mPremultipledAlphaEnabled = enable; - mUpdated = true; + mPremultipliedAlphaEnabled = enable; + mUpdated = true; } void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode) @@ -547,12 +384,12 @@ StencilOperation::Type Renderer::GetStencilOperationOnZPass() const return mStencilParameters.stencilOperationOnZPass; } -void Renderer::Upload(Context& context) +void Renderer::Upload() { - mGeometry->Upload(context); + mGeometry->Upload(*mGraphicsController); } -void Renderer::Render(Context& context, +bool Renderer::Render(Graphics::CommandBuffer& commandBuffer, BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Matrix& modelMatrix, @@ -561,14 +398,14 @@ void Renderer::Render(Context& conte const Matrix& projectionMatrix, const Vector3& size, bool blend, - Vector& boundTextures, + Vector& boundTextures, const Dali::Internal::SceneGraph::RenderInstruction& instruction, uint32_t queueIndex) { // Before doing anything test if the call happens in the right queue if(mDrawCommands.empty() && queueIndex > 0) { - return; + return false; } // Prepare commands @@ -584,116 +421,334 @@ void Renderer::Render(Context& conte // Have commands but nothing to be drawn - abort if(!mDrawCommands.empty() && commands.empty()) { - return; + return false; + } + + // Set blending mode + if(!mDrawCommands.empty()) + { + blend = (commands[0]->queue != DevelRenderer::RENDER_QUEUE_OPAQUE) && blend; } - // Get the program to use - // The program cache owns the Program object so we don't need to worry about this raw allocation here. - ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData(); - Program* program = Program::New(*mProgramCache, shaderData, (shaderData->GetHints() & Dali::Shader::Hint::MODIFIES_GEOMETRY) != 0x0); + // Create Program + ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData(); + Program* program = Program::New(*mProgramCache, + shaderData, + *mGraphicsController); if(!program) { DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast(&mRenderDataProvider->GetShader())); - return; + return false; } - //Set cull face mode - const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera(); - if(cam->GetReflectionUsed()) + // If program doesn't have Gfx program object assigned yet, prepare it. + if(!program->GetGraphicsProgramPtr()) { - auto adjFaceCullingMode = mFaceCullingMode; - switch(mFaceCullingMode) - { - case FaceCullingMode::Type::FRONT: - { - adjFaceCullingMode = FaceCullingMode::Type::BACK; - break; - } - case FaceCullingMode::Type::BACK: - { - adjFaceCullingMode = FaceCullingMode::Type::FRONT; - break; - } - default: - { - // nothing to do, leave culling as it is - } - } - context.CullFace(adjFaceCullingMode); + const std::vector &vertShader = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER); + const std::vector &fragShader = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER); + Dali::Graphics::Shader &vertexShader = mShaderCache->GetShader( + vertShader, + Graphics::PipelineStage::VERTEX_SHADER, + shaderData->GetSourceMode()); + + Dali::Graphics::Shader &fragmentShader = mShaderCache->GetShader( + fragShader, + Graphics::PipelineStage::FRAGMENT_SHADER, + shaderData->GetSourceMode()); + + std::vector shaderStates{ + Graphics::ShaderState() + .SetShader(vertexShader) + .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER), + Graphics::ShaderState() + .SetShader(fragmentShader) + .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)}; + + auto createInfo = Graphics::ProgramCreateInfo(); + createInfo.SetShaderState(shaderStates); + auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr); + program->SetGraphicsProgram(std::move(graphicsProgram)); + } + + // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one. + auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend); + + commandBuffer.BindPipeline(pipeline); + + BindTextures(commandBuffer, boundTextures); + + BuildUniformIndexMap(bufferIndex, node, size, *program); + + WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size); + + bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet + // @todo We should detect this case much earlier to prevent unnecessary work + + if(mDrawCommands.empty()) + { + drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount); } else { - context.CullFace(mFaceCullingMode); + for(auto& cmd : commands) + { + mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount); + } } - // Take the program into use so we can send uniforms to it - program->Use(); + mUpdated = false; + return drawn; +} - if(DALI_LIKELY(BindTextures(context, *program, boundTextures))) +void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program) +{ + // Check if the map has changed + DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available"); + + const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap(); + + if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) || + node.GetUniformMapChanged(bufferIndex) || + mUniformIndexMap.Count() == 0 || + mShaderChanged) { - // Only set up and draw if we have textures and they are all valid + // Reset shader pointer + mShaderChanged = false; - // set projection and view matrix if program has not yet received them yet this frame - SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix); + const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex); + const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex); + + auto maxMaps = static_cast(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough + mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size + mUniformIndexMap.Resize(maxMaps); + + // Copy uniform map into mUniformIndexMap + uint32_t mapIndex = 0; + for(; mapIndex < uniformMap.Count(); ++mapIndex) + { + mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr; + mUniformIndexMap[mapIndex].uniformName = uniformMap[mapIndex].uniformName; + mUniformIndexMap[mapIndex].uniformNameHash = uniformMap[mapIndex].uniformNameHash; + mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMap[mapIndex].uniformNameHashNoArray; + mUniformIndexMap[mapIndex].arrayIndex = uniformMap[mapIndex].arrayIndex; + } - // set color uniform - GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR); - if(Program::UNIFORM_UNKNOWN != loc) + for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex) { - const Vector4& color = node.GetRenderColor(bufferIndex); - if(mPremultipledAlphaEnabled) + auto hash = uniformMapNode[nodeMapIndex].uniformNameHash; + auto& name = uniformMapNode[nodeMapIndex].uniformName; + bool found(false); + for(uint32_t i = 0; i < uniformMap.Count(); ++i) { - float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex); - program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha); + if(mUniformIndexMap[i].uniformNameHash == hash && + mUniformIndexMap[i].uniformName == name) + { + mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr; + found = true; + break; + } } - else + + if(!found) { - program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex)); + mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr; + mUniformIndexMap[mapIndex].uniformName = uniformMapNode[nodeMapIndex].uniformName; + mUniformIndexMap[mapIndex].uniformNameHash = uniformMapNode[nodeMapIndex].uniformNameHash; + mUniformIndexMap[mapIndex].uniformNameHashNoArray = uniformMapNode[nodeMapIndex].uniformNameHashNoArray; + mUniformIndexMap[mapIndex].arrayIndex = uniformMapNode[nodeMapIndex].arrayIndex; + ++mapIndex; } } - SetUniforms(bufferIndex, node, size, *program); + mUniformIndexMap.Resize(mapIndex); + } +} + +void Renderer::WriteUniformBuffer( + BufferIndex bufferIndex, + Graphics::CommandBuffer& commandBuffer, + Program* program, + const SceneGraph::RenderInstruction& instruction, + const SceneGraph::NodeDataProvider& node, + const Matrix& modelMatrix, + const Matrix& modelViewMatrix, + const Matrix& viewMatrix, + const Matrix& projectionMatrix, + const Vector3& size) +{ + // Create the UBO + uint32_t uboOffset{0u}; + + auto &reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram()); + + uint32_t uniformBlockAllocationBytes = program->GetUniformBlocksMemoryRequirements().totalSizeRequired; + + // Create uniform buffer view from uniform buffer + Graphics::UniquePtr uboView{nullptr}; + if(uniformBlockAllocationBytes) + { + auto uboPoolView = mUniformBufferManager->GetUniformBufferViewPool(bufferIndex); + + uboView = uboPoolView->CreateUniformBufferView(uniformBlockAllocationBytes); + } + + // update the uniform buffer + // pass shared UBO and offset, return new offset for next item to be used + // don't process bindings if there are no uniform buffers allocated + if(uboView) + { + auto uboCount = reflection.GetUniformBlockCount(); + mUniformBufferBindings.resize(uboCount); + + std::vector* bindings{&mUniformBufferBindings}; - if(mUpdateAttributesLocation || mGeometry->AttributesChanged()) + mUniformBufferBindings[0].buffer = uboView->GetBuffer(&mUniformBufferBindings[0].offset); + + // Write default uniforms + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), *uboView, modelMatrix); + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::VIEW_MATRIX), *uboView, viewMatrix); + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::PROJECTION_MATRIX), *uboView, projectionMatrix); + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_VIEW_MATRIX), *uboView, modelViewMatrix); + + auto mvpUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::MVP_MATRIX); + if(mvpUniformInfo && !mvpUniformInfo->name.empty()) { - mGeometry->GetAttributeLocationFromProgram(mAttributesLocation, *program, bufferIndex); - mUpdateAttributesLocation = false; + Matrix modelViewProjectionMatrix(false); + Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix); + WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix); } - if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled) + auto normalUniformInfo = program->GetDefaultUniform(Program::DefaultUniformIndex::NORMAL_MATRIX); + if(normalUniformInfo && !normalUniformInfo->name.empty()) { - context.BlendBarrier(); + Matrix3 normalMatrix(modelViewMatrix); + normalMatrix.Invert(); + normalMatrix.Transpose(); + WriteDefaultUniform(normalUniformInfo, *uboView, normalMatrix); } - if(mDrawCommands.empty()) + Vector4 finalColor; + const Vector4& color = node.GetRenderColor(bufferIndex); + if(mPremultipliedAlphaEnabled) { - SetBlending(context, blend); - - mGeometry->Draw(context, - bufferIndex, - mAttributesLocation, - mIndexedDrawFirstElement, - mIndexedDrawElementsCount); + float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex); + finalColor = Vector4(color.r * alpha, color.g * alpha, color.b * alpha, alpha); } else { - for(auto& cmd : commands) + finalColor = Vector4(color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex)); + } + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::COLOR), *uboView, finalColor); + + // Write uniforms from the uniform map + FillUniformBuffer(*program, instruction, *uboView, bindings, uboOffset, bufferIndex); + + // Write uSize in the end, as it shouldn't be overridable by dynamic properties. + WriteDefaultUniform(program->GetDefaultUniform(Program::DefaultUniformIndex::SIZE), *uboView, size); + + commandBuffer.BindUniformBuffers(*bindings); + } +} + +template +bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Render::UniformBufferView& ubo, const T& data) +{ + if(uniformInfo && !uniformInfo->name.empty()) + { + WriteUniform(ubo, *uniformInfo, data); + return true; + } + return false; +} + +template +void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const T& data) +{ + WriteUniform(ubo, uniformInfo, &data, sizeof(T)); +} + +void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::UniformInfo& uniformInfo, const void* data, uint32_t size) +{ + ubo.Write(data, size, ubo.GetOffset() + uniformInfo.offset); +} + +void Renderer::FillUniformBuffer(Program& program, + const SceneGraph::RenderInstruction& instruction, + Render::UniformBufferView& ubo, + std::vector*& outBindings, + uint32_t& offset, + BufferIndex updateBufferIndex) +{ + auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram()); + auto uboCount = reflection.GetUniformBlockCount(); + + // Setup bindings + uint32_t dataOffset = offset; + for(auto i = 0u; i < uboCount; ++i) + { + mUniformBufferBindings[i].dataSize = reflection.GetUniformBlockSize(i); + mUniformBufferBindings[i].binding = reflection.GetUniformBlockBinding(i); + + dataOffset += GetUniformBufferDataAlignment(mUniformBufferBindings[i].dataSize); + mUniformBufferBindings[i].buffer = ubo.GetBuffer(&mUniformBufferBindings[i].offset); + + for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(), + end = mUniformIndexMap.End(); + iter != end; + ++iter) + { + auto& uniform = *iter; + int arrayIndex = uniform.arrayIndex; + + if(!uniform.uniformFunc) { - if(cmd->queue == queueIndex) + auto uniformInfo = Graphics::UniformInfo{}; + auto uniformFound = program.GetUniform(uniform.uniformName.GetCString(), + uniform.uniformNameHashNoArray ? uniform.uniformNameHashNoArray + : uniform.uniformNameHash, + uniformInfo); + + uniform.uniformOffset = uniformInfo.offset; + uniform.uniformLocation = uniformInfo.location; + + if (uniformFound) { - //Set blending mode - SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend); - mGeometry->Draw(context, bufferIndex, mAttributesLocation, cmd->firstIndex, cmd->elementCount); + auto dst = ubo.GetOffset() + uniformInfo.offset; + 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); + + uniform.uniformSize = typeSize; + uniform.uniformFunc = func; } } + else + { + auto dst = ubo.GetOffset() + uniform.uniformOffset; + const auto typeSize = uniform.uniformSize; + const auto dest = dst + static_cast(typeSize) * arrayIndex; + const auto func = uniform.uniformFunc; + + + ubo.Write(&((*iter).propertyValue->*func)(updateBufferIndex), + typeSize, + dest); + } } - mUpdated = false; } + // write output bindings + outBindings = &mUniformBufferBindings; + + // Update offset + offset = dataOffset; } -void Renderer::SetSortAttributes(BufferIndex bufferIndex, - SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const +void Renderer::SetSortAttributes(SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const { sortAttributes.shader = &(mRenderDataProvider->GetShader()); sortAttributes.geometry = mGeometry; @@ -712,7 +767,7 @@ bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvid return true; } - if(mShaderChanged || mUpdateAttributesLocation || mGeometry->AttributesChanged()) + if(mShaderChanged || mGeometry->AttributesChanged()) { return true; } @@ -748,8 +803,33 @@ bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvid return false; } -} // namespace Render +Graphics::Pipeline& Renderer::PrepareGraphicsPipeline( + Program& program, + const Dali::Internal::SceneGraph::RenderInstruction& instruction, + const SceneGraph::NodeDataProvider& node, + bool blend) +{ + if(mGeometry->AttributesChanged()) + { + mUpdated = true; + } + + // Prepare query info + PipelineCacheQueryInfo queryInfo{}; + queryInfo.program = &program; + queryInfo.renderer = this; + queryInfo.geometry = mGeometry; + queryInfo.blendingEnabled = blend; + queryInfo.blendingOptions = &mBlendingOptions; + queryInfo.alphaPremultiplied = mPremultipliedAlphaEnabled; + queryInfo.cameraUsingReflection = instruction.GetCamera()->GetReflectionUsed(); -} // namespace Internal + auto pipelineResult = mPipelineCache->GetPipeline( queryInfo, true ); + + // should be never null? + return *pipelineResult.pipeline; +} + +} // namespace Render -} // namespace Dali +} // namespace Dali::Internal