Commit 96a483bc by Jamie Madill Committed by Commit Bot

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: 's avatarCorentin Wallez <cwallez@chromium.org>
parent c8a8b843
...@@ -409,6 +409,7 @@ egl::Error Context::onDestroy(const egl::Display *display) ...@@ -409,6 +409,7 @@ egl::Error Context::onDestroy(const egl::Display *display)
{ {
SafeDelete(fence.second); SafeDelete(fence.second);
} }
mFenceNVMap.clear();
for (auto query : mQueryMap) for (auto query : mQueryMap)
{ {
...@@ -417,6 +418,7 @@ egl::Error Context::onDestroy(const egl::Display *display) ...@@ -417,6 +418,7 @@ egl::Error Context::onDestroy(const egl::Display *display)
query.second->release(this); query.second->release(this);
} }
} }
mQueryMap.clear();
for (auto vertexArray : mVertexArrayMap) for (auto vertexArray : mVertexArrayMap)
{ {
...@@ -425,6 +427,7 @@ egl::Error Context::onDestroy(const egl::Display *display) ...@@ -425,6 +427,7 @@ egl::Error Context::onDestroy(const egl::Display *display)
vertexArray.second->onDestroy(this); vertexArray.second->onDestroy(this);
} }
} }
mVertexArrayMap.clear();
for (auto transformFeedback : mTransformFeedbackMap) for (auto transformFeedback : mTransformFeedbackMap)
{ {
...@@ -433,6 +436,7 @@ egl::Error Context::onDestroy(const egl::Display *display) ...@@ -433,6 +436,7 @@ egl::Error Context::onDestroy(const egl::Display *display)
transformFeedback.second->release(this); transformFeedback.second->release(this);
} }
} }
mTransformFeedbackMap.clear();
for (auto &zeroTexture : mZeroTextures) for (auto &zeroTexture : mZeroTextures)
{ {
...@@ -606,8 +610,8 @@ GLuint Context::createPaths(GLsizei range) ...@@ -606,8 +610,8 @@ GLuint Context::createPaths(GLsizei range)
GLuint Context::createVertexArray() GLuint Context::createVertexArray()
{ {
GLuint vertexArray = mVertexArrayHandleAllocator.allocate(); GLuint vertexArray = mVertexArrayHandleAllocator.allocate();
mVertexArrayMap[vertexArray] = nullptr; mVertexArrayMap.assign(vertexArray, nullptr);
return vertexArray; return vertexArray;
} }
...@@ -618,8 +622,8 @@ GLuint Context::createSampler() ...@@ -618,8 +622,8 @@ GLuint Context::createSampler()
GLuint Context::createTransformFeedback() GLuint Context::createTransformFeedback()
{ {
GLuint transformFeedback = mTransformFeedbackAllocator.allocate(); GLuint transformFeedback = mTransformFeedbackAllocator.allocate();
mTransformFeedbackMap[transformFeedback] = nullptr; mTransformFeedbackMap.assign(transformFeedback, nullptr);
return transformFeedback; return transformFeedback;
} }
...@@ -632,9 +636,7 @@ GLuint Context::createFramebuffer() ...@@ -632,9 +636,7 @@ GLuint Context::createFramebuffer()
GLuint Context::createFenceNV() GLuint Context::createFenceNV()
{ {
GLuint handle = mFenceNVHandleAllocator.allocate(); GLuint handle = mFenceNVHandleAllocator.allocate();
mFenceNVMap.assign(handle, new FenceNV(mImplementation->createFenceNV()));
mFenceNVMap[handle] = new FenceNV(mImplementation->createFenceNV());
return handle; return handle;
} }
...@@ -642,9 +644,7 @@ GLuint Context::createFenceNV() ...@@ -642,9 +644,7 @@ GLuint Context::createFenceNV()
GLuint Context::createQuery() GLuint Context::createQuery()
{ {
GLuint handle = mQueryHandleAllocator.allocate(); GLuint handle = mQueryHandleAllocator.allocate();
mQueryMap.assign(handle, nullptr);
mQueryMap[handle] = nullptr;
return handle; return handle;
} }
...@@ -790,17 +790,15 @@ void Context::setPathStencilFunc(GLenum func, GLint ref, GLuint mask) ...@@ -790,17 +790,15 @@ void Context::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
void Context::deleteVertexArray(GLuint vertexArray) void Context::deleteVertexArray(GLuint vertexArray)
{ {
auto iter = mVertexArrayMap.find(vertexArray); VertexArray *vertexArrayObject = nullptr;
if (iter != mVertexArrayMap.end()) if (mVertexArrayMap.erase(vertexArray, &vertexArrayObject))
{ {
VertexArray *vertexArrayObject = iter->second;
if (vertexArrayObject != nullptr) if (vertexArrayObject != nullptr)
{ {
detachVertexArray(vertexArray); detachVertexArray(vertexArray);
vertexArrayObject->onDestroy(this); vertexArrayObject->onDestroy(this);
} }
mVertexArrayMap.erase(iter);
mVertexArrayHandleAllocator.release(vertexArray); mVertexArrayHandleAllocator.release(vertexArray);
} }
} }
...@@ -822,17 +820,15 @@ void Context::deleteTransformFeedback(GLuint transformFeedback) ...@@ -822,17 +820,15 @@ void Context::deleteTransformFeedback(GLuint transformFeedback)
return; return;
} }
auto iter = mTransformFeedbackMap.find(transformFeedback); TransformFeedback *transformFeedbackObject = nullptr;
if (iter != mTransformFeedbackMap.end()) if (mTransformFeedbackMap.erase(transformFeedback, &transformFeedbackObject))
{ {
TransformFeedback *transformFeedbackObject = iter->second;
if (transformFeedbackObject != nullptr) if (transformFeedbackObject != nullptr)
{ {
detachTransformFeedback(transformFeedback); detachTransformFeedback(transformFeedback);
transformFeedbackObject->release(this); transformFeedbackObject->release(this);
} }
mTransformFeedbackMap.erase(iter);
mTransformFeedbackAllocator.release(transformFeedback); mTransformFeedbackAllocator.release(transformFeedback);
} }
} }
...@@ -849,27 +845,24 @@ void Context::deleteFramebuffer(GLuint framebuffer) ...@@ -849,27 +845,24 @@ void Context::deleteFramebuffer(GLuint framebuffer)
void Context::deleteFenceNV(GLuint fence) void Context::deleteFenceNV(GLuint fence)
{ {
auto fenceObject = mFenceNVMap.find(fence); FenceNV *fenceObject = nullptr;
if (mFenceNVMap.erase(fence, &fenceObject))
if (fenceObject != mFenceNVMap.end())
{ {
mFenceNVHandleAllocator.release(fenceObject->first); mFenceNVHandleAllocator.release(fence);
delete fenceObject->second; delete fenceObject;
mFenceNVMap.erase(fenceObject);
} }
} }
void Context::deleteQuery(GLuint query) void Context::deleteQuery(GLuint query)
{ {
auto queryObject = mQueryMap.find(query); Query *queryObject = nullptr;
if (queryObject != mQueryMap.end()) if (mQueryMap.erase(query, &queryObject))
{ {
mQueryHandleAllocator.release(queryObject->first); mQueryHandleAllocator.release(query);
if (queryObject->second) if (queryObject)
{ {
queryObject->second->release(this); queryObject->release(this);
} }
mQueryMap.erase(queryObject);
} }
} }
...@@ -896,8 +889,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const ...@@ -896,8 +889,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const
VertexArray *Context::getVertexArray(GLuint handle) const VertexArray *Context::getVertexArray(GLuint handle) const
{ {
auto vertexArray = mVertexArrayMap.find(handle); return mVertexArrayMap.query(handle);
return (vertexArray != mVertexArrayMap.end()) ? vertexArray->second : nullptr;
} }
Sampler *Context::getSampler(GLuint handle) const Sampler *Context::getSampler(GLuint handle) const
...@@ -907,8 +899,7 @@ Sampler *Context::getSampler(GLuint handle) const ...@@ -907,8 +899,7 @@ Sampler *Context::getSampler(GLuint handle) const
TransformFeedback *Context::getTransformFeedback(GLuint handle) const TransformFeedback *Context::getTransformFeedback(GLuint handle) const
{ {
auto iter = mTransformFeedbackMap.find(handle); return mTransformFeedbackMap.query(handle);
return (iter != mTransformFeedbackMap.end()) ? iter->second : nullptr;
} }
LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
...@@ -1270,41 +1261,29 @@ Framebuffer *Context::getFramebuffer(GLuint handle) const ...@@ -1270,41 +1261,29 @@ Framebuffer *Context::getFramebuffer(GLuint handle) const
FenceNV *Context::getFenceNV(GLuint handle) FenceNV *Context::getFenceNV(GLuint handle)
{ {
auto fence = mFenceNVMap.find(handle); return mFenceNVMap.query(handle);
if (fence == mFenceNVMap.end())
{
return nullptr;
}
else
{
return fence->second;
}
} }
Query *Context::getQuery(GLuint handle, bool create, GLenum type) Query *Context::getQuery(GLuint handle, bool create, GLenum type)
{ {
auto query = mQueryMap.find(handle); if (!mQueryMap.contains(handle))
if (query == mQueryMap.end())
{ {
return nullptr; return nullptr;
} }
else
Query *query = mQueryMap.query(handle);
if (!query && create)
{ {
if (!query->second && create) query = new Query(mImplementation->createQuery(type), handle);
{ query->addRef();
query->second = new Query(mImplementation->createQuery(type), handle); mQueryMap.assign(handle, query);
query->second->addRef();
}
return query->second;
} }
return query;
} }
Query *Context::getQuery(GLuint handle) const Query *Context::getQuery(GLuint handle) const
{ {
auto iter = mQueryMap.find(handle); return mQueryMap.query(handle);
return (iter != mQueryMap.end()) ? iter->second : nullptr;
} }
Texture *Context::getTargetTexture(GLenum target) const Texture *Context::getTargetTexture(GLenum target) const
...@@ -2309,7 +2288,7 @@ VertexArray *Context::checkVertexArrayAllocation(GLuint vertexArrayHandle) ...@@ -2309,7 +2288,7 @@ VertexArray *Context::checkVertexArrayAllocation(GLuint vertexArrayHandle)
vertexArray = new VertexArray(mImplementation.get(), vertexArrayHandle, vertexArray = new VertexArray(mImplementation.get(), vertexArrayHandle,
mCaps.maxVertexAttributes, mCaps.maxVertexAttribBindings); mCaps.maxVertexAttributes, mCaps.maxVertexAttribBindings);
mVertexArrayMap[vertexArrayHandle] = vertexArray; mVertexArrayMap.assign(vertexArrayHandle, vertexArray);
} }
return vertexArray; return vertexArray;
...@@ -2324,7 +2303,7 @@ TransformFeedback *Context::checkTransformFeedbackAllocation(GLuint transformFee ...@@ -2324,7 +2303,7 @@ TransformFeedback *Context::checkTransformFeedbackAllocation(GLuint transformFee
transformFeedback = transformFeedback =
new TransformFeedback(mImplementation.get(), transformFeedbackHandle, mCaps); new TransformFeedback(mImplementation.get(), transformFeedbackHandle, mCaps);
transformFeedback->addRef(); transformFeedback->addRef();
mTransformFeedbackMap[transformFeedbackHandle] = transformFeedback; mTransformFeedbackMap.assign(transformFeedbackHandle, transformFeedback);
} }
return transformFeedback; return transformFeedback;
...@@ -2332,14 +2311,14 @@ TransformFeedback *Context::checkTransformFeedbackAllocation(GLuint transformFee ...@@ -2332,14 +2311,14 @@ TransformFeedback *Context::checkTransformFeedbackAllocation(GLuint transformFee
bool Context::isVertexArrayGenerated(GLuint vertexArray) bool Context::isVertexArrayGenerated(GLuint vertexArray)
{ {
ASSERT(mVertexArrayMap.find(0) != mVertexArrayMap.end()); ASSERT(mVertexArrayMap.contains(0));
return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end(); return mVertexArrayMap.contains(vertexArray);
} }
bool Context::isTransformFeedbackGenerated(GLuint transformFeedback) bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
{ {
ASSERT(mTransformFeedbackMap.find(0) != mTransformFeedbackMap.end()); ASSERT(mTransformFeedbackMap.contains(0));
return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end(); return mTransformFeedbackMap.contains(transformFeedback);
} }
void Context::detachTexture(GLuint texture) void Context::detachTexture(GLuint texture)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/HandleAllocator.h" #include "libANGLE/HandleAllocator.h"
#include "libANGLE/RefCountObject.h" #include "libANGLE/RefCountObject.h"
#include "libANGLE/ResourceMap.h"
#include "libANGLE/VertexAttribute.h" #include "libANGLE/VertexAttribute.h"
#include "libANGLE/Workarounds.h" #include "libANGLE/Workarounds.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
......
...@@ -128,4 +128,13 @@ void HandleAllocator::reserve(GLuint handle) ...@@ -128,4 +128,13 @@ void HandleAllocator::reserve(GLuint handle)
mUnallocatedList.insert(placementIt, HandleRange(begin, handle - 1)); mUnallocatedList.insert(placementIt, HandleRange(begin, handle - 1));
} }
void HandleAllocator::reset()
{
mUnallocatedList.clear();
mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max()));
mReleasedList.clear();
mBaseValue = 1;
mNextValue = 1;
}
} // namespace gl } // namespace gl
...@@ -24,7 +24,7 @@ class HandleAllocator final : angle::NonCopyable ...@@ -24,7 +24,7 @@ class HandleAllocator final : angle::NonCopyable
public: public:
// Maximum handle = MAX_UINT-1 // Maximum handle = MAX_UINT-1
HandleAllocator(); HandleAllocator();
// Specify maximum handle value // Specify maximum handle value. Used for testing.
HandleAllocator(GLuint maximumHandleValue); HandleAllocator(GLuint maximumHandleValue);
~HandleAllocator(); ~HandleAllocator();
...@@ -34,6 +34,7 @@ class HandleAllocator final : angle::NonCopyable ...@@ -34,6 +34,7 @@ class HandleAllocator final : angle::NonCopyable
GLuint allocate(); GLuint allocate();
void release(GLuint handle); void release(GLuint handle);
void reserve(GLuint handle); void reserve(GLuint handle);
void reset();
private: private:
GLuint mBaseValue; GLuint mBaseValue;
......
...@@ -135,4 +135,19 @@ TEST(HandleAllocatorTest, SortedOrderHandle) ...@@ -135,4 +135,19 @@ TEST(HandleAllocatorTest, SortedOrderHandle)
EXPECT_EQ(6u, allocatedList[4]); EXPECT_EQ(6u, allocatedList[4]);
} }
// Tests the reset method.
TEST(HandleAllocatorTest, Reset)
{
gl::HandleAllocator allocator;
for (int iteration = 0; iteration < 1; ++iteration)
{
allocator.reserve(3);
EXPECT_EQ(1u, allocator.allocate());
EXPECT_EQ(2u, allocator.allocate());
EXPECT_EQ(4u, allocator.allocate());
allocator.reset();
}
} }
} // anonymous namespace
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/HandleAllocator.h" #include "libANGLE/HandleAllocator.h"
#include "libANGLE/HandleRangeAllocator.h" #include "libANGLE/HandleRangeAllocator.h"
#include "libANGLE/ResourceMap.h"
namespace rx namespace rx
{ {
...@@ -66,7 +66,7 @@ class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType> ...@@ -66,7 +66,7 @@ class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType>
bool isHandleGenerated(GLuint handle) const bool isHandleGenerated(GLuint handle) const
{ {
// Zero is always assumed to have been generated implicitly. // Zero is always assumed to have been generated implicitly.
return handle == 0 || mObjectMap.find(handle) != mObjectMap.end(); return handle == 0 || mObjectMap.contains(handle);
} }
protected: protected:
...@@ -76,11 +76,10 @@ class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType> ...@@ -76,11 +76,10 @@ class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType>
template <typename... ArgTypes> template <typename... ArgTypes>
ResourceType *checkObjectAllocation(rx::GLImplFactory *factory, GLuint handle, ArgTypes... args) ResourceType *checkObjectAllocation(rx::GLImplFactory *factory, GLuint handle, ArgTypes... args)
{ {
auto objectMapIter = mObjectMap.find(handle); ResourceType *value = mObjectMap.query(handle);
if (value)
if (objectMapIter != mObjectMap.end() && objectMapIter->second != nullptr)
{ {
return objectMapIter->second; return value;
} }
if (handle == 0) if (handle == 0)
...@@ -88,14 +87,16 @@ class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType> ...@@ -88,14 +87,16 @@ class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType>
return nullptr; return nullptr;
} }
return allocateObject<ArgTypes...>(objectMapIter, factory, handle, args...); ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...);
}
template <typename... ArgTypes> if (!mObjectMap.contains(handle))
ResourceType *allocateObject(typename ResourceMap<ResourceType>::iterator &objectMapIter, {
rx::GLImplFactory *factory, this->mHandleAllocator.reserve(handle);
GLuint handle, }
ArgTypes... args); mObjectMap.assign(handle, object);
return object;
}
void reset(const Context *context) override; void reset(const Context *context) override;
...@@ -153,7 +154,7 @@ class TextureManager : public TypedResourceManager<Texture, HandleAllocator, Tex ...@@ -153,7 +154,7 @@ class TextureManager : public TypedResourceManager<Texture, HandleAllocator, Tex
GLuint createTexture(); GLuint createTexture();
Texture *getTexture(GLuint handle) const; Texture *getTexture(GLuint handle) const;
void invalidateTextureComplenessCache(); void invalidateTextureComplenessCache() const;
Texture *checkTextureAllocation(rx::GLImplFactory *factory, GLuint handle, GLenum target) Texture *checkTextureAllocation(rx::GLImplFactory *factory, GLuint handle, GLenum target)
{ {
...@@ -241,7 +242,7 @@ class FramebufferManager ...@@ -241,7 +242,7 @@ class FramebufferManager
Framebuffer *getFramebuffer(GLuint handle) const; Framebuffer *getFramebuffer(GLuint handle) const;
void setDefaultFramebuffer(Framebuffer *framebuffer); void setDefaultFramebuffer(Framebuffer *framebuffer);
void invalidateFramebufferComplenessCache(); void invalidateFramebufferComplenessCache() const;
Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory, Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory,
const Caps &caps, const Caps &caps,
......
//
// Copyright 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ResourceMap:
// An optimized resource map which packs the first set of allocated objects into a
// flat array, and then falls back to an unordered map for the higher handle values.
//
#ifndef LIBANGLE_RESOURCE_MAP_H_
#define LIBANGLE_RESOURCE_MAP_H_
#include "libANGLE/angletypes.h"
namespace gl
{
template <typename ResourceType>
class ResourceMap final : angle::NonCopyable
{
public:
ResourceMap();
~ResourceMap();
ResourceType *query(GLuint handle) const;
// Returns true if the handle was reserved. Not necessarily if the resource is created.
bool contains(GLuint handle) const;
// Returns the element that was at this location.
bool erase(GLuint handle, ResourceType **resourceOut);
void assign(GLuint handle, ResourceType *resource);
// Clears the map.
void clear();
using IndexAndResource = std::pair<GLuint, ResourceType *>;
using HashMap = std::unordered_map<GLuint, ResourceType *>;
class Iterator final
{
public:
bool operator==(const Iterator &other) const;
bool operator!=(const Iterator &other) const;
Iterator &operator++();
const IndexAndResource *operator->() const;
const IndexAndResource &operator*() const;
private:
friend class ResourceMap;
Iterator(const ResourceMap &origin,
GLuint flatIndex,
typename HashMap::const_iterator hashIndex);
void updateValue();
const ResourceMap &mOrigin;
GLuint mFlatIndex;
typename HashMap::const_iterator mHashIndex;
IndexAndResource mValue;
};
// null values represent reserved handles.
Iterator begin() const;
Iterator end() const;
Iterator find(GLuint handle) const;
// Not a constant-time operation, should only be used for verification.
bool empty() const;
private:
friend class Iterator;
GLuint nextNonNullResource(size_t flatIndex) const;
// constexpr methods cannot contain reinterpret_cast, so we need a static method.
static ResourceType *InvalidPointer();
static constexpr intptr_t kInvalidPointer = static_cast<intptr_t>(-1);
// Start with 32 maximum elements in the map, which can grow.
static constexpr size_t kInitialFlatResourcesSize = 0x20;
// Experimental testing suggests that 16k is a reasonable upper limit.
static constexpr size_t kFlatResourcesLimit = 0x4000;
std::vector<ResourceType *> mFlatResources;
// A map of GL objects indexed by object ID.
HashMap mHashedResources;
};
template <typename ResourceType>
ResourceMap<ResourceType>::ResourceMap()
: mFlatResources(kInitialFlatResourcesSize, InvalidPointer()), mHashedResources()
{
}
template <typename ResourceType>
ResourceMap<ResourceType>::~ResourceMap()
{
ASSERT(empty());
}
template <typename ResourceType>
ResourceType *ResourceMap<ResourceType>::query(GLuint handle) const
{
if (handle < mFlatResources.size())
{
auto value = mFlatResources[handle];
return (value == InvalidPointer() ? nullptr : value);
}
auto it = mHashedResources.find(handle);
return (it == mHashedResources.end() ? nullptr : it->second);
}
template <typename ResourceType>
bool ResourceMap<ResourceType>::contains(GLuint handle) const
{
if (handle < mFlatResources.size())
{
return (mFlatResources[handle] != InvalidPointer());
}
return (mHashedResources.find(handle) != mHashedResources.end());
}
template <typename ResourceType>
bool ResourceMap<ResourceType>::erase(GLuint handle, ResourceType **resourceOut)
{
if (handle < mFlatResources.size())
{
auto &value = mFlatResources[handle];
if (value == InvalidPointer())
{
return false;
}
*resourceOut = value;
value = InvalidPointer();
}
else
{
auto it = mHashedResources.find(handle);
if (it == mHashedResources.end())
{
return false;
}
*resourceOut = it->second;
mHashedResources.erase(it);
}
return true;
}
template <typename ResourceType>
void ResourceMap<ResourceType>::assign(GLuint handle, ResourceType *resource)
{
if (handle < kFlatResourcesLimit)
{
if (handle >= mFlatResources.size())
{
// Use power-of-two.
size_t newSize = mFlatResources.size();
while (newSize <= handle)
{
newSize *= 2;
}
mFlatResources.resize(newSize, nullptr);
}
ASSERT(mFlatResources.size() > handle);
mFlatResources[handle] = resource;
}
else
{
mHashedResources[handle] = resource;
}
}
template <typename ResourceType>
typename ResourceMap<ResourceType>::Iterator ResourceMap<ResourceType>::begin() const
{
return Iterator(*this, nextNonNullResource(0), mHashedResources.begin());
}
template <typename ResourceType>
typename ResourceMap<ResourceType>::Iterator ResourceMap<ResourceType>::end() const
{
return Iterator(*this, static_cast<GLuint>(mFlatResources.size()), mHashedResources.end());
}
template <typename ResourceType>
typename ResourceMap<ResourceType>::Iterator ResourceMap<ResourceType>::find(GLuint handle) const
{
if (handle < mFlatResources.size())
{
return (mFlatResources[handle] != InvalidPointer()
? Iterator(handle, mHashedResources.begin())
: end());
}
else
{
return mHashedResources.find(handle);
}
}
template <typename ResourceType>
bool ResourceMap<ResourceType>::empty() const
{
return (begin() == end());
}
template <typename ResourceType>
void ResourceMap<ResourceType>::clear()
{
mFlatResources.assign(kInitialFlatResourcesSize, InvalidPointer());
mHashedResources.clear();
}
template <typename ResourceType>
GLuint ResourceMap<ResourceType>::nextNonNullResource(size_t flatIndex) const
{
for (size_t index = flatIndex; index < mFlatResources.size(); index++)
{
if (mFlatResources[index] != nullptr && mFlatResources[index] != InvalidPointer())
{
return static_cast<GLuint>(index);
}
}
return static_cast<GLuint>(mFlatResources.size());
}
template <typename ResourceType>
// static
ResourceType *ResourceMap<ResourceType>::InvalidPointer()
{
return reinterpret_cast<ResourceType *>(kInvalidPointer);
}
template <typename ResourceType>
ResourceMap<ResourceType>::Iterator::Iterator(
const ResourceMap &origin,
GLuint flatIndex,
typename ResourceMap<ResourceType>::HashMap::const_iterator hashIndex)
: mOrigin(origin), mFlatIndex(flatIndex), mHashIndex(hashIndex), mValue()
{
updateValue();
}
template <typename ResourceType>
bool ResourceMap<ResourceType>::Iterator::operator==(const Iterator &other) const
{
return (mFlatIndex == other.mFlatIndex && mHashIndex == other.mHashIndex);
}
template <typename ResourceType>
bool ResourceMap<ResourceType>::Iterator::operator!=(const Iterator &other) const
{
return !(*this == other);
}
template <typename ResourceType>
typename ResourceMap<ResourceType>::Iterator &ResourceMap<ResourceType>::Iterator::operator++()
{
if (mFlatIndex < static_cast<GLuint>(mOrigin.mFlatResources.size()))
{
mFlatIndex = mOrigin.nextNonNullResource(mFlatIndex + 1);
}
else
{
mHashIndex++;
}
updateValue();
return *this;
}
template <typename ResourceType>
const typename ResourceMap<ResourceType>::IndexAndResource
*ResourceMap<ResourceType>::Iterator::operator->() const
{
return &mValue;
}
template <typename ResourceType>
const typename ResourceMap<ResourceType>::IndexAndResource
&ResourceMap<ResourceType>::Iterator::operator*() const
{
return mValue;
}
template <typename ResourceType>
void ResourceMap<ResourceType>::Iterator::updateValue()
{
if (mFlatIndex < static_cast<GLuint>(mOrigin.mFlatResources.size()))
{
mValue.first = mFlatIndex;
mValue.second = mOrigin.mFlatResources[mFlatIndex];
}
else if (mHashIndex != mOrigin.mHashedResources.end())
{
mValue.first = mHashIndex->first;
mValue.second = mHashIndex->second;
}
}
} // namespace gl
#endif // LIBANGLE_RESOURCE_MAP_H_
...@@ -211,7 +211,7 @@ bool TextureState::isSamplerComplete(const SamplerState &samplerState, ...@@ -211,7 +211,7 @@ bool TextureState::isSamplerComplete(const SamplerState &samplerState,
return mCompletenessCache.samplerComplete; return mCompletenessCache.samplerComplete;
} }
void TextureState::invalidateCompletenessCache() void TextureState::invalidateCompletenessCache() const
{ {
mCompletenessCache.context = 0; mCompletenessCache.context = 0;
} }
...@@ -868,7 +868,7 @@ egl::Stream *Texture::getBoundStream() const ...@@ -868,7 +868,7 @@ egl::Stream *Texture::getBoundStream() const
return mBoundStream; return mBoundStream;
} }
void Texture::invalidateCompletenessCache() void Texture::invalidateCompletenessCache() const
{ {
mState.invalidateCompletenessCache(); mState.invalidateCompletenessCache();
mDirtyChannel.signal(); mDirtyChannel.signal();
......
...@@ -100,7 +100,7 @@ struct TextureState final : private angle::NonCopyable ...@@ -100,7 +100,7 @@ struct TextureState final : private angle::NonCopyable
bool isCubeComplete() const; bool isCubeComplete() const;
bool isSamplerComplete(const SamplerState &samplerState, const ContextState &data) const; bool isSamplerComplete(const SamplerState &samplerState, const ContextState &data) const;
void invalidateCompletenessCache(); void invalidateCompletenessCache() const;
const ImageDesc &getImageDesc(GLenum target, size_t level) const; const ImageDesc &getImageDesc(GLenum target, size_t level) const;
const ImageDesc &getImageDesc(const ImageIndex &imageIndex) const; const ImageDesc &getImageDesc(const ImageIndex &imageIndex) const;
...@@ -358,7 +358,7 @@ class Texture final : public egl::ImageSibling, ...@@ -358,7 +358,7 @@ class Texture final : public egl::ImageSibling,
egl::Surface *getBoundSurface() const; egl::Surface *getBoundSurface() const;
egl::Stream *getBoundStream() const; egl::Stream *getBoundStream() const;
void invalidateCompletenessCache(); void invalidateCompletenessCache() const;
rx::TextureImpl *getImplementation() const { return mTexture; } rx::TextureImpl *getImplementation() const { return mTexture; }
......
...@@ -320,11 +320,6 @@ using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER ...@@ -320,11 +320,6 @@ using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER
// Used in Framebuffer // Used in Framebuffer
using DrawBufferMask = angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS>; using DrawBufferMask = angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
// A map of GL objects indexed by object ID. The specific map implementation may change.
// Client code should treat it as a std::map.
template <class ResourceT>
using ResourceMap = std::unordered_map<GLuint, ResourceT *>;
using ContextID = uintptr_t; using ContextID = uintptr_t;
} }
......
...@@ -174,6 +174,7 @@ ...@@ -174,6 +174,7 @@
'libANGLE/Renderbuffer.h', 'libANGLE/Renderbuffer.h',
'libANGLE/ResourceManager.cpp', 'libANGLE/ResourceManager.cpp',
'libANGLE/ResourceManager.h', 'libANGLE/ResourceManager.h',
'libANGLE/ResourceMap.h',
'libANGLE/Sampler.cpp', 'libANGLE/Sampler.cpp',
'libANGLE/Sampler.h', 'libANGLE/Sampler.h',
'libANGLE/Shader.cpp', 'libANGLE/Shader.cpp',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment