aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-autoroll <android-autoroll@skia-public.iam.gserviceaccount.com>2024-05-10 18:47:32 +0000
committerandroid-autoroll <android-autoroll@skia-public.iam.gserviceaccount.com>2024-05-10 18:47:32 +0000
commitcc6c51a3256fe0dd44549f3068df962bd63f8d2e (patch)
tree74e0602752cfd1331ec59e9a5677d7d42d4e632f
parentf0597d3916094dca8852684b81950fe85a138d0f (diff)
parentd1bb6ed8399dd12e79484f30f9e9ded95c25625a (diff)
downloadangle-main.tar.gz
Roll ANGLE from 8d23fa3f92ed to d1bb6ed8399d (1 revision)HEADmastermain
https://chromium.googlesource.com/angle/angle.git/+log/8d23fa3f92ed..d1bb6ed8399d Please enable autosubmit on changes if possible when approving them. If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/angle-android-autoroll Please CC abdolrashidi@google.com,angle-team@google.com,rmistry@google.com on the revert to ensure that a human is aware of the problem. To file a bug in ANGLE: https://bugs.chromium.org/p/angleproject/issues/entry To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md Test: Presubmit checks will test this change. Exempt-From-Owner-Approval: The autoroll bot does not require owner approval. Change-Id: I40b39d1e27bb3b5b1c9920dd32523a7600b3790c
-rw-r--r--extensions/ANGLE_request_extension.txt4
-rw-r--r--src/libANGLE/Context.cpp14
-rw-r--r--src/libANGLE/ResourceManager.cpp60
-rw-r--r--src/libANGLE/ResourceManager.h6
-rw-r--r--src/libANGLE/ResourceMap.h42
-rw-r--r--src/libANGLE/ResourceMap_unittest.cpp10
-rw-r--r--src/libANGLE/capture/FrameCapture.cpp33
-rw-r--r--src/libANGLE/capture/serialize.cpp20
8 files changed, 124 insertions, 65 deletions
diff --git a/extensions/ANGLE_request_extension.txt b/extensions/ANGLE_request_extension.txt
index 88d3422e3b..56317e6d6a 100644
--- a/extensions/ANGLE_request_extension.txt
+++ b/extensions/ANGLE_request_extension.txt
@@ -85,7 +85,9 @@ Additions to the OpenGL ES 3.0 Specification
enable or disable the requestable OpenGL ES extension named <name>. If the
requested extension was not requestable or disablable, INVALID_OPERATION is
generated. Not all requestable extensions can be disabled. There is
- currently no query for disablable extensions.
+ currently no query for disablable extensions. This operation is not thread
+ safe, and the application is responsible for ensuring no other context in
+ the share group is accessed by another thread during this operation.
New State
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 1b23bd94a8..5eda734ca6 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -850,7 +850,7 @@ egl::Error Context::onDestroy(const egl::Display *display)
mDefaultFramebuffer->onDestroy(this);
mDefaultFramebuffer.reset();
- for (auto fence : mFenceNVMap)
+ for (auto fence : UnsafeResourceMapIter(mFenceNVMap))
{
if (fence.second)
{
@@ -860,7 +860,7 @@ egl::Error Context::onDestroy(const egl::Display *display)
}
mFenceNVMap.clear();
- for (auto query : mQueryMap)
+ for (auto query : UnsafeResourceMapIter(mQueryMap))
{
if (query.second != nullptr)
{
@@ -869,7 +869,7 @@ egl::Error Context::onDestroy(const egl::Display *display)
}
mQueryMap.clear();
- for (auto vertexArray : mVertexArrayMap)
+ for (auto vertexArray : UnsafeResourceMapIter(mVertexArrayMap))
{
if (vertexArray.second)
{
@@ -878,7 +878,7 @@ egl::Error Context::onDestroy(const egl::Display *display)
}
mVertexArrayMap.clear();
- for (auto transformFeedback : mTransformFeedbackMap)
+ for (auto transformFeedback : UnsafeResourceMapIter(mTransformFeedbackMap))
{
if (transformFeedback.second != nullptr)
{
@@ -3618,7 +3618,8 @@ void Context::beginTransformFeedback(PrimitiveMode primitiveMode)
bool Context::hasActiveTransformFeedback(ShaderProgramID program) const
{
- for (auto pair : mTransformFeedbackMap)
+ // Note: transform feedback objects are private to context and so the map doesn't need locking
+ for (auto pair : UnsafeResourceMapIter(mTransformFeedbackMap))
{
if (pair.second != nullptr && pair.second->hasBoundProgram(program))
{
@@ -4498,7 +4499,8 @@ void Context::updateCaps()
(mState.isWebGL() || mState.hasRobustAccess()));
// Cache this in the VertexArrays. They need to check it in state change notifications.
- for (auto vaoIter : mVertexArrayMap)
+ // Note: vertex array objects are private to context and so the map doesn't need locking
+ for (auto vaoIter : UnsafeResourceMapIter(mVertexArrayMap))
{
VertexArray *vao = vaoIter.second;
vao->setBufferAccessValidationEnabled(mBufferAccessValidationEnabled);
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index 8c63342b12..bf0c93d59e 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -61,14 +61,16 @@ void ResourceManagerBase::release(const Context *context)
template <typename ResourceType, typename ImplT, typename IDType>
TypedResourceManager<ResourceType, ImplT, IDType>::~TypedResourceManager()
{
- ASSERT(mObjectMap.empty());
+ ASSERT(UnsafeResourceMapIter(mObjectMap).empty());
}
template <typename ResourceType, typename ImplT, typename IDType>
void TypedResourceManager<ResourceType, ImplT, IDType>::reset(const Context *context)
{
+ // Note: this function is called when the last context in the share group is destroyed. Thus
+ // there are no thread safety concerns.
this->mHandleAllocator.reset();
- for (const auto &resource : mObjectMap)
+ for (const auto &resource : UnsafeResourceMapIter(mObjectMap))
{
if (resource.second)
{
@@ -138,21 +140,30 @@ ShaderProgramManager::ShaderProgramManager() {}
ShaderProgramManager::~ShaderProgramManager()
{
- ASSERT(mPrograms.empty());
- ASSERT(mShaders.empty());
+ ASSERT(UnsafeResourceMapIter(mPrograms).empty());
+ ASSERT(UnsafeResourceMapIter(mShaders).empty());
}
void ShaderProgramManager::reset(const Context *context)
{
- while (!mPrograms.empty())
+ // Note: this function is called when the last context in the share group is destroyed. Thus
+ // there are no thread safety concerns.
+ mHandleAllocator.reset();
+ for (const auto &program : UnsafeResourceMapIter(mPrograms))
{
- deleteProgram(context, {mPrograms.begin()->first});
+ if (program.second)
+ {
+ program.second->onDestroy(context);
+ }
}
- mPrograms.clear();
- while (!mShaders.empty())
+ for (const auto &shader : UnsafeResourceMapIter(mShaders))
{
- deleteShader(context, {mShaders.begin()->first});
+ if (shader.second)
+ {
+ shader.second->onDestroy(context);
+ }
}
+ mPrograms.clear();
mShaders.clear();
}
@@ -238,7 +249,9 @@ TextureID TextureManager::createTexture()
void TextureManager::signalAllTexturesDirty() const
{
- for (const auto &texture : mObjectMap)
+ // Note: this function is called with glRequestExtensionANGLE and glDisableExtensionANGLE. The
+ // GL_ANGLE_request_extension explicitly requires the application to ensure thread safety.
+ for (const auto &texture : UnsafeResourceMapIter(mObjectMap))
{
if (texture.second)
{
@@ -384,7 +397,8 @@ Framebuffer *FramebufferManager::getDefaultFramebuffer() const
void FramebufferManager::invalidateFramebufferCompletenessCache() const
{
- for (const auto &framebuffer : mObjectMap)
+ // Note: framebuffer objects are private to context and so the map doesn't need locking
+ for (const auto &framebuffer : UnsafeResourceMapIter(mObjectMap))
{
if (framebuffer.second)
{
@@ -428,14 +442,20 @@ MemoryObjectManager::MemoryObjectManager() {}
MemoryObjectManager::~MemoryObjectManager()
{
- ASSERT(mMemoryObjects.empty());
+ ASSERT(UnsafeResourceMapIter(mMemoryObjects).empty());
}
void MemoryObjectManager::reset(const Context *context)
{
- while (!mMemoryObjects.empty())
+ // Note: this function is called when the last context in the share group is destroyed. Thus
+ // there are no thread safety concerns.
+ mHandleAllocator.reset();
+ for (const auto &memoryObject : UnsafeResourceMapIter(mMemoryObjects))
{
- deleteMemoryObject(context, {mMemoryObjects.begin()->first});
+ if (memoryObject.second)
+ {
+ memoryObject.second->release(context);
+ }
}
mMemoryObjects.clear();
}
@@ -477,14 +497,20 @@ SemaphoreManager::SemaphoreManager() {}
SemaphoreManager::~SemaphoreManager()
{
- ASSERT(mSemaphores.empty());
+ ASSERT(UnsafeResourceMapIter(mSemaphores).empty());
}
void SemaphoreManager::reset(const Context *context)
{
- while (!mSemaphores.empty())
+ // Note: this function is called when the last context in the share group is destroyed. Thus
+ // there are no thread safety concerns.
+ mHandleAllocator.reset();
+ for (const auto &semaphore : UnsafeResourceMapIter(mSemaphores))
{
- deleteSemaphore(context, {mSemaphores.begin()->first});
+ if (semaphore.second)
+ {
+ semaphore.second->release(context);
+ }
}
mSemaphores.clear();
}
diff --git a/src/libANGLE/ResourceManager.h b/src/libANGLE/ResourceManager.h
index 710a88dd44..372b76b4b5 100644
--- a/src/libANGLE/ResourceManager.h
+++ b/src/libANGLE/ResourceManager.h
@@ -75,11 +75,7 @@ class TypedResourceManager : public ResourceManagerBase
return GetIDValue(handle) == 0 || mObjectMap.contains(handle);
}
- typename ResourceMap<ResourceType, IDType>::Iterator begin() const
- {
- return mObjectMap.begin();
- }
- typename ResourceMap<ResourceType, IDType>::Iterator end() const { return mObjectMap.end(); }
+ const ResourceMap<ResourceType, IDType> &getResourcesForCapture() const { return mObjectMap; }
protected:
~TypedResourceManager() override;
diff --git a/src/libANGLE/ResourceMap.h b/src/libANGLE/ResourceMap.h
index b454e261a2..92d6b6251d 100644
--- a/src/libANGLE/ResourceMap.h
+++ b/src/libANGLE/ResourceMap.h
@@ -73,6 +73,11 @@ class ResourceMap final : angle::NonCopyable
bool mSkipNulls;
};
+ private:
+ friend class Iterator;
+ template <typename SameResourceType, typename SameIDType>
+ friend class UnsafeResourceMapIter;
+
// null values represent reserved handles.
Iterator begin() const;
Iterator end() const;
@@ -80,12 +85,7 @@ class ResourceMap final : angle::NonCopyable
Iterator beginWithNull() const;
Iterator endWithNull() const;
- // Not a constant-time operation, should only be used for verification.
- bool empty() const;
-
- private:
- friend class Iterator;
-
+ // Used by iterators and related functions only (due to lack of thread safety).
GLuint nextResource(size_t flatIndex, bool skipNulls) const;
// constexpr methods cannot contain reinterpret_cast, so we need a static method.
@@ -108,6 +108,30 @@ class ResourceMap final : angle::NonCopyable
HashMap mHashedResources;
};
+// A helper to retrieve the resource map iterators while being explicit that this is not thread
+// safe. Usage of iterators are limited to clean up on destruction and capture/replay, neither of
+// which can race with other threads in their access to the resource map.
+template <typename ResourceType, typename IDType>
+class UnsafeResourceMapIter
+{
+ public:
+ using ResMap = ResourceMap<ResourceType, IDType>;
+
+ UnsafeResourceMapIter(const ResMap &resourceMap) : mResourceMap(resourceMap) {}
+
+ typename ResMap::Iterator begin() const { return mResourceMap.begin(); }
+ typename ResMap::Iterator end() const { return mResourceMap.end(); }
+
+ typename ResMap::Iterator beginWithNull() const { return mResourceMap.beginWithNull(); }
+ typename ResMap::Iterator endWithNull() const { return mResourceMap.endWithNull(); }
+
+ // Not a constant-time operation, should only be used for verification.
+ bool empty() const;
+
+ private:
+ const ResMap &mResourceMap;
+};
+
template <typename ResourceType, typename IDType>
ResourceMap<ResourceType, IDType>::ResourceMap()
: mFlatResourcesSize(kInitialFlatResourcesSize),
@@ -119,7 +143,7 @@ ResourceMap<ResourceType, IDType>::ResourceMap()
template <typename ResourceType, typename IDType>
ResourceMap<ResourceType, IDType>::~ResourceMap()
{
- ASSERT(empty());
+ ASSERT(UnsafeResourceMapIter(*this).empty());
delete[] mFlatResources;
}
@@ -222,9 +246,9 @@ ResourceMap<ResourceType, IDType>::endWithNull() const
}
template <typename ResourceType, typename IDType>
-bool ResourceMap<ResourceType, IDType>::empty() const
+bool UnsafeResourceMapIter<ResourceType, IDType>::empty() const
{
- return (begin() == end());
+ return begin() == end();
}
template <typename ResourceType, typename IDType>
diff --git a/src/libANGLE/ResourceMap_unittest.cpp b/src/libANGLE/ResourceMap_unittest.cpp
index 056dde518a..01d2d706ba 100644
--- a/src/libANGLE/ResourceMap_unittest.cpp
+++ b/src/libANGLE/ResourceMap_unittest.cpp
@@ -33,7 +33,7 @@ TEST(ResourceMapTest, AssignAndErase)
ASSERT_EQ(&objects[index], found);
}
- ASSERT_TRUE(resourceMap.empty());
+ ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty());
}
// Tests assigning slots in the map and then using clear() to free it.
@@ -48,7 +48,7 @@ TEST(ResourceMapTest, AssignAndClear)
}
resourceMap.clear();
- ASSERT_TRUE(resourceMap.empty());
+ ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty());
}
// Tests growing a map more than double the size.
@@ -80,7 +80,7 @@ TEST(ResourceMapTest, BigGrowth)
ASSERT_EQ(object, *found);
}
- ASSERT_TRUE(resourceMap.empty());
+ ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty());
}
// Tests querying unassigned or erased values.
@@ -106,7 +106,7 @@ TEST(ResourceMapTest, QueryUnassigned)
resourceMap.assign(object, &object);
}
- ASSERT_FALSE(resourceMap.empty());
+ ASSERT_FALSE(UnsafeResourceMapIter(resourceMap).empty());
for (size_t &object : objects)
{
@@ -126,7 +126,7 @@ TEST(ResourceMapTest, QueryUnassigned)
ASSERT_EQ(object, *found);
}
- ASSERT_TRUE(resourceMap.empty());
+ ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty());
ASSERT_FALSE(resourceMap.contains(0));
ASSERT_EQ(nullptr, resourceMap.query(0));
diff --git a/src/libANGLE/capture/FrameCapture.cpp b/src/libANGLE/capture/FrameCapture.cpp
index 22daf186f7..3d9680aa94 100644
--- a/src/libANGLE/capture/FrameCapture.cpp
+++ b/src/libANGLE/capture/FrameCapture.cpp
@@ -4125,7 +4125,7 @@ void CaptureShareGroupMidExecutionSetup(
// Capture Buffer data.
const gl::BufferManager &buffers = apiState.getBufferManagerForCapture();
- for (const auto &bufferIter : buffers)
+ for (const auto &bufferIter : gl::UnsafeResourceMapIter(buffers.getResourcesForCapture()))
{
gl::BufferID id = {bufferIter.first};
gl::Buffer *buffer = bufferIter.second;
@@ -4267,7 +4267,7 @@ void CaptureShareGroupMidExecutionSetup(
// Capture Texture setup and data.
const gl::TextureManager &textures = apiState.getTextureManagerForCapture();
- for (const auto &textureIter : textures)
+ for (const auto &textureIter : gl::UnsafeResourceMapIter(textures.getResourcesForCapture()))
{
gl::TextureID id = {textureIter.first};
gl::Texture *texture = textureIter.second;
@@ -4593,7 +4593,8 @@ void CaptureShareGroupMidExecutionSetup(
const gl::RenderbufferManager &renderbuffers = apiState.getRenderbufferManagerForCapture();
FramebufferCaptureFuncs framebufferFuncs(context->isGLES1());
- for (const auto &renderbufIter : renderbuffers)
+ for (const auto &renderbufIter :
+ gl::UnsafeResourceMapIter(renderbuffers.getResourcesForCapture()))
{
gl::RenderbufferID id = {renderbufIter.first};
const gl::Renderbuffer *renderbuffer = renderbufIter.second;
@@ -4657,7 +4658,7 @@ void CaptureShareGroupMidExecutionSetup(
// Capture Program binary state.
gl::ShaderProgramID tempShaderStartID = {resourceTracker->getMaxShaderPrograms()};
std::map<gl::ShaderProgramID, std::vector<gl::ShaderProgramID>> deferredAttachCalls;
- for (const auto &programIter : programs)
+ for (const auto &programIter : gl::UnsafeResourceMapIter(programs))
{
gl::ShaderProgramID id = {programIter.first};
gl::Program *program = programIter.second;
@@ -4738,7 +4739,7 @@ void CaptureShareGroupMidExecutionSetup(
}
// Handle shaders.
- for (const auto &shaderIter : shaders)
+ for (const auto &shaderIter : gl::UnsafeResourceMapIter(shaders))
{
gl::ShaderProgramID id = {shaderIter.first};
gl::Shader *shader = shaderIter.second;
@@ -4827,7 +4828,7 @@ void CaptureShareGroupMidExecutionSetup(
// Capture Sampler Objects
const gl::SamplerManager &samplers = apiState.getSamplerManagerForCapture();
- for (const auto &samplerIter : samplers)
+ for (const auto &samplerIter : gl::UnsafeResourceMapIter(samplers.getResourcesForCapture()))
{
gl::SamplerID samplerID = {samplerIter.first};
@@ -4892,7 +4893,7 @@ void CaptureShareGroupMidExecutionSetup(
// Capture Sync Objects
const gl::SyncManager &syncs = apiState.getSyncManagerForCapture();
- for (const auto &syncIter : syncs)
+ for (const auto &syncIter : gl::UnsafeResourceMapIter(syncs.getResourcesForCapture()))
{
gl::SyncID syncID = {syncIter.first};
const gl::Sync *sync = syncIter.second;
@@ -4967,7 +4968,7 @@ void CaptureMidExecutionSetup(const gl::Context *context,
const gl::VertexArrayMap &vertexArrayMap = context->getVertexArraysForCapture();
gl::VertexArrayID boundVertexArrayID = {0};
- for (const auto &vertexArrayIter : vertexArrayMap)
+ for (const auto &vertexArrayIter : gl::UnsafeResourceMapIter(vertexArrayMap))
{
TrackedResource &trackedVertexArrays =
resourceTracker->getTrackedResource(context->id(), ResourceIDType::VertexArray);
@@ -5145,7 +5146,8 @@ void CaptureMidExecutionSetup(const gl::Context *context,
const gl::RenderbufferManager &renderbuffers = apiState.getRenderbufferManagerForCapture();
gl::RenderbufferID currentRenderbuffer = {0};
- for (const auto &renderbufIter : renderbuffers)
+ for (const auto &renderbufIter :
+ gl::UnsafeResourceMapIter(renderbuffers.getResourcesForCapture()))
{
currentRenderbuffer = renderbufIter.second->id();
}
@@ -5162,7 +5164,8 @@ void CaptureMidExecutionSetup(const gl::Context *context,
gl::FramebufferID currentDrawFramebuffer = {0};
gl::FramebufferID currentReadFramebuffer = {0};
- for (const auto &framebufferIter : framebuffers)
+ for (const auto &framebufferIter :
+ gl::UnsafeResourceMapIter(framebuffers.getResourcesForCapture()))
{
gl::FramebufferID id = {framebufferIter.first};
const gl::Framebuffer *framebuffer = framebufferIter.second;
@@ -5297,7 +5300,8 @@ void CaptureMidExecutionSetup(const gl::Context *context,
const gl::ProgramPipelineManager *programPipelineManager =
apiState.getProgramPipelineManagerForCapture();
- for (const auto &ppoIterator : *programPipelineManager)
+ for (const auto &ppoIterator :
+ gl::UnsafeResourceMapIter(programPipelineManager->getResourcesForCapture()))
{
gl::ProgramPipeline *pipeline = ppoIterator.second;
gl::ProgramPipelineID id = {ppoIterator.first};
@@ -5380,8 +5384,9 @@ void CaptureMidExecutionSetup(const gl::Context *context,
// Create existing queries. Note that queries may be genned and not yet started. In that
// case the queries will exist in the query map as nullptr entries.
const gl::QueryMap &queryMap = context->getQueriesForCapture();
- for (gl::QueryMap::Iterator queryIter = queryMap.beginWithNull();
- queryIter != queryMap.endWithNull(); ++queryIter)
+ for (gl::QueryMap::Iterator queryIter = gl::UnsafeResourceMapIter(queryMap).beginWithNull(),
+ endIter = gl::UnsafeResourceMapIter(queryMap).endWithNull();
+ queryIter != endIter; ++queryIter)
{
ASSERT(queryIter->first);
gl::QueryID queryID = {queryIter->first};
@@ -5407,7 +5412,7 @@ void CaptureMidExecutionSetup(const gl::Context *context,
// Transform Feedback
const gl::TransformFeedbackMap &xfbMap = context->getTransformFeedbacksForCapture();
- for (const auto &xfbIter : xfbMap)
+ for (const auto &xfbIter : gl::UnsafeResourceMapIter(xfbMap))
{
gl::TransformFeedbackID xfbID = {xfbIter.first};
diff --git a/src/libANGLE/capture/serialize.cpp b/src/libANGLE/capture/serialize.cpp
index c1138a7f34..61655020a6 100644
--- a/src/libANGLE/capture/serialize.cpp
+++ b/src/libANGLE/capture/serialize.cpp
@@ -1404,7 +1404,8 @@ Result SerializeContextToString(const gl::Context *context, std::string *stringO
const gl::FramebufferManager &framebufferManager =
context->getState().getFramebufferManagerForCapture();
GroupScope framebufferGroup(&json, "FramebufferManager");
- for (const auto &framebuffer : framebufferManager)
+ for (const auto &framebuffer :
+ gl::UnsafeResourceMapIter(framebufferManager.getResourcesForCapture()))
{
gl::Framebuffer *framebufferPtr = framebuffer.second;
ANGLE_TRY(SerializeFramebuffer(context, &json, &scratchBuffer, framebufferPtr));
@@ -1413,7 +1414,7 @@ Result SerializeContextToString(const gl::Context *context, std::string *stringO
{
const gl::BufferManager &bufferManager = context->getState().getBufferManagerForCapture();
GroupScope framebufferGroup(&json, "BufferManager");
- for (const auto &buffer : bufferManager)
+ for (const auto &buffer : gl::UnsafeResourceMapIter(bufferManager.getResourcesForCapture()))
{
gl::Buffer *bufferPtr = buffer.second;
ANGLE_TRY(SerializeBuffer(context, &json, &scratchBuffer, bufferPtr));
@@ -1423,7 +1424,8 @@ Result SerializeContextToString(const gl::Context *context, std::string *stringO
const gl::SamplerManager &samplerManager =
context->getState().getSamplerManagerForCapture();
GroupScope samplerGroup(&json, "SamplerManager");
- for (const auto &sampler : samplerManager)
+ for (const auto &sampler :
+ gl::UnsafeResourceMapIter(samplerManager.getResourcesForCapture()))
{
gl::Sampler *samplerPtr = sampler.second;
SerializeSampler(&json, samplerPtr);
@@ -1433,7 +1435,8 @@ Result SerializeContextToString(const gl::Context *context, std::string *stringO
const gl::RenderbufferManager &renderbufferManager =
context->getState().getRenderbufferManagerForCapture();
GroupScope renderbufferGroup(&json, "RenderbufferManager");
- for (const auto &renderbuffer : renderbufferManager)
+ for (const auto &renderbuffer :
+ gl::UnsafeResourceMapIter(renderbufferManager.getResourcesForCapture()))
{
gl::Renderbuffer *renderbufferPtr = renderbuffer.second;
ANGLE_TRY(SerializeRenderbuffer(context, &json, &scratchBuffer, renderbufferPtr));
@@ -1445,7 +1448,7 @@ Result SerializeContextToString(const gl::Context *context, std::string *stringO
const gl::ResourceMap<gl::Shader, gl::ShaderProgramID> &shaderManager =
shaderProgramManager.getShadersForCapture();
GroupScope shaderGroup(&json, "ShaderManager");
- for (const auto &shader : shaderManager)
+ for (const auto &shader : gl::UnsafeResourceMapIter(shaderManager))
{
GLuint id = shader.first;
gl::Shader *shaderPtr = shader.second;
@@ -1456,7 +1459,7 @@ Result SerializeContextToString(const gl::Context *context, std::string *stringO
const gl::ResourceMap<gl::Program, gl::ShaderProgramID> &programManager =
shaderProgramManager.getProgramsForCaptureAndPerf();
GroupScope shaderGroup(&json, "ProgramManager");
- for (const auto &program : programManager)
+ for (const auto &program : gl::UnsafeResourceMapIter(programManager))
{
GLuint id = program.first;
gl::Program *programPtr = program.second;
@@ -1467,7 +1470,8 @@ Result SerializeContextToString(const gl::Context *context, std::string *stringO
const gl::TextureManager &textureManager =
context->getState().getTextureManagerForCapture();
GroupScope shaderGroup(&json, "TextureManager");
- for (const auto &texture : textureManager)
+ for (const auto &texture :
+ gl::UnsafeResourceMapIter(textureManager.getResourcesForCapture()))
{
gl::Texture *texturePtr = texture.second;
ANGLE_TRY(SerializeTexture(context, &json, &scratchBuffer, texturePtr));
@@ -1476,7 +1480,7 @@ Result SerializeContextToString(const gl::Context *context, std::string *stringO
{
const gl::VertexArrayMap &vertexArrayMap = context->getVertexArraysForCapture();
GroupScope shaderGroup(&json, "VertexArrayMap");
- for (const auto &vertexArray : vertexArrayMap)
+ for (const auto &vertexArray : gl::UnsafeResourceMapIter(vertexArrayMap))
{
gl::VertexArray *vertexArrayPtr = vertexArray.second;
SerializeVertexArray(&json, vertexArrayPtr);