/*
- * Copyright (c) 2023 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.
// EXTERNAL INCLUDES
#include <dali/integration-api/platform-abstraction.h>
-#include <dali/integration-api/shader-precompiler.h>
#include <errno.h>
#include <unistd.h>
#include "dali/public-api/common/dali-common.h"
// INTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/shader-precompiler.h>
#include <dali/integration-api/adaptor-framework/trigger-event-factory.h>
#include <dali/internal/adaptor/common/adaptor-internal-services.h>
#include <dali/internal/adaptor/common/combined-update-render-controller-debug.h>
{
namespace
{
-
const unsigned int CREATED_THREAD_COUNT = 1u;
const int CONTINUOUS = -1;
* 3) MAIN THREAD: Sleep Request: COUNTER = 0 -> Go to sleep
*/
const unsigned int MAXIMUM_UPDATE_REQUESTS = 2;
+
+inline std::vector<char> StringToVector(const std::string& str)
+{
+ auto retval = std::vector<char>{};
+ retval.insert(retval.begin(), str.begin(), str.end());
+ retval.push_back('\0');
+ return retval;
+}
+
} // unnamed namespace
///////////////////////////////////////////////////////////////////////////////////////////////////
mUpdateRenderThreadCanSleep(FALSE),
mPendingRequestUpdate(FALSE),
mUseElapsedTimeAfterWait(FALSE),
+ mIsPreCompileCancelled(FALSE),
mNewSurface(NULL),
mDeletedSurface(nullptr),
mPostRendering(FALSE),
ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will replace the surface now
mNewSurface = newSurface;
+ CancelPreCompile();
mUpdateRenderThreadWaitCondition.Notify(lock);
}
ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will delete the surface now
mDeletedSurface = surface;
+ CancelPreCompile();
mUpdateRenderThreadWaitCondition.Notify(lock);
}
ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
// Surface is resized and the surface resized count is increased.
mSurfaceResized++;
+ CancelPreCompile();
mUpdateRenderThreadWaitCondition.Notify(lock);
}
}
mUpdateRenderThreadCanSleep = FALSE;
mUploadWithoutRendering = (updateMode == UpdateMode::SKIP_RENDER);
LOG_COUNTER_EVENT("mUpdateRenderRunCount: %d, mUseElapsedTimeAfterWait: %d", mUpdateRenderRunCount, mUseElapsedTimeAfterWait);
+ CancelPreCompile();
mUpdateRenderThreadWaitCondition.Notify(lock);
}
{
ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
mDestroyUpdateRenderThread = TRUE;
+ CancelPreCompile();
mUpdateRenderThreadWaitCondition.Notify(lock);
}
// Install a function for tracing
mEnvironmentOptions.InstallTraceFunction();
+ TRACE_UPDATE_RENDER_BEGIN("DALI_RENDER_THREAD_INIT");
+
LOG_UPDATE_RENDER("THREAD CREATED");
// Initialize graphics
const bool renderToFboEnabled = 0u != renderToFboInterval;
unsigned int frameCount = 0u;
- if(Integration::ShaderPrecompiler::Get().IsEnable())
+ TRACE_UPDATE_RENDER_END("DALI_RENDER_THREAD_INIT");
+ if(!mDestroyUpdateRenderThread)
{
- std::vector<RawShaderData> precompiledShaderList;
- Integration::ShaderPrecompiler::Get().GetPrecompileShaderList(precompiledShaderList);
- DALI_LOG_RELEASE_INFO("ShaderPrecompiler[ENABLE], list size:%d \n",precompiledShaderList.size());
- for(auto precompiledShader = precompiledShaderList.begin(); precompiledShader != precompiledShaderList.end(); ++precompiledShader)
+ ShaderPreCompiler::Get().Wait();
+ if(ShaderPreCompiler::Get().IsEnable())
{
- auto numberOfPrecomipledShader = precompiledShader->shaderCount;
- for(int i= 0; i<numberOfPrecomipledShader; ++i)
+ std::vector<RawShaderData> precompiledShaderList;
+ ShaderPreCompiler::Get().GetPreCompileShaderList(precompiledShaderList);
+ DALI_LOG_RELEASE_INFO("ShaderPreCompiler[ENABLE], list size:%d \n", precompiledShaderList.size());
+ for(auto precompiledShader = precompiledShaderList.begin(); precompiledShader != precompiledShaderList.end(); ++precompiledShader)
{
- auto vertexShader = std::string(graphics.GetController().GetGlAbstraction().GetVertexShaderPrefix() + precompiledShader->vertexPrefix[i].data() + precompiledShader->vertexShader.data());
- auto fragmentShader = std::string(graphics.GetController().GetGlAbstraction().GetFragmentShaderPrefix() + precompiledShader->fragmentPrefix[i].data() + precompiledShader->fragmentShader.data());
- mCore.PreCompileShader(vertexShader.data(), fragmentShader.data());
+ if(mIsPreCompileCancelled == TRUE)
+ {
+ ShaderPreCompiler::Get().Awake();
+ DALI_LOG_RELEASE_INFO("ShaderPreCompiler[ENABLE], but stop precompile");
+ break;
+ }
+
+ auto numberOfPrecompiledShader = precompiledShader->shaderCount;
+ for(int i = 0; i < numberOfPrecompiledShader; ++i)
+ {
+ auto vertexShader = graphics.GetController().GetGlAbstraction().GetVertexShaderPrefix() + std::string(precompiledShader->vertexPrefix[i].data()) + std::string(precompiledShader->vertexShader.data());
+ auto fragmentShader = graphics.GetController().GetGlAbstraction().GetFragmentShaderPrefix() + std::string(precompiledShader->fragmentPrefix[i].data()) + std::string(precompiledShader->fragmentShader.data());
+ PreCompileShader(std::move(vertexShader), std::move(fragmentShader));
+ }
+ DALI_LOG_RELEASE_INFO("ShaderPreCompiler[ENABLE], shader count :%d \n", numberOfPrecompiledShader);
}
- DALI_LOG_RELEASE_INFO("ShaderPrecompiler[ENABLE], shader count :%d \n",numberOfPrecomipledShader);
}
- }
- else
- {
- DALI_LOG_RELEASE_INFO("ShaderPrecompiler[DISABLE] \n");
+ else
+ {
+ DALI_LOG_RELEASE_INFO("ShaderPreCompiler[DISABLE] \n");
+ }
}
while(UpdateRenderReady(useElapsedTime, updateRequired, timeToSleepUntil))
{
LOG_UPDATE_RENDER_TRACE;
+ TRACE_UPDATE_RENDER_BEGIN("DALI_UPDATE_RENDER");
// For thread safe
bool uploadOnly = mUploadWithoutRendering;
mNotificationTrigger.Trigger();
LOG_UPDATE_RENDER("Notification Triggered");
}
+
+ if(uploadOnly && (keepUpdatingStatus & Dali::Integration::KeepUpdating::STAGE_KEEP_RENDERING))
+ {
+ // Render forcely if there exist some keep rendering required.
+ uploadOnly = false;
+ }
// Optional logging of update/render status
mUpdateStatusLogger.Log(keepUpdatingStatus);
if(scene && windowSurface)
{
- TRACE_UPDATE_RENDER_BEGIN("DALI_RENDER_SCENE");
+ TRACE_UPDATE_RENDER_SCOPE("DALI_RENDER_SCENE");
Integration::RenderStatus windowRenderStatus;
- const bool sceneSurfaceResized = scene.IsSurfaceRectChanged();
+ const uint32_t sceneSurfaceResized = scene.GetSurfaceRectChangedCount();
// clear previous frame damaged render items rects, buffer history is tracked on surface level
mDamagedRects.clear();
Rect<int> clippingRect; // Empty for fbo rendering
// Switch to the context of the surface, merge damaged areas for previous frames
- windowSurface->PreRender(sceneSurfaceResized, mDamagedRects, clippingRect); // Switch GL context
+ windowSurface->PreRender(sceneSurfaceResized > 0u, mDamagedRects, clippingRect); // Switch GL context
// Render the surface
mCore.RenderScene(windowRenderStatus, scene, false, clippingRect);
// Buffer swapping now happens when the surface render target is presented.
// If surface is resized, the surface resized count is decreased.
- if(DALI_UNLIKELY(sceneSurfaceResized))
+ if(DALI_UNLIKELY(sceneSurfaceResized > 0u))
{
- SurfaceResized();
+ SurfaceResized(sceneSurfaceResized);
}
- TRACE_UPDATE_RENDER_END("DALI_RENDER_SCENE");
}
}
}
+ else
+ {
+ DALI_LOG_RELEASE_INFO("DALI Rendering skip (upload only)\n");
+ }
TRACE_UPDATE_RENDER_BEGIN("DALI_POST_RENDER");
if(!uploadOnly)
}
}
+ TRACE_UPDATE_RENDER_END("DALI_UPDATE_RENDER");
+
// Render to FBO is intended to measure fps above 60 so sleep is not wanted.
if(0u == renderToFboInterval)
{
+ TRACE_UPDATE_RENDER_SCOPE("DALI_UPDATE_RENDER_SLEEP");
// Sleep until at least the the default frame duration has elapsed. This will return immediately if the specified end-time has already passed.
TimeService::SleepUntil(timeToSleepUntil);
}
}
+ TRACE_UPDATE_RENDER_BEGIN("DALI_RENDER_THREAD_FINISH");
// Inform core of context destruction
mCore.ContextDestroyed();
LOG_UPDATE_RENDER("THREAD DESTROYED");
+ TRACE_UPDATE_RENDER_END("DALI_RENDER_THREAD_FINISH");
+
// Uninstall the logging function
mEnvironmentOptions.UnInstallLogFunction();
}
// of the first frame.
timeToSleepUntil = 0;
+ TRACE_UPDATE_RENDER_BEGIN("DALI_UPDATE_RENDER_THREAD_WAIT_CONDITION");
mUpdateRenderThreadWaitCondition.Wait(updateLock);
+ TRACE_UPDATE_RENDER_END("DALI_UPDATE_RENDER_THREAD_WAIT_CONDITION");
if(!mUseElapsedTimeAfterWait)
{
mSurfaceSemaphore.Release(1);
}
-void CombinedUpdateRenderController::SurfaceResized()
+void CombinedUpdateRenderController::SurfaceResized(uint32_t resizedCount)
{
ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
- if(mSurfaceResized)
+
+ if(mSurfaceResized >= resizedCount)
+ {
+ mSurfaceResized -= resizedCount;
+ }
+ else
+ {
+ mSurfaceResized = 0u;
+ }
+}
+
+void CombinedUpdateRenderController::PreCompileShader(std::string vertexShader, std::string fragmentShader)
+{
+ GraphicsInterface& graphics = mAdaptorInterfaces.GetGraphicsInterface();
+
+ Graphics::ShaderCreateInfo vertexShaderCreateInfo;
+ vertexShaderCreateInfo.SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
+ vertexShaderCreateInfo.SetSourceMode(Graphics::ShaderSourceMode::TEXT);
+ const std::vector<char>& vertexShaderSrc = StringToVector(std::move(vertexShader));
+ vertexShaderCreateInfo.SetSourceSize(vertexShaderSrc.size());
+ vertexShaderCreateInfo.SetSourceData(static_cast<const void*>(vertexShaderSrc.data()));
+ auto vertexGraphicsShader = graphics.GetController().CreateShader(vertexShaderCreateInfo, nullptr);
+
+ Graphics::ShaderCreateInfo fragmentShaderCreateInfo;
+ fragmentShaderCreateInfo.SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
+ fragmentShaderCreateInfo.SetSourceMode(Graphics::ShaderSourceMode::TEXT);
+ const std::vector<char>& fragmentShaderSrc = StringToVector(std::move(fragmentShader));
+ fragmentShaderCreateInfo.SetSourceSize(fragmentShaderSrc.size());
+ fragmentShaderCreateInfo.SetSourceData(static_cast<const void*>(fragmentShaderSrc.data()));
+ auto fragmentGraphicsShader = graphics.GetController().CreateShader(fragmentShaderCreateInfo, nullptr);
+
+ std::vector<Graphics::ShaderState> shaderStates{
+ Graphics::ShaderState()
+ .SetShader(*vertexGraphicsShader.get())
+ .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
+ Graphics::ShaderState()
+ .SetShader(*fragmentGraphicsShader.get())
+ .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
+
+ auto createInfo = Graphics::ProgramCreateInfo();
+ createInfo.SetShaderState(shaderStates);
+
+ auto graphicsProgram = graphics.GetController().CreateProgram(createInfo, nullptr);
+ ShaderPreCompiler::Get().AddPreCompiledProgram(std::move(graphicsProgram));
+}
+
+void CombinedUpdateRenderController::CancelPreCompile()
+{
+ if(mIsPreCompileCancelled == FALSE)
{
- mSurfaceResized--;
+ mIsPreCompileCancelled = TRUE;
+ ShaderPreCompiler::Get().Awake();
}
}
{
ConditionalWait::ScopedLock lock(mUpdateRenderThreadWaitCondition);
mPostRendering = FALSE;
+ CancelPreCompile();
mUpdateRenderThreadWaitCondition.Notify(lock);
}