Fix ResourceManager create-on-bind reallocations.
*re-land with build fix for Clang*
We had a funny bug where the Handle Allocator would re-allocate
reserved handles after the app layer creates one with Bind rather
than using Gen. This affects Textures, Buffers and Renderbuffers.
Fix this by using a different allocation scheme. It should still
be fast on the "good" case (using Gen) and use tree lookups on the
bind case. Also add some unit tests.
BUG=angleproject:942
Change-Id: I63ce608fcd6a11f92e2b5421f090551934e729ed
Reviewed-on: https://chromium-review.googlesource.com/261591
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index 71a6a32..aaf144c 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -356,33 +356,84 @@
mRenderbufferMap[handle] = buffer;
}
-void ResourceManager::checkBufferAllocation(unsigned int buffer)
+void ResourceManager::checkBufferAllocation(GLuint handle)
{
- if (buffer != 0 && !getBuffer(buffer))
+ if (handle != 0)
{
- Buffer *bufferObject = new Buffer(mFactory->createBuffer(), buffer);
- mBufferMap[buffer] = bufferObject;
- bufferObject->addRef();
+ auto bufferMapIt = mBufferMap.find(handle);
+ bool handleAllocated = (bufferMapIt != mBufferMap.end());
+
+ if (handleAllocated && bufferMapIt->second != nullptr)
+ {
+ return;
+ }
+
+ Buffer *buffer = new Buffer(mFactory->createBuffer(), handle);
+ buffer->addRef();
+
+ if (handleAllocated)
+ {
+ bufferMapIt->second = buffer;
+ }
+ else
+ {
+ mBufferHandleAllocator.reserve(handle);
+ mBufferMap[handle] = buffer;
+ }
}
}
-void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type)
+void ResourceManager::checkTextureAllocation(GLuint handle, GLenum type)
{
- if (!getTexture(texture) && texture != 0)
+ if (handle != 0)
{
- Texture *textureObject = new Texture(mFactory->createTexture(type), texture, type);
- mTextureMap[texture] = textureObject;
- textureObject->addRef();
+ auto textureMapIt = mTextureMap.find(handle);
+ bool handleAllocated = (textureMapIt != mTextureMap.end());
+
+ if (handleAllocated && textureMapIt->second != nullptr)
+ {
+ return;
+ }
+
+ Texture *texture = new Texture(mFactory->createTexture(type), handle, type);
+ texture->addRef();
+
+ if (handleAllocated)
+ {
+ textureMapIt->second = texture;
+ }
+ else
+ {
+ mTextureHandleAllocator.reserve(handle);
+ mTextureMap[handle] = texture;
+ }
}
}
-void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
+void ResourceManager::checkRenderbufferAllocation(GLuint handle)
{
- if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
+ if (handle != 0)
{
- Renderbuffer *renderbufferObject = new Renderbuffer(mFactory->createRenderbuffer(), renderbuffer);
- mRenderbufferMap[renderbuffer] = renderbufferObject;
- renderbufferObject->addRef();
+ auto renderbufferMapIt = mRenderbufferMap.find(handle);
+ bool handleAllocated = (renderbufferMapIt != mRenderbufferMap.end());
+
+ if (handleAllocated && renderbufferMapIt->second != nullptr)
+ {
+ return;
+ }
+
+ Renderbuffer *renderbuffer = new Renderbuffer(mFactory->createRenderbuffer(), handle);
+ renderbuffer->addRef();
+
+ if (handleAllocated)
+ {
+ renderbufferMapIt->second = renderbuffer;
+ }
+ else
+ {
+ mRenderbufferHandleAllocator.reserve(handle);
+ mRenderbufferMap[handle] = renderbuffer;
+ }
}
}
@@ -393,6 +444,7 @@
Sampler *samplerObject = new Sampler(sampler);
mSamplerMap[sampler] = samplerObject;
samplerObject->addRef();
+ // Samplers cannot be created via Bind
}
}