From d217778ac6f0b391d9229dae551a40eff2fb57bf Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Fri, 3 Nov 2023 11:52:44 +0900 Subject: [PATCH] Reduce some useless if check during prepare render instructions - Reduce overhead when we get ShaderData - Do not check RenderingBehaviour multiple times. - Remove some useless IntrusivePtr copy operation (Reference / Unreference) Change-Id: I2215f7bacff6571c2508848ebda1ea67d52b8c98 Signed-off-by: Eunki, Hong --- dali/internal/event/rendering/shader-impl.cpp | 27 ++++--- dali/internal/render/renderers/render-renderer.cpp | 4 +- dali/internal/render/shaders/program.cpp | 4 +- dali/internal/render/shaders/program.h | 2 +- dali/internal/render/shaders/render-shader.cpp | 42 +++++------ dali/internal/render/shaders/render-shader.h | 3 +- .../manager/render-instruction-processor.cpp | 22 ++++-- .../update/manager/render-task-processor.cpp | 82 +++++++++++----------- .../update/rendering/scene-graph-renderer.cpp | 10 ++- 9 files changed, 102 insertions(+), 94 deletions(-) diff --git a/dali/internal/event/rendering/shader-impl.cpp b/dali/internal/event/rendering/shader-impl.cpp index 57b8b59..e1f9005 100644 --- a/dali/internal/event/rendering/shader-impl.cpp +++ b/dali/internal/event/rendering/shader-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -90,8 +90,8 @@ Property::Value HintString(const Dali::Shader::Hint::Value& hints) void GetShaderData(const Property::Map& shaderMap, std::string& vertexShader, std::string& fragmentShader, uint32_t& renderPassTag, Dali::Shader::Hint::Value& hints) { - hints = Dali::Shader::Hint::NONE; - renderPassTag = 0u; + hints = Dali::Shader::Hint::NONE; + renderPassTag = DEFAULT_RENDER_PASS_TAG; if(Property::Value* value = shaderMap.Find("vertex")) { @@ -194,11 +194,11 @@ Property::Value Shader::GetDefaultProperty(Property::Index index) const if(mShaderDataList.size() == 1u) { Dali::Property::Map map; - map["vertex"] = Property::Value(mShaderDataList.front()->GetVertexShader()); - map["fragment"] = Property::Value(mShaderDataList.front()->GetFragmentShader()); + map["vertex"] = Property::Value(mShaderDataList.front()->GetVertexShader()); + map["fragment"] = Property::Value(mShaderDataList.front()->GetFragmentShader()); map["renderPassTag"] = Property::Value(static_cast(mShaderDataList.front()->GetRenderPassTag())); - map["hints"] = HintString(mShaderDataList.front()->GetHints()); - value = map; + map["hints"] = HintString(mShaderDataList.front()->GetHints()); + value = map; } else { @@ -208,10 +208,10 @@ Property::Value Shader::GetDefaultProperty(Property::Index index) const if(shaderData) { Dali::Property::Map map; - map["vertex"] = Property::Value(shaderData->GetVertexShader()); - map["fragment"] = Property::Value(shaderData->GetFragmentShader()); + map["vertex"] = Property::Value(shaderData->GetVertexShader()); + map["fragment"] = Property::Value(shaderData->GetFragmentShader()); map["renderPassTag"] = Property::Value(static_cast(shaderData->GetRenderPassTag())); - map["hints"] = HintString(shaderData->GetHints()); + map["hints"] = HintString(shaderData->GetHints()); array.PushBack(map); } } @@ -245,8 +245,7 @@ void Shader::UpdateShaderData(std::string_view vertexSource, size_t shaderHash; Internal::ShaderDataPtr shaderData = shaderFactory.Load(vertexSource, fragmentSource, hints, renderPassTag, shaderHash); - std::vector::iterator shaderDataIterator = std::find_if(mShaderDataList.begin(), mShaderDataList.end(), [&shaderData](const Internal::ShaderDataPtr& shaderDataItem) - { return shaderDataItem->GetRenderPassTag() == shaderData->GetRenderPassTag(); }); + std::vector::iterator shaderDataIterator = std::find_if(mShaderDataList.begin(), mShaderDataList.end(), [&shaderData](const Internal::ShaderDataPtr& shaderDataItem) { return shaderDataItem->GetRenderPassTag() == shaderData->GetRenderPassTag(); }); if(shaderDataIterator != mShaderDataList.end()) { *shaderDataIterator = shaderData; @@ -269,7 +268,7 @@ void Shader::SetShaderProperty(const Dali::Property::Value& shaderMap) { std::string vertex; std::string fragment; - uint32_t renderPassTag{0u}; + uint32_t renderPassTag{DEFAULT_RENDER_PASS_TAG}; Dali::Shader::Hint::Value hints(Dali::Shader::Hint::NONE); GetShaderData(*map, vertex, fragment, renderPassTag, hints); @@ -289,7 +288,7 @@ void Shader::SetShaderProperty(const Dali::Property::Value& shaderMap) { std::string vertex; std::string fragment; - uint32_t renderPassTag{0u}; + uint32_t renderPassTag{DEFAULT_RENDER_PASS_TAG}; Dali::Shader::Hint::Value hints(Dali::Shader::Hint::NONE); GetShaderData(*map, vertex, fragment, renderPassTag, hints); diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp index 2762d44..8eb8120 100644 --- a/dali/internal/render/renderers/render-renderer.cpp +++ b/dali/internal/render/renderers/render-renderer.cpp @@ -488,7 +488,7 @@ Program* Renderer::PrepareProgram(const SceneGraph::RenderInstruction& instructi // Create Program const SceneGraph::Shader& shader = mRenderDataProvider->GetShader(); - ShaderDataPtr shaderData = shader.GetShaderData(instruction.mRenderPassTag); + const ShaderDataPtr& shaderData = shader.GetShaderData(instruction.mRenderPassTag); if(!shaderData) { DALI_LOG_ERROR("Failed to get shader data.\n"); @@ -696,7 +696,7 @@ std::size_t Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneG // Specially, if node don't have uniformMap, we mark nodePtr as nullptr. // So, all nodes without uniformMap will share same UniformIndexMap, contains only render data providers. - const auto nodePtr = uniformMapNode.Count() ? &node : nullptr; + const auto nodePtr = uniformMapNode.Count() ? &node : nullptr; const auto programPtr = &program; const auto nodeChangeCounter = nodePtr ? uniformMapNode.GetChangeCounter() : 0; diff --git a/dali/internal/render/shaders/program.cpp b/dali/internal/render/shaders/program.cpp index 1acafae..bdc7053 100644 --- a/dali/internal/render/shaders/program.cpp +++ b/dali/internal/render/shaders/program.cpp @@ -74,7 +74,7 @@ inline uint32_t AlignSize(uint32_t dataSize, uint32_t alignSize) // 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(); @@ -97,7 +97,7 @@ Program::Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphi mViewMatrix(nullptr), mGfxProgram(nullptr), mGfxController(controller), - mProgramData(shaderData) + mProgramData(std::move(shaderData)) { } diff --git a/dali/internal/render/shaders/program.h b/dali/internal/render/shaders/program.h index 5e46c39..8130f93 100644 --- a/dali/internal/render/shaders/program.h +++ b/dali/internal/render/shaders/program.h @@ -84,7 +84,7 @@ public: * @param[in] gfxController Reference to valid graphics Controller object * @return pointer to the program */ - static Program* New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphics::Controller& gfxController); + static Program* New(ProgramCache& cache, const Internal::ShaderDataPtr& shaderData, Graphics::Controller& gfxController); /** * Set the projection matrix that has currently been sent diff --git a/dali/internal/render/shaders/render-shader.cpp b/dali/internal/render/shaders/render-shader.cpp index 5e03ec1..cee4b2f 100644 --- a/dali/internal/render/shaders/render-shader.cpp +++ b/dali/internal/render/shaders/render-shader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -31,7 +31,6 @@ namespace Internal { namespace SceneGraph { - namespace { static constexpr uint32_t DEFAULT_RENDER_PASS_TAG = 0u; @@ -43,45 +42,38 @@ Shader::~Shader() void Shader::UpdateShaderData(ShaderDataPtr shaderData) { + if(shaderData->GetRenderPassTag() == DEFAULT_RENDER_PASS_TAG) + { + mDefaultShaderData = std::move(shaderData); + return; + } + DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, "%d\n", shaderData->GetHashValue()); - std::vector::iterator shaderDataIterator = std::find_if(mShaderDataList.begin(), mShaderDataList.end(), [&shaderData](const Internal::ShaderDataPtr& shaderDataItem) - { return shaderDataItem->GetRenderPassTag() == shaderData->GetRenderPassTag(); }); + std::vector::iterator shaderDataIterator = std::find_if(mShaderDataList.begin(), mShaderDataList.end(), [&shaderData](const Internal::ShaderDataPtr& shaderDataItem) { return shaderDataItem->GetRenderPassTag() == shaderData->GetRenderPassTag(); }); if(shaderDataIterator != mShaderDataList.end()) { - *shaderDataIterator = shaderData; + *shaderDataIterator = std::move(shaderData); } else { - mShaderDataList.push_back(shaderData); + mShaderDataList.push_back(std::move(shaderData)); } } ShaderDataPtr Shader::GetShaderData(uint32_t renderPassTag) const { - if(mShaderDataList.empty()) - { - return nullptr; - } - - Internal::ShaderDataPtr returnShaderData = nullptr; - for(auto && shaderData : mShaderDataList) + if(renderPassTag != DEFAULT_RENDER_PASS_TAG) { - if(shaderData->GetRenderPassTag() == renderPassTag) - { - return shaderData; - } - if(shaderData->GetRenderPassTag() == DEFAULT_RENDER_PASS_TAG) + for(auto&& shaderData : mShaderDataList) { - returnShaderData = shaderData; + if(shaderData->GetRenderPassTag() == renderPassTag) + { + return shaderData; + } } } - if(returnShaderData) - { - return returnShaderData; - } - - return mShaderDataList.front(); + return mDefaultShaderData; } } // namespace SceneGraph diff --git a/dali/internal/render/shaders/render-shader.h b/dali/internal/render/shaders/render-shader.h index d94224e..9be08d6 100644 --- a/dali/internal/render/shaders/render-shader.h +++ b/dali/internal/render/shaders/render-shader.h @@ -70,7 +70,8 @@ public: [[nodiscard]] ShaderDataPtr GetShaderData(uint32_t renderPassTag) const; private: // Data - std::vector mShaderDataList; + ShaderDataPtr mDefaultShaderData{nullptr}; + std::vector mShaderDataList{}; }; inline void UpdateShaderDataMessage(EventThreadServices& eventThreadServices, const Shader& shader, ShaderDataPtr shaderData) diff --git a/dali/internal/update/manager/render-instruction-processor.cpp b/dali/internal/update/manager/render-instruction-processor.cpp index cb75c1b..09fa6d5 100644 --- a/dali/internal/update/manager/render-instruction-processor.cpp +++ b/dali/internal/update/manager/render-instruction-processor.cpp @@ -209,10 +209,24 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, Matrix nodeModelViewMatrix(false); bool nodeModelViewMatrixSet(false); + const bool rendererExist(renderable.mRenderer); + // Don't cull items which have render callback - bool hasRenderCallback = (renderable.mRenderer && renderable.mRenderer->GetRenderCallback()); + bool hasRenderCallback = (rendererExist && renderable.mRenderer->GetRenderCallback()); + + auto requiredInsideCheck = [&]() { + if(cull && + !hasRenderCallback && + node->GetClippingMode() == ClippingMode::DISABLED && + rendererExist) + { + const auto& shaderData = renderable.mRenderer->GetShader().GetShaderData(renderPass); + return (shaderData && !shaderData->HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY)); + } + return false; + }; - if(cull && renderable.mRenderer && !hasRenderCallback && renderable.mRenderer->GetShader().GetShaderData(renderPass) && !renderable.mRenderer->GetShader().GetShaderData(renderPass)->HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED) + if(requiredInsideCheck()) { const Vector4& boundingSphere = node->GetBoundingSphere(); inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) && @@ -254,7 +268,7 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, bool isOpaque = true; if(!hasRenderCallback) { - Renderer::OpacityType opacityType = renderable.mRenderer ? renderable.mRenderer->GetOpacityType(updateBufferIndex, renderPass, *node) : Renderer::OPAQUE; + Renderer::OpacityType opacityType = rendererExist ? renderable.mRenderer->GetOpacityType(updateBufferIndex, renderPass, *node) : Renderer::OPAQUE; // We can skip render when node is not clipping and transparent skipRender = (opacityType == Renderer::TRANSPARENT && node->GetClippingMode() == ClippingMode::DISABLED); @@ -271,7 +285,7 @@ inline void AddRendererToRenderList(BufferIndex updateBufferIndex, item.mIsOpaque = isOpaque; item.mDepthIndex = isLayer3d ? 0 : node->GetDepthIndex(); - if(DALI_LIKELY(renderable.mRenderer)) + if(DALI_LIKELY(rendererExist)) { item.mRenderer = renderable.mRenderer->GetRenderer(); item.mTextureSet = renderable.mRenderer->GetTextureSet(); diff --git a/dali/internal/update/manager/render-task-processor.cpp b/dali/internal/update/manager/render-task-processor.cpp index 865e910..c1460e2 100644 --- a/dali/internal/update/manager/render-task-processor.cpp +++ b/dali/internal/update/manager/render-task-processor.cpp @@ -92,9 +92,9 @@ Layer* FindLayer(Node& node) * @param[in] clippingDepth The current stencil clipping depth * @param[in] clippingDepth The current scissor clipping depth * @param[out] clippingUsed Gets set to true if any clipping nodes have been found - * @return true if rendering should be kept, false otherwise. + * @param[out] keepRendering Gets set to true if rendering should be kept. */ -bool AddRenderablesForTask(BufferIndex updateBufferIndex, +void AddRenderablesForTask(BufferIndex updateBufferIndex, Node& node, Layer& currentLayer, RenderTask& renderTask, @@ -102,15 +102,14 @@ bool AddRenderablesForTask(BufferIndex updateBufferIndex, uint32_t& currentClippingId, uint32_t clippingDepth, uint32_t scissorDepth, - bool& clippingUsed) + bool& clippingUsed, + bool& keepRendering) { - bool keepRendering = false; - // Short-circuit for invisible nodes if(!node.IsVisible(updateBufferIndex)) { node.GetPartialRenderingData().mVisible = false; - return keepRendering; + return; } // If the node was not previously visible @@ -123,7 +122,7 @@ bool AddRenderablesForTask(BufferIndex updateBufferIndex, // Check whether node is exclusive to a different render-task if(node.GetExclusiveRenderTaskCount() && !node.IsExclusiveRenderTask(&renderTask)) { - return keepRendering; + return; } // Assume all children go to this layer (if this node is a layer). @@ -185,10 +184,8 @@ bool AddRenderablesForTask(BufferIndex updateBufferIndex, for(NodeIter iter = children.Begin(); iter != endIter; ++iter) { Node& child = **iter; - keepRendering |= AddRenderablesForTask(updateBufferIndex, child, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed); + AddRenderablesForTask(updateBufferIndex, child, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed, keepRendering); } - - return keepRendering; } /** @@ -201,17 +198,18 @@ bool AddRenderablesForTask(BufferIndex updateBufferIndex, * @param[in] sortedLayers The layers containing lists of opaque / transparent renderables. * @param[out] instructions The instructions for rendering the next frame. * @param[in] renderInstructionProcessor An instance of the RenderInstructionProcessor used to sort and handle the renderers for each layer. + * @param[out] keepRendering Gets set to true if rendering should be kept. * @param[in] renderToFboEnabled Whether rendering into the Frame Buffer Object is enabled (used to measure FPS above 60) * @param[in] isRenderingToFbo Whether this frame is being rendered into the Frame Buffer Object (used to measure FPS above 60) * @param[in] processOffscreen Whether the offscreen render tasks are the ones processed. Otherwise it processes the onscreen tasks. - * @return true if rendering should be kept, false otherwise. */ -bool ProcessTasks(BufferIndex updateBufferIndex, +void ProcessTasks(BufferIndex updateBufferIndex, RenderTaskList::RenderTaskContainer& taskContainer, Layer& rootNode, SortedLayerPointers& sortedLayers, RenderInstructionContainer& instructions, RenderInstructionProcessor& renderInstructionProcessor, + bool& keepRendering, bool renderToFboEnabled, bool isRenderingToFbo, bool processOffscreen) @@ -220,7 +218,6 @@ bool ProcessTasks(BufferIndex updateBufferIndex, bool hasClippingNodes = false; bool isFirstRenderTask = true; - bool keepRendering = false; // Retrieve size of Scene and default camera position to update viewport of each RenderTask if the RenderTask uses ViewportGuideNode. RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); @@ -281,15 +278,16 @@ bool ProcessTasks(BufferIndex updateBufferIndex, sortedLayer->ClearRenderables(); } - keepRendering |= AddRenderablesForTask(updateBufferIndex, - *sourceNode, - *layer, - renderTask, - sourceNode->GetDrawMode(), - clippingId, - 0u, - 0u, - hasClippingNodes); + AddRenderablesForTask(updateBufferIndex, + *sourceNode, + *layer, + renderTask, + sourceNode->GetDrawMode(), + clippingId, + 0u, + 0u, + hasClippingNodes, + keepRendering); renderInstructionProcessor.Prepare(updateBufferIndex, sortedLayers, @@ -310,8 +308,6 @@ bool ProcessTasks(BufferIndex updateBufferIndex, } } } - - return keepRendering; } } // Anonymous namespace. @@ -347,30 +343,32 @@ bool RenderTaskProcessor::Process(BufferIndex updateBufferIndex, // First process off screen render tasks - we may need the results of these for the on screen renders - keepRendering = ProcessTasks(updateBufferIndex, - taskContainer, - rootNode, - sortedLayers, - instructions, - mRenderInstructionProcessor, - renderToFboEnabled, - isRenderingToFbo, - true); + ProcessTasks(updateBufferIndex, + taskContainer, + rootNode, + sortedLayers, + instructions, + mRenderInstructionProcessor, + keepRendering, + renderToFboEnabled, + isRenderingToFbo, + true); DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "RenderTaskProcessor::Process() Onscreen\n"); // Now that the off screen renders are done we can process on screen render tasks. // Reset the clipping Id for the OnScreen render tasks. - keepRendering |= ProcessTasks(updateBufferIndex, - taskContainer, - rootNode, - sortedLayers, - instructions, - mRenderInstructionProcessor, - renderToFboEnabled, - isRenderingToFbo, - false); + ProcessTasks(updateBufferIndex, + taskContainer, + rootNode, + sortedLayers, + instructions, + mRenderInstructionProcessor, + keepRendering, + renderToFboEnabled, + isRenderingToFbo, + false); return keepRendering; } diff --git a/dali/internal/update/rendering/scene-graph-renderer.cpp b/dali/internal/update/rendering/scene-graph-renderer.cpp index 7ca244e..85c269a 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.cpp +++ b/dali/internal/update/rendering/scene-graph-renderer.cpp @@ -684,10 +684,14 @@ Renderer::OpacityType Renderer::GetOpacityType(BufferIndex updateBufferIndex, ui break; } - if(mShader->GetShaderData(renderPass)) + if(mTextureSet && mTextureSet->HasAlpha()) { - bool shaderRequiresBlending(mShader->GetShaderData(renderPass)->HintEnabled(Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT)); - if(shaderRequiresBlending || (mTextureSet && mTextureSet->HasAlpha())) + opacityType = Renderer::TRANSLUCENT; + } + else + { + const auto& shaderData = mShader->GetShaderData(renderPass); + if(shaderData && shaderData->HintEnabled(Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT)) { opacityType = Renderer::TRANSLUCENT; } -- 2.7.4