/*
- * 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.
#include <memory.h>
// INTERNAL INCLUDES
-#include <dali/devel-api/threading/thread-pool.h>
#include <dali/integration-api/core.h>
#include <dali/internal/common/ordered-set.h>
#include <dali/internal/render/renderers/pipeline-cache.h>
#include <dali/internal/render/renderers/render-frame-buffer.h>
#include <dali/internal/render/renderers/render-texture.h>
-#include <dali/internal/render/renderers/shader-cache.h>
#include <dali/internal/render/renderers/uniform-buffer-manager.h>
#include <dali/internal/render/renderers/uniform-buffer.h>
#include <dali/internal/render/shaders/program-controller.h>
namespace
{
+// TODO : Cache clean logic have some problem now. Just block it until bug resolved
+//constexpr uint32_t CACHE_CLEAN_FRAME_COUNT = 600u; // 60fps * 10sec
+
inline Graphics::Rect2D RecalculateScissorArea(const Graphics::Rect2D& scissorArea, int orientation, const Rect<int32_t>& viewportRect)
{
Graphics::Rect2D newScissorArea;
: graphicsController(graphicsController),
renderAlgorithms(graphicsController),
programController(graphicsController),
- shaderCache(graphicsController),
depthBufferAvailable(depthBufferAvailableParam),
stencilBufferAvailable(stencilBufferAvailableParam),
partialUpdateAvailable(partialUpdateAvailableParam)
{
- // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
- threadPool = std::make_unique<Dali::ThreadPool>();
- threadPool->Initialize(1u);
-
uniformBufferManager = std::make_unique<Render::UniformBufferManager>(&graphicsController);
pipelineCache = std::make_unique<Render::PipelineCache>(graphicsController);
}
~Impl()
{
- threadPool.reset(nullptr); // reset now to maintain correct destruction order
rendererContainer.Clear(); // clear now before the pipeline cache is deleted
}
OrderedSet<Render::RenderTracker> mRenderTrackers; ///< List of owned render trackers
- ProgramController programController; ///< Owner of the programs
- Render::ShaderCache shaderCache; ///< The cache for the graphics shaders
+ OwnerKeyContainer<Render::Texture> textureDiscardQueue; ///< Discarded textures
+
+ ProgramController programController; ///< Owner of the programs
std::unique_ptr<Render::UniformBufferManager> uniformBufferManager; ///< The uniform buffer manager
std::unique_ptr<Render::PipelineCache> pipelineCache;
Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available
- std::unique_ptr<Dali::ThreadPool> threadPool; ///< The thread pool
- Vector<Graphics::Texture*> boundTextures; ///< The textures bound for rendering
- Vector<Graphics::Texture*> textureDependencyList; ///< The dependency list of bound textures
- Vector<Render::TextureKey> updatedTextures{}; ///< The updated texture list
+ Vector<Render::TextureKey> updatedTextures{}; ///< The updated texture list
uint32_t frameCount{0u}; ///< The current frame count
BufferIndex renderBufferIndex{SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX}; ///< The index of the buffer to read from;
void RenderManager::AddRenderer(const Render::RendererKey& renderer)
{
// Initialize the renderer as we are now in render thread
- renderer->Initialize(mImpl->graphicsController, mImpl->programController, mImpl->shaderCache, *(mImpl->uniformBufferManager.get()), *(mImpl->pipelineCache.get()));
+ renderer->Initialize(mImpl->graphicsController, mImpl->programController, *(mImpl->uniformBufferManager.get()), *(mImpl->pipelineCache.get()));
mImpl->rendererContainer.PushBack(renderer);
}
{
DALI_ASSERT_DEBUG(textureKey && "Trying to add empty texture key");
- textureKey->Initialize(mImpl->graphicsController);
+ textureKey->Initialize(mImpl->graphicsController, *this);
mImpl->textureContainer.PushBack(textureKey);
mImpl->updatedTextures.PushBack(textureKey);
}
if(iter != mImpl->textureContainer.End())
{
+ // Destroy texture.
textureKey->Destroy();
- mImpl->textureContainer.Erase(iter); // Texture found; now destroy it
+
+ // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
+ mImpl->textureDiscardQueue.PushBack(mImpl->textureContainer.Release(iter));
}
}
-void RenderManager::UploadTexture(const Render::TextureKey& textureKey, PixelDataPtr pixelData, const Texture::UploadParams& params)
+void RenderManager::UploadTexture(const Render::TextureKey& textureKey, PixelDataPtr pixelData, const Graphics::UploadParams& params)
{
DALI_ASSERT_DEBUG(textureKey && "Trying to upload to empty texture key");
textureKey->Upload(pixelData, params);
mImpl->updatedTextures.PushBack(textureKey);
}
+void RenderManager::SetTextureSize(const Render::TextureKey& textureKey, const Dali::ImageDimensions& size)
+{
+ DALI_ASSERT_DEBUG(textureKey && "Trying to set size on empty texture key");
+ textureKey->SetWidth(size.GetWidth());
+ textureKey->SetHeight(size.GetHeight());
+}
+
+void RenderManager::SetTextureFormat(const Render::TextureKey& textureKey, Dali::Pixel::Format pixelFormat)
+{
+ DALI_ASSERT_DEBUG(textureKey && "Trying to set pixel format on empty texture key");
+ textureKey->SetPixelFormat(pixelFormat);
+}
+
void RenderManager::SetTextureUpdated(const Render::TextureKey& textureKey)
{
DALI_ASSERT_DEBUG(textureKey && "Trying to set updated on empty texture key");
// Reset pipeline cache before rendering
mImpl->pipelineCache->PreRender();
+ // Let we collect reference counts during CACHE_CLEAN_FRAME_COUNT frames.
+ // TODO : Cache clean logic have some problem now. Just block it until bug resolved
+ /*
+ if(mImpl->frameCount % CACHE_CLEAN_FRAME_COUNT == 1)
+ {
+ mImpl->programController.ResetReferenceCount();
+ }
+ */
+
mImpl->commandBufferSubmitted = false;
}
if(!sceneObject || sceneObject->IsRenderingSkipped())
{
// We don't need to calculate dirty rects
+ if(!sceneObject)
+ {
+ DALI_LOG_ERROR("Scene was empty handle. Skip pre-rendering\n");
+ }
+ else
+ {
+ DALI_LOG_RELEASE_INFO("RenderingSkipped set true. Skip pre-rendering\n");
+ }
return;
}
if(mImpl->partialUpdateAvailable == Integration::PartialUpdateAvailable::TRUE && !renderToFbo && clippingRect.IsEmpty())
{
// ClippingRect is empty. Skip rendering
+ DALI_LOG_DEBUG_INFO("ClippingRect is empty. Skip rendering\n");
return;
}
SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject();
if(!sceneObject)
{
+ DALI_LOG_ERROR("Scene was empty handle. Skip rendering\n");
return;
}
auto program = item.mRenderer->PrepareProgram(instruction);
if(program)
{
- auto memoryRequirements = program->GetUniformBlocksMemoryRequirements();
+ const auto& memoryRequirements = program->GetUniformBlocksMemoryRequirements();
totalSizeCPU += memoryRequirements.totalCpuSizeRequired;
totalSizeGPU += memoryRequirements.totalGpuSizeRequired;
targetstoPresent.emplace_back(currentRenderTarget);
- // reset the program matrices for all programs once per frame
- // this ensures we will set view and projection matrix once per program per camera
- mImpl->programController.ResetProgramMatrices();
-
- if(instruction.mFrameBuffer)
- {
- // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer.
- for(unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0)
- {
- mImpl->textureDependencyList.PushBack(instruction.mFrameBuffer->GetTexture(i0));
- }
- }
-
if(!instruction.mIgnoreRenderToFbo && (instruction.mFrameBuffer != nullptr))
{
// Offscreen buffer rendering
float(viewportRect.width),
float(viewportRect.height)});
- // Clear the list of bound textures
- mImpl->boundTextures.Clear();
-
mImpl->renderAlgorithms.ProcessRenderInstruction(
instruction,
mImpl->renderBufferIndex,
depthBufferAvailable,
stencilBufferAvailable,
- mImpl->boundTextures,
viewportRect,
clippingRect,
surfaceOrientation,
// Flush UBOs
mImpl->uniformBufferManager->Flush(sceneObject, renderToFbo);
-
mImpl->renderAlgorithms.SubmitCommandBuffer();
mImpl->commandBufferSubmitted = true;
}
mImpl->updatedTextures.Clear();
+ // Remove discarded textures after OnRenderFinished called
+ mImpl->textureDiscardQueue.Clear();
+
mImpl->UpdateTrackers();
uint32_t count = 0u;
count += scene->GetRenderInstructions().Count(mImpl->renderBufferIndex);
}
+ // Remove unused shader and programs during CACHE_CLEAN_FRAME_COUNT frames.
+ // TODO : Cache clean logic have some problem now. Just block it until bug resolved
+ /*
+ if(mImpl->frameCount % CACHE_CLEAN_FRAME_COUNT == 0)
+ {
+ mImpl->programController.ClearUnusedCache();
+ }
+ */
+
const bool haveInstructions = count > 0u;
// If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.