From: Adam Bialogonski Date: Wed, 7 Jul 2021 14:57:25 +0000 (+0100) Subject: Added GLES command buffer pool X-Git-Tag: dali_2.0.35~1^2~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git;a=commitdiff_plain;h=08384ee586769b0546b874fe8c8dc4fda815879c Added GLES command buffer pool Added GLES command buffer pool to improve internal commands and transient memory allocation Change-Id: Iad386cdf8fd88aa7b7676df706163e87b6eb74ba --- diff --git a/dali/internal/graphics/gles-impl/egl-graphics-controller-debug.cpp b/dali/internal/graphics/gles-impl/egl-graphics-controller-debug.cpp index ff11704..9ee5721 100644 --- a/dali/internal/graphics/gles-impl/egl-graphics-controller-debug.cpp +++ b/dali/internal/graphics/gles-impl/egl-graphics-controller-debug.cpp @@ -86,9 +86,12 @@ std::string DumpStencilOp(Graphics::StencilOp stencilOp) void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer) { - bool first{true}; - for(auto& cmd : commandBuffer->GetCommands()) + bool first{true}; + uint32_t count = 0u; + const auto command = commandBuffer->GetCommands(count); + for(auto i = 0u; i < count; ++i) { + auto& cmd = command[i]; if(!first) { fprintf(output, ","); @@ -251,8 +254,9 @@ void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer) cmd.beginRenderPass.renderArea.height); fprintf(output, "\"clearValues\":["); bool firstV = true; - for(auto& value : cmd.beginRenderPass.clearValues) + for(auto i = 0u; i < cmd.beginRenderPass.clearValuesCount; ++i) { + auto value = cmd.beginRenderPass.clearValues.Ptr()[i]; if(!firstV) { fprintf(output, ","); @@ -277,14 +281,15 @@ void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer) { fprintf(output, "{\"Cmd\":\"EXECUTE_COMMAND_BUFFERS\",\n\"buffers\":["); bool firstBuf{true}; - for(auto& buf : cmd.executeCommandBuffers.buffers) + for(auto i = 0u; i < cmd.executeCommandBuffers.buffersCount; ++i) { + const auto buf = cmd.executeCommandBuffers.buffers.Ptr()[i]; if(!firstBuf) { fprintf(output, ", "); } firstBuf = false; - DumpCommandBuffer(output, static_cast(buf)); + DumpCommandBuffer(output, buf); } fprintf(output, "]\n}"); break; diff --git a/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp b/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp index bd0d499..eec74af 100644 --- a/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp +++ b/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp @@ -144,11 +144,20 @@ void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo) void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget) { - // Use command buffer to execute presentation (we should pool it) - CommandBufferCreateInfo info; - info.SetLevel(CommandBufferLevel::PRIMARY); - info.fixedCapacity = 1; // only one command - auto presentCommandBuffer = new GLES::CommandBuffer(info, *this); + GLES::CommandBuffer* presentCommandBuffer{nullptr}; + if(mPresentationCommandBuffers.empty()) + { + CommandBufferCreateInfo info; + info.SetLevel(CommandBufferLevel::PRIMARY); + info.fixedCapacity = 1; // only one command + presentCommandBuffer = new GLES::CommandBuffer(info, *this); + } + else + { + presentCommandBuffer = const_cast(mPresentationCommandBuffers.front()); + presentCommandBuffer->Reset(); + mPresentationCommandBuffers.pop(); + } presentCommandBuffer->PresentRenderTarget(static_cast(renderTarget)); SubmitInfo submitInfo; submitInfo.cmdBuffer = {presentCommandBuffer}; @@ -368,8 +377,11 @@ void EglGraphicsController::ProcessCreateQueues() void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer) { - for(auto& cmd : commandBuffer.GetCommands()) + auto count = 0u; + const auto commands = commandBuffer.GetCommands(count); + for(auto i = 0u; i < count; ++i) { + auto& cmd = commands[i]; // process command switch(cmd.type) { @@ -380,19 +392,19 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm } case GLES::CommandType::BIND_TEXTURES: { - mCurrentContext->BindTextures(cmd.bindTextures.textureBindings); + mCurrentContext->BindTextures(cmd.bindTextures.textureBindings.Ptr(), cmd.bindTextures.textureBindingsCount); break; } case GLES::CommandType::BIND_VERTEX_BUFFERS: { - auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings; - mCurrentContext->BindVertexBuffers(bindings); + auto bindings = cmd.bindVertexBuffers.vertexBufferBindings.Ptr(); + mCurrentContext->BindVertexBuffers(bindings, cmd.bindVertexBuffers.vertexBufferBindingsCount); break; } case GLES::CommandType::BIND_UNIFORM_BUFFER: { auto& bindings = cmd.bindUniformBuffers; - mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding); + mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindingsCount ? bindings.uniformBufferBindings.Ptr() : nullptr, bindings.uniformBufferBindingsCount, bindings.standaloneUniformsBufferBinding); break; } case GLES::CommandType::BIND_INDEX_BUFFER: @@ -535,8 +547,12 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm { ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent); - // push this command buffer to the discard queue - mDiscardCommandBufferQueue.push(const_cast(&commandBuffer)); + // The command buffer will be pushed into the queue of presentation command buffers + // for further reuse. + if(commandBuffer.GetCreateInfo().fixedCapacity == 1) + { + mPresentationCommandBuffers.push(&commandBuffer); + } break; } case GLES::CommandType::EXECUTE_COMMAND_BUFFERS: @@ -545,8 +561,10 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm // todo: check validity of the secondaries // there are operations which are illigal to be done // within secondaries. - for(auto& buf : cmd.executeCommandBuffers.buffers) + auto buffers = cmd.executeCommandBuffers.buffers.Ptr(); + for(auto j = 0u; j < cmd.executeCommandBuffers.buffersCount; ++j) { + auto& buf = buffers[j]; ProcessCommandBuffer(*static_cast(buf)); } break; @@ -557,10 +575,6 @@ void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& comm void EglGraphicsController::ProcessCommandQueues() { - // TODO: command queue per context, sync between queues should be - // done externally - currentFramebuffer = nullptr; - DUMP_FRAME_START(); while(!mCommandQueue.empty()) diff --git a/dali/internal/graphics/gles-impl/egl-graphics-controller.h b/dali/internal/graphics/gles-impl/egl-graphics-controller.h index 2491aba..a792eea 100644 --- a/dali/internal/graphics/gles-impl/egl-graphics-controller.h +++ b/dali/internal/graphics/gles-impl/egl-graphics-controller.h @@ -772,8 +772,7 @@ private: bool mIsShuttingDown{false}; ///< Indicates whether the controller is shutting down - // todo: to be removed after renderpass - const Graphics::Framebuffer* currentFramebuffer{nullptr}; + std::queue mPresentationCommandBuffers{}; ///< Queue of reusable command buffers used by presentation engine }; } // namespace Graphics diff --git a/dali/internal/graphics/gles-impl/gles-context.cpp b/dali/internal/graphics/gles-impl/gles-context.cpp index 89a6010..d5064a7 100644 --- a/dali/internal/graphics/gles-impl/gles-context.cpp +++ b/dali/internal/graphics/gles-impl/gles-context.cpp @@ -322,11 +322,13 @@ void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall) } } -void Context::BindTextures(const std::vector& bindings) +void Context::BindTextures(const Graphics::TextureBinding* bindings, uint32_t count) { // for each texture allocate slot - for(const auto& binding : bindings) + for(auto i = 0u; i < count; ++i) { + auto& binding = bindings[i]; + // Resize binding array if needed if(mImpl->mCurrentTextureBindings.size() <= binding.binding) { @@ -337,14 +339,14 @@ void Context::BindTextures(const std::vector& bindings } } -void Context::BindVertexBuffers(const std::vector& bindings) +void Context::BindVertexBuffers(const GLES::VertexBufferBindingDescriptor* bindings, uint32_t count) { - if(bindings.size() > mImpl->mCurrentVertexBufferBindings.size()) + if(count > mImpl->mCurrentVertexBufferBindings.size()) { - mImpl->mCurrentVertexBufferBindings.resize(bindings.size()); + mImpl->mCurrentVertexBufferBindings.resize(count); } // Copy only set slots - std::copy_if(bindings.begin(), bindings.end(), mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) { + std::copy_if(bindings, bindings + count, mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) { return (nullptr != item.buffer); }); } @@ -360,21 +362,22 @@ void Context::BindPipeline(const GLES::Pipeline* newPipeline) mImpl->mNewPipeline = &newPipeline->GetPipeline(); } -void Context::BindUniformBuffers(const std::vector& uboBindings, - const UniformBufferBindingDescriptor& standaloneBindings) +void Context::BindUniformBuffers(const UniformBufferBindingDescriptor* uboBindings, + uint32_t uboCount, + const UniformBufferBindingDescriptor& standaloneBindings) { if(standaloneBindings.buffer) { mImpl->mCurrentStandaloneUBOBinding = standaloneBindings; } - if(uboBindings.size() >= mImpl->mCurrentUBOBindings.size()) + if(uboCount >= mImpl->mCurrentUBOBindings.size()) { - mImpl->mCurrentUBOBindings.resize(uboBindings.size() + 1); + mImpl->mCurrentUBOBindings.resize(uboCount + 1); } - auto it = uboBindings.begin(); - for(auto i = 0u; i < uboBindings.size(); ++i) + auto it = uboBindings; + for(auto i = 0u; i < uboCount; ++i) { if(it->buffer) { @@ -554,22 +557,24 @@ void Context::BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin) // Something goes wrong here if Alpha mask is GL_TRUE ColorMask(true); + const auto clearValues = renderPassBegin.clearValues.Ptr(); + if(!mImpl->mGlStateCache.mClearColorSet || - mImpl->mGlStateCache.mClearColor.r != renderPassBegin.clearValues[0].color.r || - mImpl->mGlStateCache.mClearColor.g != renderPassBegin.clearValues[0].color.g || - mImpl->mGlStateCache.mClearColor.b != renderPassBegin.clearValues[0].color.b || - mImpl->mGlStateCache.mClearColor.a != renderPassBegin.clearValues[0].color.a) + mImpl->mGlStateCache.mClearColor.r != clearValues[0].color.r || + mImpl->mGlStateCache.mClearColor.g != clearValues[0].color.g || + mImpl->mGlStateCache.mClearColor.b != clearValues[0].color.b || + mImpl->mGlStateCache.mClearColor.a != clearValues[0].color.a) { - gl.ClearColor(renderPassBegin.clearValues[0].color.r, - renderPassBegin.clearValues[0].color.g, - renderPassBegin.clearValues[0].color.b, - renderPassBegin.clearValues[0].color.a); + gl.ClearColor(clearValues[0].color.r, + clearValues[0].color.g, + clearValues[0].color.b, + clearValues[0].color.a); mImpl->mGlStateCache.mClearColorSet = true; - mImpl->mGlStateCache.mClearColor = Vector4(renderPassBegin.clearValues[0].color.r, - renderPassBegin.clearValues[0].color.g, - renderPassBegin.clearValues[0].color.b, - renderPassBegin.clearValues[0].color.a); + mImpl->mGlStateCache.mClearColor = Vector4(clearValues[0].color.r, + clearValues[0].color.g, + clearValues[0].color.b, + clearValues[0].color.a); } } diff --git a/dali/internal/graphics/gles-impl/gles-context.h b/dali/internal/graphics/gles-impl/gles-context.h index 973536a..a4c3c8b 100644 --- a/dali/internal/graphics/gles-impl/gles-context.h +++ b/dali/internal/graphics/gles-impl/gles-context.h @@ -72,7 +72,7 @@ public: * @param[in] bindings List of bindings * */ - void BindTextures(const std::vector& bindings); + void BindTextures(const Graphics::TextureBinding* bindings, uint32_t count); /** * @brief Vertex buffers to bind @@ -81,7 +81,7 @@ public: * currently processed and copied into the local storage. */ - void BindVertexBuffers(const std::vector& bindings); + void BindVertexBuffers(const GLES::VertexBufferBindingDescriptor* bindings, uint32_t count); /** * @brief Binds index buffer @@ -102,7 +102,7 @@ public: * @param[in] uboBindings real UBO binfins * @param[in] standaloneBindings emulated (legacy) UBO object */ - void BindUniformBuffers(const std::vector& uboBindings, const UniformBufferBindingDescriptor& standaloneBindings); + void BindUniformBuffers(const UniformBufferBindingDescriptor* uboBindings, uint32_t uboCount, const UniformBufferBindingDescriptor& standaloneBindings); /** * @brief Resolves blend state on the currently attached pipeline diff --git a/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.cpp b/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.cpp index b79607b..7cc24f8 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.cpp +++ b/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.cpp @@ -29,9 +29,199 @@ namespace Dali::Graphics::GLES { +class CommandPool +{ + static const uint32_t COMMAND_POOL_DEFAULT_INCREMENT = 1024 * 32; // 32kb banks + static const uint32_t MEMORY_POOL_DEFAULT_INCREMENT = 1024; // 4kb memory pool increment + static const uint32_t MEMORY_POOL_DEFAULT_ALIGNMENT = 64; // 64bytes alignment + + template + struct Block + { + Block() = default; + ~Block() + { + if(ptr) + { + free(ptr); + } + } + + T* ptr{nullptr}; + uint32_t dataSize{0u}; + uint32_t capacity{0u}; + inline T& operator[](int index) const + { + return ptr[index]; + } + + inline void clear() + { + free(ptr); + capacity = 0; + dataSize = 0; + } + + inline void resize(int newSize) + { + ptr = reinterpret_cast(realloc(ptr, newSize * sizeof(T))); + capacity = newSize; + dataSize = newSize; + } + + inline T* data() const + { + return ptr; + } + + inline uint32_t size() const + { + return dataSize; + } + }; + // This memory pool guarantees all items will be placed + // in the continuous memory area but returned pointers are relative + // and require translation before using + template + struct MemoryPool + { + Block data; + inline T& operator[](int index) + { + return data[index]; + } + MemoryPool() = default; + + IndirectPtr Allocate(uint32_t count) + { + // set fixed capacity + if(fixedCapacity && data.size() != fixedCapacity) + { + data.resize(fixedCapacity); + totalCapacity = data.size(); + } + + // or resize dynamically + else if(data.size() <= offset + count) + { + data.resize(data.size() + Increment); + + // update base pointer, required for address translation + totalCapacity = data.size(); + } + + basePtr = data.data(); + + IndirectPtr retval{uint32_t(uintptr_t(&data[offset]) - uintptr_t(basePtr)), &basePtr}; + size += count; + offset += count; + + // align offset if needed (only if type size is 1) + if(Alignment && sizeof(T) == 1) + { + offset = ((offset / Alignment) * Alignment) + ((offset % Alignment) ? Alignment : 0); + } + return retval; + } + + // Rolls back pool + void Rollback() + { + offset = 0; + size = 0; + } + + // Discards all data and storage + void Clear() + { + data.clear(); + totalCapacity = 0; + offset = 0; + size = 0; + } + + uint32_t offset{0u}; + uint32_t totalCapacity{0u}; + uint32_t size{0u}; + uint32_t increment{Increment}; + uint32_t alignment{Alignment}; + uint32_t fixedCapacity{0u}; + void* basePtr{nullptr}; + }; + + MemoryPool memoryPool; + MemoryPool commandPool; + +public: + CommandPool() = default; + CommandPool(uint32_t fixedCapacity) + { + commandPool.fixedCapacity = fixedCapacity; + memoryPool.fixedCapacity = fixedCapacity * 1024; + } + + /** + * Return value may become invalid if pool is resized (by allocating another command) + * @param type + * @return + */ + Command* AllocateCommand(CommandType type) + { + auto command = commandPool.Allocate(1); + command->type = type; + auto* cmd = command.Ptr(); + return cmd; + } + + template + IndirectPtr Allocate(uint32_t count) + { + const auto typeSize = sizeof(T); + const auto memoryRequired = typeSize * count; + auto ptr = memoryPool.Allocate(memoryRequired); + + // Convert generic pointer and return + return IndirectPtr{ptr.ptr, ptr.base}; + } + + // New (should not be needed) + template + T* New(uint32_t count) + { + auto ptr = Allocate(count); + for(auto i = 0u; i < count; ++i) + { + new(&ptr[i]) T(); + } + return ptr; + } + + // TODO: explicit delete? + void Rollback(bool discard) + { + if(discard) + { + commandPool.Clear(); + memoryPool.Clear(); + } + else + { + commandPool.Rollback(); + memoryPool.Rollback(); + } + } + + const Command* GetCommands(uint32_t& size) const + { + size = commandPool.size; + return commandPool.data.ptr; + } +}; + CommandBuffer::CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller) : CommandBufferResource(createInfo, controller) { + mCommandPool = std::make_unique(createInfo.fixedCapacity); } CommandBuffer::~CommandBuffer() = default; @@ -40,26 +230,39 @@ void CommandBuffer::BindVertexBuffers(uint32_t first std::vector buffers, std::vector offsets) { - mCommands.emplace_back(CommandType::BIND_VERTEX_BUFFERS); - auto& bindings = mCommands.back().bindVertexBuffers.vertexBufferBindings; - if(bindings.size() < firstBinding + buffers.size()) + auto command = mCommandPool->AllocateCommand(CommandType::BIND_VERTEX_BUFFERS); + command->bindVertexBuffers.vertexBufferBindingsCount = firstBinding + buffers.size(); + auto pBindings = mCommandPool->Allocate(firstBinding + buffers.size()); + + command->bindVertexBuffers.vertexBufferBindings = pBindings; + auto index = firstBinding; + for(auto& buf : buffers) { - bindings.resize(firstBinding + buffers.size()); - auto index = firstBinding; - for(auto& buf : buffers) - { - bindings[index].buffer = static_cast(buf); - bindings[index].offset = offsets[index - firstBinding]; - index++; - } + pBindings[index].buffer = static_cast(buf); + pBindings[index].offset = offsets[index - firstBinding]; + index++; } } void CommandBuffer::BindUniformBuffers(const std::vector& bindings) { - mCommands.emplace_back(CommandType::BIND_UNIFORM_BUFFER); - auto& cmd = mCommands.back(); + auto command = mCommandPool->AllocateCommand(CommandType::BIND_UNIFORM_BUFFER); + + auto& cmd = *command; auto& bindCmd = cmd.bindUniformBuffers; + + // temporary static set of binding slots (thread local) + static const auto MAX_UNIFORM_BUFFER_BINDINGS = 64; // TODO: this should be read from introspection + + // TODO: could use vector? + static thread_local UniformBufferBindingDescriptor sTempBindings[MAX_UNIFORM_BUFFER_BINDINGS]; + + // reset temp bindings + memset(sTempBindings, 0, sizeof(UniformBufferBindingDescriptor) * MAX_UNIFORM_BUFFER_BINDINGS); + + auto maxBinding = 0u; + + // find max binding and standalone UBO for(const auto& binding : bindings) { if(binding.buffer) @@ -74,37 +277,51 @@ void CommandBuffer::BindUniformBuffers(const std::vector= bindCmd.uniformBufferBindings.size()) - { - bindCmd.uniformBufferBindings.resize(binding.binding + 1); - } - auto& slot = bindCmd.uniformBufferBindings[binding.binding]; + auto& slot = sTempBindings[binding.binding]; slot.buffer = glesBuffer; slot.offset = binding.offset; slot.binding = binding.binding; slot.emulated = false; + maxBinding = std::max(maxBinding, binding.binding); } } } + bindCmd.uniformBufferBindings = nullptr; + bindCmd.uniformBufferBindingsCount = 0u; + + // copy data + if(maxBinding) + { + auto destBindings = mCommandPool->Allocate(maxBinding + 1); + // copy + memcpy(destBindings.Ptr(), sTempBindings, sizeof(UniformBufferBindingDescriptor) * (maxBinding + 1)); + bindCmd.uniformBufferBindings = destBindings; + bindCmd.uniformBufferBindingsCount = maxBinding + 1; + } } void CommandBuffer::BindPipeline(const Graphics::Pipeline& pipeline) { - mCommands.emplace_back(CommandType::BIND_PIPELINE); - mCommands.back().bindPipeline.pipeline = static_cast(&pipeline); + auto command = mCommandPool->AllocateCommand(CommandType::BIND_PIPELINE); + command->bindPipeline.pipeline = static_cast(&pipeline); } void CommandBuffer::BindTextures(std::vector& textureBindings) { - mCommands.emplace_back(CommandType::BIND_TEXTURES); - mCommands.back().bindTextures.textureBindings = std::move(textureBindings); + auto command = mCommandPool->AllocateCommand(CommandType::BIND_TEXTURES); + auto& bindTexturesCmd = command->bindTextures; + bindTexturesCmd.textureBindings = mCommandPool->Allocate(textureBindings.size()); + bindTexturesCmd.textureBindingsCount = textureBindings.size(); + memcpy(bindTexturesCmd.textureBindings.Ptr(), textureBindings.data(), sizeof(TextureBinding) * textureBindings.size()); } void CommandBuffer::BindSamplers(std::vector& samplerBindings) { - mCommands.emplace_back(CommandType::BIND_SAMPLERS); - mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings); + auto command = mCommandPool->AllocateCommand(CommandType::BIND_SAMPLERS); + auto& bindSamplersCmd = command->bindSamplers; + bindSamplersCmd.samplerBindings = mCommandPool->Allocate(samplerBindings.size()); + bindSamplersCmd.samplerBindingsCount = samplerBindings.size(); + memcpy(bindSamplersCmd.samplerBindings.Ptr(), samplerBindings.data(), sizeof(TextureBinding) * samplerBindings.size()); } void CommandBuffer::BindPushConstants(void* data, @@ -117,10 +334,10 @@ void CommandBuffer::BindIndexBuffer(const Graphics::Buffer& buffer, uint32_t offset, Format format) { - mCommands.emplace_back(CommandType::BIND_INDEX_BUFFER); - mCommands.back().bindIndexBuffer.buffer = static_cast(&buffer); - mCommands.back().bindIndexBuffer.offset = offset; - mCommands.back().bindIndexBuffer.format = format; + auto command = mCommandPool->AllocateCommand(CommandType::BIND_INDEX_BUFFER); + command->bindIndexBuffer.buffer = static_cast(&buffer); + command->bindIndexBuffer.offset = offset; + command->bindIndexBuffer.format = format; } void CommandBuffer::BeginRenderPass( @@ -129,30 +346,32 @@ void CommandBuffer::BeginRenderPass( Rect2D renderArea, std::vector clearValues) { - mCommands.emplace_back(CommandType::BEGIN_RENDERPASS); - auto& cmd = mCommands.back(); + auto command = mCommandPool->AllocateCommand(CommandType::BEGIN_RENDERPASS); + auto& cmd = *command; cmd.beginRenderPass.renderPass = static_cast(renderPass); cmd.beginRenderPass.renderTarget = static_cast(renderTarget); cmd.beginRenderPass.renderArea = renderArea; - cmd.beginRenderPass.clearValues = clearValues; + + cmd.beginRenderPass.clearValues = mCommandPool->Allocate(clearValues.size()); + memcpy(cmd.beginRenderPass.clearValues.Ptr(), clearValues.data(), sizeof(ClearValue) * clearValues.size()); + cmd.beginRenderPass.clearValuesCount = clearValues.size(); } void CommandBuffer::EndRenderPass(Graphics::SyncObject* syncObject) { - mCommands.emplace_back(CommandType::END_RENDERPASS); - auto& cmd = mCommands.back(); - - cmd.endRenderPass.syncObject = static_cast(syncObject); + auto command = mCommandPool->AllocateCommand(CommandType::END_RENDERPASS); + command->endRenderPass.syncObject = static_cast(syncObject); } void CommandBuffer::ExecuteCommandBuffers(std::vector&& commandBuffers) { - mCommands.emplace_back(CommandType::EXECUTE_COMMAND_BUFFERS); - auto& cmd = mCommands.back(); - cmd.executeCommandBuffers.buffers.reserve(commandBuffers.size()); - for(auto&& item : commandBuffers) + auto command = mCommandPool->AllocateCommand(CommandType::EXECUTE_COMMAND_BUFFERS); + auto& cmd = command->executeCommandBuffers; + cmd.buffers = mCommandPool->Allocate(commandBuffers.size()); + cmd.buffersCount = commandBuffers.size(); + for(auto i = 0u; i < cmd.buffersCount; ++i) { - cmd.executeCommandBuffers.buffers.emplace_back(static_cast(item)); + cmd.buffers[i] = static_cast(commandBuffers[i]); } } @@ -162,8 +381,8 @@ void CommandBuffer::Draw( uint32_t firstVertex, uint32_t firstInstance) { - mCommands.emplace_back(CommandType::DRAW); - auto& cmd = mCommands.back().draw; + auto command = mCommandPool->AllocateCommand(CommandType::DRAW); + auto& cmd = command->draw; cmd.type = DrawCallDescriptor::Type::DRAW; cmd.draw.vertexCount = vertexCount; cmd.draw.instanceCount = instanceCount; @@ -178,8 +397,8 @@ void CommandBuffer::DrawIndexed( int32_t vertexOffset, uint32_t firstInstance) { - mCommands.emplace_back(CommandType::DRAW_INDEXED); - auto& cmd = mCommands.back().draw; + auto command = mCommandPool->AllocateCommand(CommandType::DRAW_INDEXED); + auto& cmd = command->draw; cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED; cmd.drawIndexed.firstIndex = firstIndex; cmd.drawIndexed.firstInstance = firstInstance; @@ -194,8 +413,8 @@ void CommandBuffer::DrawIndexedIndirect( uint32_t drawCount, uint32_t stride) { - mCommands.emplace_back(CommandType::DRAW_INDEXED_INDIRECT); - auto& cmd = mCommands.back().draw; + auto command = mCommandPool->AllocateCommand(CommandType::DRAW_INDEXED_INDIRECT); + auto& cmd = command->draw; cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT; cmd.drawIndexedIndirect.buffer = static_cast(&buffer); cmd.drawIndexedIndirect.offset = offset; @@ -205,25 +424,25 @@ void CommandBuffer::DrawIndexedIndirect( void CommandBuffer::Reset() { - mCommands.clear(); + mCommandPool->Rollback(false); } void CommandBuffer::SetScissor(Graphics::Rect2D value) { - mCommands.emplace_back(CommandType::SET_SCISSOR); - mCommands.back().scissor.region = value; + auto command = mCommandPool->AllocateCommand(CommandType::SET_SCISSOR); + command->scissor.region = value; } void CommandBuffer::SetScissorTestEnable(bool value) { - mCommands.emplace_back(CommandType::SET_SCISSOR_TEST); - mCommands.back().scissorTest.enable = value; + auto command = mCommandPool->AllocateCommand(CommandType::SET_SCISSOR_TEST); + command->scissorTest.enable = value; } void CommandBuffer::SetViewport(Viewport value) { - mCommands.emplace_back(CommandType::SET_VIEWPORT); - mCommands.back().viewport.region = value; + auto command = mCommandPool->AllocateCommand(CommandType::SET_VIEWPORT); + command->viewport.region = value; } void CommandBuffer::SetViewportEnable(bool value) @@ -233,35 +452,33 @@ void CommandBuffer::SetViewportEnable(bool value) void CommandBuffer::SetColorMask(bool enabled) { - mCommands.emplace_back(CommandType::SET_COLOR_MASK); - auto& cmd = mCommands.back().colorMask; - ; - cmd.enabled = enabled; + auto command = mCommandPool->AllocateCommand(CommandType::SET_COLOR_MASK); + command->colorMask.enabled = enabled; } void CommandBuffer::ClearStencilBuffer() { - mCommands.emplace_back(CommandType::CLEAR_STENCIL_BUFFER); + mCommandPool->AllocateCommand(CommandType::CLEAR_STENCIL_BUFFER); } void CommandBuffer::SetStencilTestEnable(bool stencilEnable) { - mCommands.emplace_back(CommandType::SET_STENCIL_TEST_ENABLE); - mCommands.back().stencilTest.enabled = stencilEnable; + auto command = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_TEST_ENABLE); + command->stencilTest.enabled = stencilEnable; } void CommandBuffer::SetStencilWriteMask(uint32_t writeMask) { - mCommands.emplace_back(CommandType::SET_STENCIL_WRITE_MASK); - mCommands.back().stencilWriteMask.mask = writeMask; + auto command = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_WRITE_MASK); + command->stencilWriteMask.mask = writeMask; } void CommandBuffer::SetStencilOp(Graphics::StencilOp failOp, Graphics::StencilOp passOp, Graphics::StencilOp depthFailOp) { - mCommands.emplace_back(CommandType::SET_STENCIL_OP); - auto& cmd = mCommands.back().stencilOp; + auto command = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_OP); + auto& cmd = command->stencilOp; cmd.failOp = failOp; cmd.passOp = passOp; cmd.depthFailOp = depthFailOp; @@ -271,8 +488,8 @@ void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp, uint32_t reference, uint32_t compareMask) { - mCommands.emplace_back(CommandType::SET_STENCIL_FUNC); - auto& cmd = mCommands.back().stencilFunc; + auto command = mCommandPool->AllocateCommand(CommandType::SET_STENCIL_FUNC); + auto& cmd = command->stencilFunc; cmd.compareOp = compareOp; cmd.compareMask = compareMask; cmd.reference = reference; @@ -280,34 +497,34 @@ void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp, void CommandBuffer::SetDepthCompareOp(Graphics::CompareOp compareOp) { - mCommands.emplace_back(CommandType::SET_DEPTH_COMPARE_OP); - mCommands.back().depth.compareOp = compareOp; + auto command = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_COMPARE_OP); + command->depth.compareOp = compareOp; } void CommandBuffer::SetDepthTestEnable(bool depthTestEnable) { - mCommands.emplace_back(CommandType::SET_DEPTH_TEST_ENABLE); - mCommands.back().depth.testEnabled = depthTestEnable; + auto command = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_TEST_ENABLE); + command->depth.testEnabled = depthTestEnable; } void CommandBuffer::SetDepthWriteEnable(bool depthWriteEnable) { - mCommands.emplace_back(CommandType::SET_DEPTH_WRITE_ENABLE); - mCommands.back().depth.writeEnabled = depthWriteEnable; + auto command = mCommandPool->AllocateCommand(CommandType::SET_DEPTH_WRITE_ENABLE); + command->depth.writeEnabled = depthWriteEnable; } void CommandBuffer::ClearDepthBuffer() { - mCommands.emplace_back(CommandType::CLEAR_DEPTH_BUFFER); + mCommandPool->AllocateCommand(CommandType::CLEAR_DEPTH_BUFFER); } void CommandBuffer::PresentRenderTarget(GLES::RenderTarget* renderTarget) { - mCommands.emplace_back(CommandType::PRESENT_RENDER_TARGET); - mCommands.back().presentRenderTarget.targetToPresent = renderTarget; + auto command = mCommandPool->AllocateCommand(CommandType::PRESENT_RENDER_TARGET); + command->presentRenderTarget.targetToPresent = renderTarget; } -[[nodiscard]] const std::vector& CommandBuffer::GetCommands() const +[[nodiscard]] const Command* CommandBuffer::GetCommands(uint32_t& size) const { - return mCommands; + return mCommandPool->GetCommands(size); } void CommandBuffer::DestroyResource() diff --git a/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h b/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h index f539103..8e2aeac 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h +++ b/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h @@ -28,12 +28,15 @@ #include "gles-graphics-types.h" #include "gles-sync-object.h" +#include + namespace Dali::Graphics::GLES { class Pipeline; class RenderPass; class Framebuffer; class CommandBuffer; +class CommandPool; enum class CommandType { FLUSH, @@ -79,370 +82,25 @@ static void InvokeDestructor(T& object) */ struct Command { - Command() = delete; - - Command(CommandType commandType) + Command() { - type = commandType; - switch(type) - { - case CommandType::BIND_VERTEX_BUFFERS: - { - new(&bindVertexBuffers) decltype(bindVertexBuffers); - break; - } - case CommandType::BIND_TEXTURES: - { - new(&bindTextures) decltype(bindTextures); - break; - } - case CommandType::BEGIN_RENDERPASS: - { - // run destructor - new(&beginRenderPass) decltype(beginRenderPass); - break; - } - default: - { - } - } } - ~Command() + explicit Command(CommandType commandType) { - switch(type) - { - case CommandType::BIND_VERTEX_BUFFERS: - { - InvokeDestructor(bindVertexBuffers); - break; - } - case CommandType::BIND_TEXTURES: - { - InvokeDestructor(bindTextures); - break; - } - case CommandType::BEGIN_RENDERPASS: - { - // run destructor - InvokeDestructor(beginRenderPass); - break; - } - default: - { - } - } + type = commandType; } - /** - * @brief Copy constructor - * @param[in] rhs Command - */ - Command(const Command& rhs) - { - switch(rhs.type) - { - case CommandType::BIND_VERTEX_BUFFERS: - { - new(&bindVertexBuffers) decltype(bindVertexBuffers); - bindVertexBuffers = rhs.bindVertexBuffers; - break; - } - case CommandType::BIND_INDEX_BUFFER: - { - bindIndexBuffer = rhs.bindIndexBuffer; - break; - } - case CommandType::BIND_SAMPLERS: - { - bindSamplers = rhs.bindSamplers; - break; - } - case CommandType::BIND_TEXTURES: - { - new(&bindTextures) decltype(bindTextures); - bindTextures = rhs.bindTextures; - break; - } - case CommandType::BIND_PIPELINE: - { - bindPipeline = rhs.bindPipeline; - break; - } - case CommandType::BIND_UNIFORM_BUFFER: - { - bindUniformBuffers = rhs.bindUniformBuffers; - break; - } - case CommandType::DRAW: - { - draw.type = rhs.draw.type; - draw.draw = rhs.draw.draw; - break; - } - case CommandType::DRAW_INDEXED: - { - draw.type = rhs.draw.type; - draw.drawIndexed = rhs.draw.drawIndexed; - break; - } - case CommandType::DRAW_INDEXED_INDIRECT: - { - draw.type = rhs.draw.type; - draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect; - break; - } - case CommandType::BEGIN_RENDERPASS: - { - new(&beginRenderPass) BeginRenderPassDescriptor(rhs.beginRenderPass); - break; - } - case CommandType::END_RENDERPASS: - { - endRenderPass.syncObject = rhs.endRenderPass.syncObject; - break; - } - case CommandType::EXECUTE_COMMAND_BUFFERS: - { - executeCommandBuffers = rhs.executeCommandBuffers; - break; - } - case CommandType::FLUSH: - { - // Nothing to do - break; - } - case CommandType::SET_SCISSOR: - { - scissor.region = rhs.scissor.region; - break; - } - case CommandType::SET_SCISSOR_TEST: - { - scissorTest.enable = rhs.scissorTest.enable; - break; - } - case CommandType::SET_VIEWPORT: - { - viewport.region = rhs.viewport.region; - break; - } - case CommandType::PRESENT_RENDER_TARGET: - { - presentRenderTarget = rhs.presentRenderTarget; - break; - } - case CommandType::SET_COLOR_MASK: - { - colorMask.enabled = rhs.colorMask.enabled; - break; - } - case CommandType::CLEAR_STENCIL_BUFFER: - { - break; - } - case CommandType::CLEAR_DEPTH_BUFFER: - { - break; - } - case CommandType::SET_STENCIL_TEST_ENABLE: - { - stencilTest.enabled = rhs.stencilTest.enabled; - break; - } - case CommandType::SET_STENCIL_FUNC: - { - stencilFunc.compareMask = rhs.stencilFunc.compareMask; - stencilFunc.compareOp = rhs.stencilFunc.compareOp; - stencilFunc.reference = rhs.stencilFunc.reference; - break; - } - case CommandType::SET_STENCIL_WRITE_MASK: - { - stencilWriteMask.mask = rhs.stencilWriteMask.mask; - break; - } - case CommandType::SET_STENCIL_OP: - { - stencilOp.failOp = rhs.stencilOp.failOp; - stencilOp.depthFailOp = rhs.stencilOp.depthFailOp; - stencilOp.passOp = rhs.stencilOp.passOp; - break; - } - - case CommandType::SET_DEPTH_COMPARE_OP: - { - depth.compareOp = rhs.depth.compareOp; - break; - } - case CommandType::SET_DEPTH_TEST_ENABLE: - { - depth.testEnabled = rhs.depth.testEnabled; - break; - } - case CommandType::SET_DEPTH_WRITE_ENABLE: - { - depth.writeEnabled = rhs.depth.writeEnabled; - break; - } - } - type = rhs.type; - } + ~Command() = default; /** - * @brief Move constructor + * @brief Copy constructor * @param[in] rhs Command */ - Command(Command&& rhs) noexcept - { - switch(rhs.type) - { - case CommandType::BIND_VERTEX_BUFFERS: - { - new(&bindVertexBuffers) decltype(bindVertexBuffers); - bindVertexBuffers = std::move(rhs.bindVertexBuffers); - break; - } - case CommandType::BIND_INDEX_BUFFER: - { - bindIndexBuffer = rhs.bindIndexBuffer; - break; - } - case CommandType::BIND_UNIFORM_BUFFER: - { - bindUniformBuffers = std::move(rhs.bindUniformBuffers); - break; - } - case CommandType::BIND_SAMPLERS: - { - bindSamplers = std::move(rhs.bindSamplers); - break; - } - case CommandType::BIND_TEXTURES: - { - new(&bindTextures) decltype(bindTextures); - bindTextures = std::move(rhs.bindTextures); - break; - } - case CommandType::BIND_PIPELINE: - { - bindPipeline = rhs.bindPipeline; - break; - } - case CommandType::DRAW: - { - draw.type = rhs.draw.type; - draw.draw = rhs.draw.draw; - break; - } - case CommandType::DRAW_INDEXED: - { - draw.type = rhs.draw.type; - draw.drawIndexed = rhs.draw.drawIndexed; - break; - } - case CommandType::DRAW_INDEXED_INDIRECT: - { - draw.type = rhs.draw.type; - draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect; - break; - } - case CommandType::BEGIN_RENDERPASS: - { - new(&beginRenderPass) BeginRenderPassDescriptor(std::move(rhs.beginRenderPass)); - break; - } - case CommandType::END_RENDERPASS: - { - endRenderPass.syncObject = rhs.endRenderPass.syncObject; - break; - } - case CommandType::EXECUTE_COMMAND_BUFFERS: - { - executeCommandBuffers = std::move(rhs.executeCommandBuffers); - break; - } - case CommandType::FLUSH: - { - // Nothing to do - break; - } - case CommandType::SET_SCISSOR: - { - scissor.region = rhs.scissor.region; - break; - } - case CommandType::SET_SCISSOR_TEST: - { - scissorTest.enable = rhs.scissorTest.enable; - break; - } - case CommandType::SET_VIEWPORT: - { - viewport.region = rhs.viewport.region; - break; - } - case CommandType::PRESENT_RENDER_TARGET: - { - presentRenderTarget = rhs.presentRenderTarget; - break; - } - case CommandType::SET_COLOR_MASK: - { - colorMask.enabled = rhs.colorMask.enabled; - break; - } - case CommandType::CLEAR_STENCIL_BUFFER: - { - break; - } - case CommandType::CLEAR_DEPTH_BUFFER: - { - break; - } - case CommandType::SET_STENCIL_TEST_ENABLE: - { - stencilTest.enabled = rhs.stencilTest.enabled; - break; - } - case CommandType::SET_STENCIL_FUNC: - { - stencilFunc.compareMask = rhs.stencilFunc.compareMask; - stencilFunc.compareOp = rhs.stencilFunc.compareOp; - stencilFunc.reference = rhs.stencilFunc.reference; - break; - } - case CommandType::SET_STENCIL_WRITE_MASK: - { - stencilWriteMask.mask = rhs.stencilWriteMask.mask; - break; - } - case CommandType::SET_STENCIL_OP: - { - stencilOp.failOp = rhs.stencilOp.failOp; - stencilOp.depthFailOp = rhs.stencilOp.depthFailOp; - stencilOp.passOp = rhs.stencilOp.passOp; - break; - } - - case CommandType::SET_DEPTH_COMPARE_OP: - { - depth.compareOp = rhs.depth.compareOp; - break; - } - case CommandType::SET_DEPTH_TEST_ENABLE: - { - depth.testEnabled = rhs.depth.testEnabled; - break; - } - case CommandType::SET_DEPTH_WRITE_ENABLE: - { - depth.writeEnabled = rhs.depth.writeEnabled; - break; - } - } - type = rhs.type; - } + Command(const Command& rhs) = default; + Command& operator=(const Command& rhs) = default; + Command(Command&& rhs) noexcept = delete; + Command& operator=(Command&& rhs) = delete; CommandType type{CommandType::FLUSH}; ///< Type of command @@ -450,19 +108,22 @@ struct Command { struct { - std::vector textureBindings; + IndirectPtr textureBindings; + uint32_t textureBindingsCount; } bindTextures{}; // BindSampler command struct { - std::vector samplerBindings; + IndirectPtr samplerBindings; + uint32_t samplerBindingsCount; } bindSamplers; struct { using Binding = GLES::VertexBufferBindingDescriptor; - std::vector vertexBufferBindings; + IndirectPtr vertexBufferBindings; + uint32_t vertexBufferBindingsCount; } bindVertexBuffers; struct : public IndexBufferBindingDescriptor @@ -471,7 +132,8 @@ struct Command struct { - std::vector uniformBufferBindings{}; + IndirectPtr uniformBufferBindings; + uint32_t uniformBufferBindingsCount; UniformBufferBindingDescriptor standaloneUniformsBufferBinding{}; } bindUniformBuffers; @@ -509,7 +171,8 @@ struct Command struct { - std::vector buffers; + IndirectPtr buffers; + uint32_t buffersCount; } executeCommandBuffers; struct @@ -741,7 +404,13 @@ public: */ void PresentRenderTarget(GLES::RenderTarget* renderTarget); - [[nodiscard]] const std::vector& GetCommands() const; + /** + * @brief Returns pointer to the list of command and size of the list + * + * @param[out] size Size of the list + * @return Valid pointer to the list of commands + */ + [[nodiscard]] const Command* GetCommands(uint32_t& size) const; /** * @brief Destroy the associated resources @@ -759,7 +428,7 @@ public: void DiscardResource() override; private: - std::vector mCommands; ///< List of commands in this command buffer + std::unique_ptr mCommandPool; ///< Pool of commands and transient memory }; } // namespace Dali::Graphics::GLES diff --git a/dali/internal/graphics/gles-impl/gles-graphics-types.h b/dali/internal/graphics/gles-impl/gles-graphics-types.h index 8c77721..06f95e3 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-types.h +++ b/dali/internal/graphics/gles-impl/gles-graphics-types.h @@ -2029,14 +2029,56 @@ enum class BoundTextureType }; /** + * This class stores indirect pointer, used by the CommandBuffer + * to store data allocated within resizeable pool + */ +template +struct IndirectPtr +{ + uint32_t ptr; // relative pointer + void** base; // base pointer + + inline T* operator->() + { + return reinterpret_cast((reinterpret_cast(*base) + ptr)); + } + + inline T& operator*() + { + return *reinterpret_cast((reinterpret_cast(*base) + ptr)); + } + + // Returns indirect pointer casted to requested type + T* Ptr() const + { + auto val = reinterpret_cast((reinterpret_cast(*base) + ptr)); + return val; + } + + inline T& operator[](int index) + { + return reinterpret_cast((reinterpret_cast(*base) + ptr))[index]; + } + + // Fake assignment operator for void* type + inline IndirectPtr& operator=(void* p) + { + ptr = 0; + base = nullptr; + return *this; + } +}; + +/** * The descriptor of BeginRenderPass command */ struct BeginRenderPassDescriptor { - const GLES::RenderPass* renderPass{}; - const GLES::RenderTarget* renderTarget{}; - Rect2D renderArea{}; - std::vector clearValues{}; + const GLES::RenderPass* renderPass; + const GLES::RenderTarget* renderTarget; + Rect2D renderArea; + IndirectPtr clearValues; + uint32_t clearValuesCount; }; } // namespace Dali::Graphics::GLES