}
}
}
+
+ // Finalize Render::Renderer Render for this secondary command buffer.
+ Renderer::FinishedCommandBuffer();
secondaryCommandBuffer.End();
}
uint32_t totalUniformBufferViewCount = 0u;
#endif
+ static Render::UniformBufferView* sDummyView = nullptr;
+
for(auto& item : mImpl->mSharedUniformBlockBufferViews)
{
const auto& program = *item.first.program;
auto& sharedUniformBlock = *item.first.sharedUniformBlock;
uint32_t blockSize = item.first.blockSize;
- item.second = uniformBufferManager.CreateUniformBufferView(blockSize, false);
+ item.second = uniformBufferManager.CreateUniformBufferView(sDummyView, blockSize, false);
if(DALI_UNLIKELY(!item.second))
{
static Dali::Internal::MemoryPoolObjectAllocator<Renderer> gRenderRendererMemoryPool;
return gRenderRendererMemoryPool;
}
+
+Render::UboViewContainer& GetUboViewList()
+{
+ static Render::UboViewContainer gUboViews;
+ return gUboViews;
+}
} // namespace
void Renderer::PrepareCommandBuffer()
// todo : Fill here as many caches as we can store for reduce the number of command buffers
}
+void Renderer::FinishedCommandBuffer()
+{
+ // Ensure to remove current frame's UBOView list now.
+ GetUboViewList().Clear();
+}
+
RendererKey Renderer::NewKey(SceneGraph::RenderDataProvider* dataProvider,
Render::Geometry* geometry,
uint32_t blendingBitmask,
const Vector3& size,
std::size_t nodeIndex)
{
- auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
+ const auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
const auto& programRequirements = program->GetUniformBlocksMemoryRequirements();
// Allocate UBO view per each block (include standalone block)
auto blockCount = programRequirements.blockCount;
- std::vector<std::unique_ptr<UniformBufferView>> uboViews;
- uboViews.resize(blockCount);
+ auto& uboViews = GetUboViewList();
+ uboViews.Resize(blockCount);
// Prepare bindings
auto uboCount = reflection.GetUniformBlockCount();
mUniformBufferBindings[i].buffer = sharedUniformBufferViewPtr->GetBuffer();
mUniformBufferBindings[i].offset = sharedUniformBufferViewPtr->GetOffset();
- uboViews[i].reset(nullptr);
+ delete uboViews[i];
+ uboViews[i] = nullptr;
}
else
{
// If this block is NOT shared, create new uboView.
- auto uniformBufferView = mUniformBufferManager->CreateUniformBufferView(programRequirements.blockSize[i], standaloneUniforms);
+ auto uniformBufferView = mUniformBufferManager->CreateUniformBufferView(uboViews[i], programRequirements.blockSize[i], standaloneUniforms);
mUniformBufferBindings[i].buffer = uniformBufferView->GetBuffer();
mUniformBufferBindings[i].offset = uniformBufferView->GetOffset();
- uboViews[i].reset(uniformBufferView.release());
+ uboViews[i] = uniformBufferView.release();
}
}
}
// 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(!uboViews.empty())
+ if(!uboViews.IsEmpty())
{
// Write default uniforms
WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), uboViews, modelMatrix);
}
template<class T>
-bool Renderer::WriteDefaultUniformV2(const Graphics::UniformInfo* uniformInfo, const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews, const T& data)
+bool Renderer::WriteDefaultUniformV2(const Graphics::UniformInfo* uniformInfo, const Render::UboViewContainer& uboViews, const T& data)
{
if(uniformInfo && !uniformInfo->name.empty())
{
// Test for non-null view first
- auto ubo = uboViews[uniformInfo->bufferIndex].get();
+ auto* ubo = uboViews[uniformInfo->bufferIndex];
if(ubo == nullptr) // Uniform belongs to shared UniformBlock, can't overwrite
{
ubo.Write(data, size, uniformInfo.offset);
}
-void Renderer::FillUniformBuffer(Program& program,
- const SceneGraph::RenderInstruction& instruction,
- const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews,
- BufferIndex updateBufferIndex,
- std::size_t nodeIndex)
+void Renderer::FillUniformBuffer(Program& program,
+ const SceneGraph::RenderInstruction& instruction,
+ const Render::UboViewContainer& uboViews,
+ BufferIndex updateBufferIndex,
+ std::size_t nodeIndex)
{
for(auto& iter : mUniformIndexMaps[nodeIndex])
{
}
case UniformIndexMap::State::INITIALIZED:
{
- Render::UniformBufferView* ubo = uboViews[uniform.uniformBlockIndex].get();
+ auto* ubo = uboViews[uniform.uniformBlockIndex];
if(ubo == nullptr) // Uniform belongs to shared UniformBlock, can't overwrite
{
uniform.state = UniformIndexMap::State::NOT_USED;
#include <dali/public-api/rendering/texture-set.h>
#include <dali/public-api/signals/render-callback.h>
+#include <dali/devel-api/common/owner-container.h>
#include <dali/graphics-api/graphics-controller.h>
#include <dali/integration-api/debug.h>
#include <dali/internal/common/blending-options.h>
using PipelineCachePtr = PipelineCacheL2Container::iterator;
using RendererKey = MemoryPoolKey<Render::Renderer>;
+
+using UboViewContainer = Dali::OwnerContainer<Render::UniformBufferView*>;
} //namespace Render
} //namespace Internal
*/
static void PrepareCommandBuffer();
+ /**
+ * @brief Global static finalize for Render::Renderer after new CommandBuffer's Render fill finished.
+ */
+ static void FinishedCommandBuffer();
+
/**
* Create a new renderer instance
* @param[in] dataProviders The data providers for the renderer
const T& data);
template<class T>
- bool WriteDefaultUniformV2(const Graphics::UniformInfo* uniformInfo,
- const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews,
- const T& data);
+ bool WriteDefaultUniformV2(const Graphics::UniformInfo* uniformInfo,
+ const Render::UboViewContainer& uboViews,
+ const T& data);
template<class T>
void WriteUniform(Render::UniformBufferView& ubo,
* @param[in] updateBufferIndex update buffer index
* @param[in] nodeIndex Index of node/renderer pair in mUniformIndexMaps
*/
- void FillUniformBuffer(Program& program,
- const SceneGraph::RenderInstruction& instruction,
- const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews,
- BufferIndex updateBufferIndex,
- std::size_t nodeIndex);
+ void FillUniformBuffer(Program& program,
+ const SceneGraph::RenderInstruction& instruction,
+ const Render::UboViewContainer& uboViews,
+ BufferIndex updateBufferIndex,
+ std::size_t nodeIndex);
/**
* @brief Write dynamic (i.e. not default) uniform into the buffer
mCurrentUBOSet = FindSetForScene(scene);
}
-Graphics::UniquePtr<UniformBufferView> UniformBufferManager::CreateUniformBufferView(uint32_t size, bool emulated)
+Graphics::UniquePtr<UniformBufferView> UniformBufferManager::CreateUniformBufferView(UniformBufferView*& oldView, uint32_t size, bool emulated)
{
// Allocate offset of given UBO (allocation strategy may reuse memory)
// Use current offset and increment it after
auto offset = ubo->GetCurrentOffset();
- auto retval = Graphics::UniquePtr<UniformBufferView>(UniformBufferView::New(*ubo.get(), offset));
+ auto retval = Graphics::UniquePtr<UniformBufferView>(UniformBufferView::TryRecycle(oldView, *ubo.get(), offset));
// make sure new offset will meet alignment requirements
uint32_t alignedSize = ubo->AlignSize(size);
#define DALI_INTERNAL_UNIFORM_BUFFER_MANAGER_H
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
void ContextDestroyed();
- Graphics::UniquePtr<UniformBufferView> CreateUniformBufferView(uint32_t size, bool emulated = true);
+ Graphics::UniquePtr<UniformBufferView> CreateUniformBufferView(UniformBufferView*& oldView, uint32_t size, bool emulated = true);
/**
* @brief Registers scene with the manager
return new(GetUboViewMemoryPool().AllocateRaw()) UniformBufferView(ubo, offset);
}
+UniformBufferView* UniformBufferView::TryRecycle(UniformBufferView*& oldView, UniformBufferV2& ubo, uint32_t offset)
+{
+ auto* ptr = oldView;
+ if(ptr)
+ {
+ oldView = nullptr;
+ ptr->mUniformBuffer = &ubo;
+ ptr->mOffset = offset;
+ return ptr;
+ }
+ return UniformBufferView::New(ubo, offset);
+}
+
void UniformBufferView::ResetMemoryPool()
{
GetUboViewMemoryPool().ResetMemoryPool();
*/
static UniformBufferView* New(UniformBufferV2& ubo, uint32_t offset);
+ /**
+ * Try to recycle input view. If recycle failed, inputed view memory freed, and new UniformView created.
+ * @param[in, out] oldView The old buffer view that want to recycle. Set as nullptr after recycle done.
+ * @param[in] ubo The buffer for this view
+ * @param[in] offset The offset of this view from ubo
+ * @return A UniformBufferView that recycled, or newly created.
+ */
+ static UniformBufferView* TryRecycle(UniformBufferView*& oldView, UniformBufferV2& ubo, uint32_t offset);
+
/**
* Clear memory pool of UniformBufferView.
* This should be called at the begin of Core.