diff options
author | android-autoroll <android-autoroll@skia-public.iam.gserviceaccount.com> | 2024-05-10 18:47:32 +0000 |
---|---|---|
committer | android-autoroll <android-autoroll@skia-public.iam.gserviceaccount.com> | 2024-05-10 18:47:32 +0000 |
commit | cc6c51a3256fe0dd44549f3068df962bd63f8d2e (patch) | |
tree | 74e0602752cfd1331ec59e9a5677d7d42d4e632f | |
parent | f0597d3916094dca8852684b81950fe85a138d0f (diff) | |
parent | d1bb6ed8399dd12e79484f30f9e9ded95c25625a (diff) | |
download | angle-main.tar.gz |
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.txt | 4 | ||||
-rw-r--r-- | src/libANGLE/Context.cpp | 14 | ||||
-rw-r--r-- | src/libANGLE/ResourceManager.cpp | 60 | ||||
-rw-r--r-- | src/libANGLE/ResourceManager.h | 6 | ||||
-rw-r--r-- | src/libANGLE/ResourceMap.h | 42 | ||||
-rw-r--r-- | src/libANGLE/ResourceMap_unittest.cpp | 10 | ||||
-rw-r--r-- | src/libANGLE/capture/FrameCapture.cpp | 33 | ||||
-rw-r--r-- | src/libANGLE/capture/serialize.cpp | 20 |
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); |