/*
- * 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.
const GLES::PipelineImpl* mCurrentPipeline{nullptr}; ///< Currently bound pipeline
const GLES::PipelineImpl* mNewPipeline{nullptr}; ///< New pipeline to be set on flush
- std::vector<Graphics::TextureBinding> mCurrentTextureBindings{};
- std::vector<Graphics::SamplerBinding> mCurrentSamplerBindings{};
- GLES::IndexBufferBindingDescriptor mCurrentIndexBufferBinding{};
+ Dali::Vector<Graphics::TextureBinding> mCurrentTextureBindings{};
+
+ GLES::IndexBufferBindingDescriptor mCurrentIndexBufferBinding{};
struct VertexBufferBinding
{
std::vector<VertexBufferBindingDescriptor> mCurrentVertexBufferBindings{};
// Currently bound UBOs (check if it's needed per program!)
- std::vector<UniformBufferBindingDescriptor> mCurrentUBOBindings{};
- UniformBufferBindingDescriptor mCurrentStandaloneUBOBinding{};
+ Dali::Vector<UniformBufferBindingDescriptor> mCurrentUBOBindings{};
+ UniformBufferBindingDescriptor mCurrentStandaloneUBOBinding{};
// Current render pass and render target
const GLES::RenderTarget* mCurrentRenderTarget{nullptr};
break;
}
+ DALI_ASSERT_DEBUG(binding.texture && "GLES::Texture not assigned!");
+
auto texture = const_cast<GLES::Texture*>(static_cast<const GLES::Texture*>(binding.texture));
// Texture may not have been initialized yet...(tbm_surface timing issue?)
if(drawCall.draw.instanceCount == 0)
{
gl->DrawArrays(GLESTopology(ia->topology),
- drawCall.draw.firstVertex,
- drawCall.draw.vertexCount);
+ drawCall.draw.firstVertex,
+ drawCall.draw.vertexCount);
}
else
{
if(drawCall.drawIndexed.instanceCount == 0)
{
gl->DrawElements(GLESTopology(ia->topology),
- drawCall.drawIndexed.indexCount,
- indexBufferFormat,
- reinterpret_cast<void*>(binding.offset));
+ drawCall.drawIndexed.indexCount,
+ indexBufferFormat,
+ reinterpret_cast<void*>(binding.offset));
}
else
{
void Context::BindTextures(const Graphics::TextureBinding* bindings, uint32_t count)
{
- // for each texture allocate slot
- for(auto i = 0u; i < count; ++i)
- {
- auto& binding = bindings[i];
-
- // Resize binding array if needed
- if(mImpl->mCurrentTextureBindings.size() <= binding.binding)
- {
- mImpl->mCurrentTextureBindings.resize(binding.binding + 1);
- }
- // Store the binding details
- mImpl->mCurrentTextureBindings[binding.binding] = binding;
- }
+ // We can assume that bindings is sorted by binding number.
+ // So we can only copy the data
+ mImpl->mCurrentTextureBindings.Resize(count);
+ memcpy(mImpl->mCurrentTextureBindings.Begin(), bindings, sizeof(Graphics::TextureBinding) * count);
}
void Context::BindVertexBuffers(const GLES::VertexBufferBindingDescriptor* bindings, uint32_t count)
{
mImpl->mCurrentStandaloneUBOBinding = standaloneBindings;
}
-
- if(uboCount && uboCount > mImpl->mCurrentUBOBindings.size())
+ else
{
- mImpl->mCurrentUBOBindings.resize(uboCount);
+ mImpl->mCurrentStandaloneUBOBinding.buffer = nullptr;
}
- auto it = uboBindings;
- for(auto i = 0u; i < uboCount; ++i)
- {
- if(it->buffer)
- {
- mImpl->mCurrentUBOBindings[i] = *it;
- }
- ++it;
- }
+ // We can assume that bindings is sorted by binding number.
+ // So we can only copy the data
+ mImpl->mCurrentUBOBindings.Resize(uboCount);
+ memcpy(mImpl->mCurrentUBOBindings.Begin(), uboBindings, sizeof(UniformBufferBindingDescriptor) * uboCount);
}
void Context::ResolveBlendState()
{
ResolveStandaloneUniforms();
}
- if(!mImpl->mCurrentUBOBindings.empty())
+ if(!mImpl->mCurrentUBOBindings.Empty())
{
ResolveGpuUniformBuffers();
}
if(auto* gl = mImpl->GetGL())
{
auto i = 0u;
- for(auto& binding : mImpl->mCurrentUBOBindings)
+ for(const auto& binding : mImpl->mCurrentUBOBindings)
{
- gl->BindBufferRange(GL_UNIFORM_BUFFER, i++, binding.buffer->GetGLBuffer(), GLintptr(binding.offset), GLintptr(binding.dataSize));
+ if(DALI_LIKELY(binding.buffer && binding.dataSize > 0u))
+ {
+ gl->BindBufferRange(GL_UNIFORM_BUFFER, i++, binding.buffer->GetGLBuffer(), GLintptr(binding.offset), GLintptr(binding.dataSize));
+ }
}
}
}
void Context::ClearState()
{
- mImpl->mCurrentTextureBindings.clear();
- mImpl->mCurrentUBOBindings.clear();
+ mImpl->mCurrentTextureBindings.Clear();
+ mImpl->mCurrentUBOBindings.Clear();
}
void Context::ColorMask(bool enabled)
mImpl->mGlStateCache.ResetBufferCache();
mImpl->mGlStateCache.ResetTextureCache();
mImpl->mCurrentPipeline = nullptr;
- mImpl->mCurrentUBOBindings.clear();
- mImpl->mCurrentTextureBindings.clear();
+
mImpl->mCurrentVertexBufferBindings.clear();
mImpl->mCurrentRenderTarget = nullptr;
mImpl->mCurrentRenderPass = nullptr;
mImpl->mVertexBuffersChanged = true;
mImpl->mCurrentIndexBufferBinding = {};
- mImpl->mCurrentSamplerBindings = {};
mImpl->mProgramVAOCurrentState = 0;
ClearState();
static constexpr UniformBufferBindingDescriptor NULL_DESCRIPTOR{nullptr, 0, 0, 0, 0, false};
static thread_local std::vector<UniformBufferBindingDescriptor> sTempBindings(MAX_UNIFORM_BUFFER_BINDINGS, NULL_DESCRIPTOR);
- static std::vector<bool> sTempBindingsUsed(MAX_UNIFORM_BUFFER_BINDINGS, false);
+ static thread_local std::vector<bool> sTempBindingsUsed(MAX_UNIFORM_BUFFER_BINDINGS, false);
memset(&bindCmd.standaloneUniformsBufferBinding, 0, sizeof(UniformBufferBindingDescriptor));
++maxBinding;
auto destBindings = mCommandPool->Allocate<UniformBufferBindingDescriptor>(maxBinding);
+
// copy
- const auto size = sizeof(UniformBufferBindingDescriptor) * (maxBinding);
- if(!(size % sizeof(intptr_t)))
- {
- // Use iteration hardly, to avoid SIGBUS... (SIGBUS occurs when accessing unaligned memory)
- auto* srcPtr = reinterpret_cast<intptr_t*>(&sTempBindings[0]);
- auto* dstPtr = reinterpret_cast<intptr_t*>(destBindings.Ptr());
- for(auto i = 0u; i < size / sizeof(intptr_t); ++i)
- {
- *dstPtr++ = *srcPtr++;
- }
- }
- else
- {
- memcpy(destBindings.Ptr(), &sTempBindings[0], size);
- }
+ memcpy(destBindings.Ptr(), &sTempBindings[0], sizeof(UniformBufferBindingDescriptor) * (maxBinding));
bindCmd.uniformBufferBindings = destBindings;
bindCmd.uniformBufferBindingsCount = maxBinding;
}
void CommandBuffer::BindTextures(const std::vector<TextureBinding>& textureBindings)
{
- auto command = mCommandPool->AllocateCommand(CommandType::BIND_TEXTURES);
- auto& bindTexturesCmd = command->bindTextures;
- bindTexturesCmd.textureBindings = mCommandPool->Allocate<TextureBinding>(textureBindings.size());
- bindTexturesCmd.textureBindingsCount = textureBindings.size();
- memcpy(bindTexturesCmd.textureBindings.Ptr(), textureBindings.data(), sizeof(TextureBinding) * textureBindings.size());
+ auto command = mCommandPool->AllocateCommand(CommandType::BIND_TEXTURES);
+ auto& bindTexturesCmd = command->bindTextures;
+
+ if(textureBindings.empty())
+ {
+ bindTexturesCmd.textureBindings = nullptr;
+ bindTexturesCmd.textureBindingsCount = 0u;
+ }
+ else
+ {
+ const uint32_t bindingCount = static_cast<uint32_t>(textureBindings.size());
+
+ auto destBindings = mCommandPool->Allocate<TextureBinding>(bindingCount);
+
+ // copy
+ memcpy(destBindings.Ptr(), textureBindings.data(), sizeof(TextureBinding) * (bindingCount));
+
+ bindTexturesCmd.textureBindings = destBindings;
+ bindTexturesCmd.textureBindingsCount = bindingCount;
+
+ // Check binding is continuous, and throw exception for debug mode
+#if defined(DEBUG_ENABLED)
+ uint32_t lastBinding = 0u;
+ for(const auto& binding : textureBindings)
+ {
+ DALI_ASSERT_DEBUG(lastBinding == binding.binding && "Texture binding order not matched!");
+ ++lastBinding;
+ }
+#endif
+ }
}
void CommandBuffer::BindSamplers(const std::vector<SamplerBinding>& samplerBindings)
{
- auto command = mCommandPool->AllocateCommand(CommandType::BIND_SAMPLERS);
- auto& bindSamplersCmd = command->bindSamplers;
- bindSamplersCmd.samplerBindings = mCommandPool->Allocate<SamplerBinding>(samplerBindings.size());
- bindSamplersCmd.samplerBindingsCount = samplerBindings.size();
- memcpy(bindSamplersCmd.samplerBindings.Ptr(), samplerBindings.data(), sizeof(TextureBinding) * samplerBindings.size());
+ // Unused in core
}
void CommandBuffer::BindPushConstants(void* data,
#define DALI_GRAPHICS_GLES_COMMAND_BUFFER_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.
* @brief Copy constructor
* @param[in] rhs Command
*/
- Command(const Command& rhs) = default;
+ Command(const Command& rhs) = default;
Command& operator=(const Command& rhs) = default;
Command(Command&& rhs) noexcept = delete;
- Command& operator=(Command&& rhs) = delete;
+ Command& operator=(Command&& rhs) = delete;
CommandType type{CommandType::FLUSH}; ///< Type of command
{
struct
{
- IndirectPtr<Graphics::TextureBinding> textureBindings;
+ IndirectPtr<Graphics::TextureBinding> textureBindings; ///< Sorted by binding index.
uint32_t textureBindingsCount;
} bindTextures{};
// BindSampler command
struct
{
- IndirectPtr<Graphics::SamplerBinding> samplerBindings;
+ IndirectPtr<Graphics::SamplerBinding> samplerBindings; ///< Sorted by binding index.
uint32_t samplerBindingsCount;
} bindSamplers;
struct
{
- IndirectPtr<UniformBufferBindingDescriptor> uniformBufferBindings;
+ IndirectPtr<UniformBufferBindingDescriptor> uniformBufferBindings; ///< Sorted by binding index.
uint32_t uniformBufferBindingsCount;
UniformBufferBindingDescriptor standaloneUniformsBufferBinding{};
} bindUniformBuffers;