Add a ResourceMap class for faster GL resource maps.
This gives a very fast query time for handles that are within a fixed
range. For WebGL, where we don't allow create-on-bind, this will be
100% of the time, unless we create a very large number of resources.
It is implemented as a two-tier map - the first uses a flat array to
index into a handle buffer. The second tier uses a map for out-of-
range values.
BUG=angleproject:1458
Change-Id: I421bb3725cf523918cdfdbfaab035ad0dd3bf82d
Reviewed-on: https://chromium-review.googlesource.com/544684
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index 5eeaf2e..7a49181 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -28,18 +28,11 @@
template <typename ResourceType>
GLuint AllocateEmptyObject(HandleAllocator *handleAllocator, ResourceMap<ResourceType> *objectMap)
{
- GLuint handle = handleAllocator->allocate();
- (*objectMap)[handle] = nullptr;
+ GLuint handle = handleAllocator->allocate();
+ objectMap->assign(handle, nullptr);
return handle;
}
-template <typename ResourceType>
-ResourceType *GetObject(const ResourceMap<ResourceType> &objectMap, GLuint handle)
-{
- auto iter = objectMap.find(handle);
- return iter != objectMap.end() ? iter->second : nullptr;
-}
-
} // anonymous namespace
template <typename HandleAllocatorType>
@@ -72,9 +65,13 @@
template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::reset(const Context *context)
{
- while (!mObjectMap.empty())
+ this->mHandleAllocator.reset();
+ for (const auto &resource : mObjectMap)
{
- deleteObject(context, mObjectMap.begin()->first);
+ if (resource.second)
+ {
+ ImplT::DeleteObject(context, resource.second);
+ }
}
mObjectMap.clear();
}
@@ -84,77 +81,29 @@
const Context *context,
GLuint handle)
{
- auto objectIter = mObjectMap.find(handle);
- if (objectIter == mObjectMap.end())
+ ResourceType *resource = nullptr;
+ if (!mObjectMap.erase(handle, &resource))
{
return;
}
- if (objectIter->second != nullptr)
- {
- ImplT::DeleteObject(context, objectIter->second);
- }
-
// Requires an explicit this-> because of C++ template rules.
- this->mHandleAllocator.release(objectIter->first);
- mObjectMap.erase(objectIter);
-}
+ this->mHandleAllocator.release(handle);
-template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
-template <typename... ArgTypes>
-ResourceType *TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::allocateObject(
- typename ResourceMap<ResourceType>::iterator &objectMapIter,
- rx::GLImplFactory *factory,
- GLuint handle,
- ArgTypes... args)
-{
- ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...);
-
- if (objectMapIter != mObjectMap.end())
+ if (resource)
{
- objectMapIter->second = object;
+ ImplT::DeleteObject(context, resource);
}
- else
- {
- this->mHandleAllocator.reserve(handle);
- mObjectMap[handle] = object;
- }
-
- return object;
}
template class ResourceManagerBase<HandleAllocator>;
template class ResourceManagerBase<HandleRangeAllocator>;
template class TypedResourceManager<Buffer, HandleAllocator, BufferManager>;
-template Buffer *TypedResourceManager<Buffer, HandleAllocator, BufferManager>::allocateObject(
- ResourceMap<Buffer>::iterator &,
- rx::GLImplFactory *,
- GLuint);
template class TypedResourceManager<Texture, HandleAllocator, TextureManager>;
-template Texture *TypedResourceManager<Texture, HandleAllocator, TextureManager>::allocateObject(
- ResourceMap<Texture>::iterator &,
- rx::GLImplFactory *,
- GLuint,
- GLenum);
template class TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>;
-template Renderbuffer *
-TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>::allocateObject(
- ResourceMap<Renderbuffer>::iterator &,
- rx::GLImplFactory *,
- GLuint);
template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager>;
-template Sampler *TypedResourceManager<Sampler, HandleAllocator, SamplerManager>::allocateObject(
- ResourceMap<Sampler>::iterator &,
- rx::GLImplFactory *,
- GLuint);
template class TypedResourceManager<FenceSync, HandleAllocator, FenceSyncManager>;
template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>;
-template Framebuffer *
-TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>::allocateObject(
- ResourceMap<Framebuffer>::iterator &,
- rx::GLImplFactory *,
- GLuint,
- const Caps &);
// BufferManager Implementation.
@@ -179,7 +128,7 @@
Buffer *BufferManager::getBuffer(GLuint handle) const
{
- return GetObject(mObjectMap, handle);
+ return mObjectMap.query(handle);
}
// ShaderProgramManager Implementation.
@@ -210,7 +159,7 @@
{
ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER);
GLuint handle = mHandleAllocator.allocate();
- mShaders[handle] = new Shader(this, factory, rendererLimitations, type, handle);
+ mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
return handle;
}
@@ -221,13 +170,13 @@
Shader *ShaderProgramManager::getShader(GLuint handle) const
{
- return GetObject(mShaders, handle);
+ return mShaders.query(handle);
}
GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
{
- GLuint handle = mHandleAllocator.allocate();
- mPrograms[handle] = new Program(factory, this, handle);
+ GLuint handle = mHandleAllocator.allocate();
+ mPrograms.assign(handle, new Program(factory, this, handle));
return handle;
}
@@ -238,7 +187,7 @@
Program *ShaderProgramManager::getProgram(GLuint handle) const
{
- return GetObject(mPrograms, handle);
+ return mPrograms.query(handle);
}
template <typename ObjectType>
@@ -246,18 +195,17 @@
ResourceMap<ObjectType> *objectMap,
GLuint id)
{
- auto iter = objectMap->find(id);
- if (iter == objectMap->end())
+ ObjectType *object = objectMap->query(id);
+ if (!object)
{
return;
}
- auto object = iter->second;
if (object->getRefCount() == 0)
{
mHandleAllocator.release(id);
object->onDestroy(context);
- objectMap->erase(iter);
+ objectMap->erase(id, &object);
}
else
{
@@ -288,13 +236,13 @@
Texture *TextureManager::getTexture(GLuint handle) const
{
- ASSERT(GetObject(mObjectMap, 0) == nullptr);
- return GetObject(mObjectMap, handle);
+ ASSERT(mObjectMap.query(0) == nullptr);
+ return mObjectMap.query(handle);
}
-void TextureManager::invalidateTextureComplenessCache()
+void TextureManager::invalidateTextureComplenessCache() const
{
- for (auto &texture : mObjectMap)
+ for (const auto &texture : mObjectMap)
{
if (texture.second)
{
@@ -326,7 +274,7 @@
Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle)
{
- return GetObject(mObjectMap, handle);
+ return mObjectMap.query(handle);
}
// SamplerManager Implementation.
@@ -352,12 +300,12 @@
Sampler *SamplerManager::getSampler(GLuint handle)
{
- return GetObject(mObjectMap, handle);
+ return mObjectMap.query(handle);
}
bool SamplerManager::isSampler(GLuint sampler)
{
- return mObjectMap.find(sampler) != mObjectMap.end();
+ return mObjectMap.contains(sampler);
}
// FenceSyncManager Implementation.
@@ -373,13 +321,13 @@
GLuint handle = mHandleAllocator.allocate();
FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
fenceSync->addRef();
- mObjectMap[handle] = fenceSync;
+ mObjectMap.assign(handle, fenceSync);
return handle;
}
FenceSync *FenceSyncManager::getFenceSync(GLuint handle)
{
- return GetObject(mObjectMap, handle);
+ return mObjectMap.query(handle);
}
// PathManager Implementation.
@@ -398,13 +346,11 @@
return OutOfMemory() << "Failed to allocate path objects.";
}
- auto hint = mPaths.begin();
-
for (GLsizei i = 0; i < range; ++i)
{
const auto impl = paths[static_cast<unsigned>(i)];
const auto id = client + i;
- hint = mPaths.insert(hint, std::make_pair(id, new Path(impl)));
+ mPaths.assign(id, new Path(impl));
}
return client;
}
@@ -414,20 +360,17 @@
for (GLsizei i = 0; i < range; ++i)
{
const auto id = first + i;
- const auto it = mPaths.find(id);
- if (it == mPaths.end())
+ Path *p = nullptr;
+ if (!mPaths.erase(id, &p))
continue;
- Path *p = it->second;
delete p;
- mPaths.erase(it);
}
mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
}
Path *PathManager::getPath(GLuint handle) const
{
- auto iter = mPaths.find(handle);
- return iter != mPaths.end() ? iter->second : nullptr;
+ return mPaths.query(handle);
}
bool PathManager::hasPath(GLuint handle) const
@@ -477,18 +420,18 @@
Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
{
- return GetObject(mObjectMap, handle);
+ return mObjectMap.query(handle);
}
void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
{
ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
- mObjectMap[0] = framebuffer;
+ mObjectMap.assign(0, framebuffer);
}
-void FramebufferManager::invalidateFramebufferComplenessCache()
+void FramebufferManager::invalidateFramebufferComplenessCache() const
{
- for (auto &framebuffer : mObjectMap)
+ for (const auto &framebuffer : mObjectMap)
{
if (framebuffer.second)
{