std::size_t hash = 0;
for(const auto& attr : vertexInputState.attributes)
{
- hash ^= std::hash<uint32_t>{}(attr.location);
+ // Make unordered hash value by location.
+ // Note : This hash function varified for locations only under < 20.
+ std::size_t salt = attr.location + 1;
+ hash += salt << (sizeof(std::size_t) * 6);
+ salt *= salt;
+ salt ^= attr.location;
+ hash += salt << (sizeof(std::size_t) * 4);
+ salt *= salt;
+ hash += salt;
}
- auto& gl = *mController.GetGL();
- auto iter = mProgramVAOMap.find(program);
+ auto& gl = *mController.GetGL();
+
+ if(DALI_UNLIKELY(!mDiscardedVAOList.empty()))
+ {
+ gl.DeleteVertexArrays(static_cast<Dali::GLsizei>(mDiscardedVAOList.size()), mDiscardedVAOList.data());
+ mDiscardedVAOList.clear();
+ }
+
+ auto iter = mProgramVAOMap.find(program);
if(iter != mProgramVAOMap.end())
{
auto attributeIter = iter->second.find(hash);
std::unordered_map<const GLES::ProgramImpl*, std::map<std::size_t, uint32_t>> mProgramVAOMap; ///< GL program-VAO map
uint32_t mProgramVAOCurrentState{0u}; ///< Currently bound VAO
GLStateCache mGlStateCache{}; ///< GL status cache
+ std::vector<Dali::GLuint> mDiscardedVAOList{};
bool mGlContextCreated{false}; ///< True if the OpenGL context has been created
// Map binding# to sampler location
const auto& reflection = !newProgram ? currentProgram->GetReflection() : newProgram->GetReflection();
const auto& samplers = reflection.GetSamplers();
+
+ uint32_t currentSampler = 0;
+ uint32_t currentElement = 0;
+
+ // @warning Assume that binding.binding is strictly linear in the same order as mCurrentTextureBindings
+ // elements. This avoids having to sort the bindings.
for(const auto& binding : mImpl->mCurrentTextureBindings)
{
+ if(currentSampler >= samplers.size())
+ {
+ // Don't bind more textures than there are active samplers.
+ break;
+ }
+
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(!texture->GetGLTexture())
{
- // Attempt to reinitialize
- // @todo need to put this somewhere else where it isn't const.
- // Maybe post it back on end of initialize queue if initialization fails?
texture->InitializeResource();
}
// Warning, this may cause glWaitSync to occur on the GPU.
dependencyChecker.CheckNeedsSync(this, texture);
-
texture->Bind(binding);
-
- texture->Prepare(); // @todo also non-const.
-
- if(binding.binding < samplers.size()) // binding maps to texture unit. (texture bindings should also be in binding order)
+ texture->Prepare();
+
+ // @warning Assume that location of array elements is sequential.
+ // @warning GL does not guarantee this, but in practice, it is.
+ gl.Uniform1i(samplers[currentSampler].location + currentElement,
+ samplers[currentSampler].offset + currentElement);
+ ++currentElement;
+ if(currentElement >= samplers[currentSampler].elementCount)
{
- // Offset is set to the lexical offset within the frag shader, map it to the texture unit
- // @todo Explicitly set the texture unit through the graphics interface
- gl.Uniform1i(samplers[binding.binding].location, samplers[binding.binding].offset);
+ ++currentSampler;
+ currentElement = 0;
}
}
auto& gl = *mImpl->mController.GetGL();
gl.Flush();
+ if(framebuffer->CaptureRequested())
+ {
+ framebuffer->DrawRenderedBuffer();
+ }
+
/* @todo Full dependency checking would need to store textures in Begin, and create
* fence objects here; but we're going to draw all fbos on shared context in serial,
* so no real need (yet). Might want to consider ensuring order of render passes,
for(auto& attributeHashPair : iter->second)
{
auto vao = attributeHashPair.second;
- gl->DeleteVertexArrays(1, &vao);
+
+ // Do not delete vao now. (Since Context might not be current.)
+ mImpl->mDiscardedVAOList.emplace_back(vao);
if(mImpl->mProgramVAOCurrentState == vao)
{
mImpl->mProgramVAOCurrentState = 0u;
}
}
+
+ // Clear cached Vertex buffer.
+ mImpl->mCurrentVertexBufferBindings.clear();
+
mImpl->mProgramVAOMap.erase(iter);
}
}