xref: /aosp_15_r20/external/angle/src/libANGLE/ResourceManager.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // ResourceManager.cpp: Implements the the ResourceManager classes, which handle allocation and
8 // lifetime of GL objects.
9 
10 #include "libANGLE/ResourceManager.h"
11 
12 #include "libANGLE/Buffer.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Fence.h"
15 #include "libANGLE/MemoryObject.h"
16 #include "libANGLE/Program.h"
17 #include "libANGLE/ProgramPipeline.h"
18 #include "libANGLE/Query.h"
19 #include "libANGLE/Renderbuffer.h"
20 #include "libANGLE/Sampler.h"
21 #include "libANGLE/Semaphore.h"
22 #include "libANGLE/Shader.h"
23 #include "libANGLE/Texture.h"
24 #include "libANGLE/renderer/ContextImpl.h"
25 
26 namespace gl
27 {
28 
29 namespace
30 {
31 
32 template <typename ResourceType, typename IDType>
AllocateEmptyObject(HandleAllocator * handleAllocator,ResourceMap<ResourceType,IDType> * objectMap)33 IDType AllocateEmptyObject(HandleAllocator *handleAllocator,
34                            ResourceMap<ResourceType, IDType> *objectMap)
35 {
36     IDType handle = PackParam<IDType>(handleAllocator->allocate());
37     objectMap->assign(handle, nullptr);
38     return handle;
39 }
40 
41 }  // anonymous namespace
42 
ResourceManagerBase()43 ResourceManagerBase::ResourceManagerBase() : mRefCount(1) {}
44 
45 ResourceManagerBase::~ResourceManagerBase() = default;
46 
addRef()47 void ResourceManagerBase::addRef()
48 {
49     mRefCount++;
50 }
51 
release(const Context * context)52 void ResourceManagerBase::release(const Context *context)
53 {
54     if (--mRefCount == 0)
55     {
56         reset(context);
57         delete this;
58     }
59 }
60 
61 template <typename ResourceType, typename ImplT, typename IDType>
~TypedResourceManager()62 TypedResourceManager<ResourceType, ImplT, IDType>::~TypedResourceManager()
63 {
64     using UnsafeResourceMapIterTyped = UnsafeResourceMapIter<ResourceType, IDType>;
65     ASSERT(UnsafeResourceMapIterTyped(mObjectMap).empty());
66 }
67 
68 template <typename ResourceType, typename ImplT, typename IDType>
reset(const Context * context)69 void TypedResourceManager<ResourceType, ImplT, IDType>::reset(const Context *context)
70 {
71     // Note: this function is called when the last context in the share group is destroyed.  Thus
72     // there are no thread safety concerns.
73     this->mHandleAllocator.reset();
74     for (const auto &resource : UnsafeResourceMapIter(mObjectMap))
75     {
76         if (resource.second)
77         {
78             ImplT::DeleteObject(context, resource.second);
79         }
80     }
81     mObjectMap.clear();
82 }
83 
84 template <typename ResourceType, typename ImplT, typename IDType>
deleteObject(const Context * context,IDType handle)85 void TypedResourceManager<ResourceType, ImplT, IDType>::deleteObject(const Context *context,
86                                                                      IDType handle)
87 {
88     ResourceType *resource = nullptr;
89     if (!mObjectMap.erase(handle, &resource))
90     {
91         return;
92     }
93 
94     // Requires an explicit this-> because of C++ template rules.
95     this->mHandleAllocator.release(GetIDValue(handle));
96 
97     if (resource)
98     {
99         ImplT::DeleteObject(context, resource);
100     }
101 }
102 
103 template class TypedResourceManager<Buffer, BufferManager, BufferID>;
104 template class TypedResourceManager<Texture, TextureManager, TextureID>;
105 template class TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID>;
106 template class TypedResourceManager<Sampler, SamplerManager, SamplerID>;
107 template class TypedResourceManager<Sync, SyncManager, SyncID>;
108 template class TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID>;
109 template class TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID>;
110 
111 // BufferManager Implementation.
112 BufferManager::~BufferManager() = default;
113 
114 // static
AllocateNewObject(rx::GLImplFactory * factory,BufferID handle)115 Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, BufferID handle)
116 {
117     Buffer *buffer = new Buffer(factory, handle);
118     buffer->addRef();
119     return buffer;
120 }
121 
122 // static
DeleteObject(const Context * context,Buffer * buffer)123 void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
124 {
125     buffer->release(context);
126 }
127 
createBuffer()128 BufferID BufferManager::createBuffer()
129 {
130     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
131 }
132 
getBuffer(BufferID handle) const133 Buffer *BufferManager::getBuffer(BufferID handle) const
134 {
135     return mObjectMap.query(handle);
136 }
137 
138 // ShaderProgramManager Implementation.
139 
ShaderProgramManager()140 ShaderProgramManager::ShaderProgramManager() {}
141 
~ShaderProgramManager()142 ShaderProgramManager::~ShaderProgramManager()
143 {
144     ASSERT(UnsafeResourceMapIter(mPrograms).empty());
145     ASSERT(UnsafeResourceMapIter(mShaders).empty());
146 }
147 
reset(const Context * context)148 void ShaderProgramManager::reset(const Context *context)
149 {
150     // Note: this function is called when the last context in the share group is destroyed.  Thus
151     // there are no thread safety concerns.
152     mHandleAllocator.reset();
153     for (const auto &program : UnsafeResourceMapIter(mPrograms))
154     {
155         if (program.second)
156         {
157             program.second->onDestroy(context);
158         }
159     }
160     for (const auto &shader : UnsafeResourceMapIter(mShaders))
161     {
162         if (shader.second)
163         {
164             shader.second->onDestroy(context);
165         }
166     }
167     mPrograms.clear();
168     mShaders.clear();
169 }
170 
createShader(rx::GLImplFactory * factory,const gl::Limitations & rendererLimitations,ShaderType type)171 ShaderProgramID ShaderProgramManager::createShader(rx::GLImplFactory *factory,
172                                                    const gl::Limitations &rendererLimitations,
173                                                    ShaderType type)
174 {
175     ASSERT(type != ShaderType::InvalidEnum);
176     ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
177     mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
178     return handle;
179 }
180 
deleteShader(const Context * context,ShaderProgramID shader)181 void ShaderProgramManager::deleteShader(const Context *context, ShaderProgramID shader)
182 {
183     deleteObject(context, &mShaders, shader);
184 }
185 
getShader(ShaderProgramID handle) const186 Shader *ShaderProgramManager::getShader(ShaderProgramID handle) const
187 {
188     return mShaders.query(handle);
189 }
190 
createProgram(rx::GLImplFactory * factory)191 ShaderProgramID ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
192 {
193     ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
194     mPrograms.assign(handle, new Program(factory, this, handle));
195     return handle;
196 }
197 
deleteProgram(const gl::Context * context,ShaderProgramID program)198 void ShaderProgramManager::deleteProgram(const gl::Context *context, ShaderProgramID program)
199 {
200     deleteObject(context, &mPrograms, program);
201 }
202 
203 template <typename ObjectType, typename IDType>
deleteObject(const Context * context,ResourceMap<ObjectType,IDType> * objectMap,IDType id)204 void ShaderProgramManager::deleteObject(const Context *context,
205                                         ResourceMap<ObjectType, IDType> *objectMap,
206                                         IDType id)
207 {
208     ObjectType *object = objectMap->query(id);
209     if (!object)
210     {
211         return;
212     }
213 
214     if (object->getRefCount() == 0)
215     {
216         mHandleAllocator.release(id.value);
217         object->onDestroy(context);
218         objectMap->erase(id, &object);
219     }
220     else
221     {
222         object->flagForDeletion();
223     }
224 }
225 
226 // TextureManager Implementation.
227 
228 TextureManager::~TextureManager() = default;
229 
230 // static
AllocateNewObject(rx::GLImplFactory * factory,TextureID handle,TextureType type)231 Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
232                                            TextureID handle,
233                                            TextureType type)
234 {
235     Texture *texture = new Texture(factory, handle, type);
236     texture->addRef();
237     return texture;
238 }
239 
240 // static
DeleteObject(const Context * context,Texture * texture)241 void TextureManager::DeleteObject(const Context *context, Texture *texture)
242 {
243     texture->release(context);
244 }
245 
createTexture()246 TextureID TextureManager::createTexture()
247 {
248     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
249 }
250 
signalAllTexturesDirty() const251 void TextureManager::signalAllTexturesDirty() const
252 {
253     // Note: this function is called with glRequestExtensionANGLE and glDisableExtensionANGLE.  The
254     // GL_ANGLE_request_extension explicitly requires the application to ensure thread safety.
255     for (const auto &texture : UnsafeResourceMapIter(mObjectMap))
256     {
257         if (texture.second)
258         {
259             // We don't know if the Texture needs init, but that's ok, since it will only force
260             // a re-check, and will not initialize the pixels if it's not needed.
261             texture.second->signalDirtyStorage(InitState::MayNeedInit);
262         }
263     }
264 }
265 
enableHandleAllocatorLogging()266 void TextureManager::enableHandleAllocatorLogging()
267 {
268     mHandleAllocator.enableLogging(true);
269 }
270 
271 // RenderbufferManager Implementation.
272 
273 RenderbufferManager::~RenderbufferManager() = default;
274 
275 // static
AllocateNewObject(rx::GLImplFactory * factory,RenderbufferID handle)276 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
277                                                      RenderbufferID handle)
278 {
279     Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
280     renderbuffer->addRef();
281     return renderbuffer;
282 }
283 
284 // static
DeleteObject(const Context * context,Renderbuffer * renderbuffer)285 void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
286 {
287     renderbuffer->release(context);
288 }
289 
createRenderbuffer()290 RenderbufferID RenderbufferManager::createRenderbuffer()
291 {
292     return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
293 }
294 
getRenderbuffer(RenderbufferID handle) const295 Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
296 {
297     return mObjectMap.query(handle);
298 }
299 
300 // SamplerManager Implementation.
301 
302 SamplerManager::~SamplerManager() = default;
303 
304 // static
AllocateNewObject(rx::GLImplFactory * factory,SamplerID handle)305 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle)
306 {
307     Sampler *sampler = new Sampler(factory, handle);
308     sampler->addRef();
309     return sampler;
310 }
311 
312 // static
DeleteObject(const Context * context,Sampler * sampler)313 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
314 {
315     sampler->release(context);
316 }
317 
createSampler()318 SamplerID SamplerManager::createSampler()
319 {
320     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
321 }
322 
getSampler(SamplerID handle) const323 Sampler *SamplerManager::getSampler(SamplerID handle) const
324 {
325     return mObjectMap.query(handle);
326 }
327 
isSampler(SamplerID sampler) const328 bool SamplerManager::isSampler(SamplerID sampler) const
329 {
330     return mObjectMap.contains(sampler);
331 }
332 
333 // SyncManager Implementation.
334 
335 SyncManager::~SyncManager() = default;
336 
337 // static
DeleteObject(const Context * context,Sync * sync)338 void SyncManager::DeleteObject(const Context *context, Sync *sync)
339 {
340     sync->release(context);
341 }
342 
createSync(rx::GLImplFactory * factory)343 SyncID SyncManager::createSync(rx::GLImplFactory *factory)
344 {
345     SyncID handle = {mHandleAllocator.allocate()};
346     Sync *sync    = new Sync(factory, handle);
347     sync->addRef();
348     mObjectMap.assign(handle, sync);
349     return handle;
350 }
351 
getSync(SyncID handle) const352 Sync *SyncManager::getSync(SyncID handle) const
353 {
354     return mObjectMap.query(handle);
355 }
356 
357 // FramebufferManager Implementation.
358 
359 FramebufferManager::~FramebufferManager() = default;
360 
361 // static
AllocateNewObject(rx::GLImplFactory * factory,FramebufferID handle,const Context * context)362 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
363                                                    FramebufferID handle,
364                                                    const Context *context)
365 {
366     // Make sure the caller isn't using a reserved handle.
367     ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
368     return new Framebuffer(context, factory, handle);
369 }
370 
371 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)372 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
373 {
374     framebuffer->onDestroy(context);
375     delete framebuffer;
376 }
377 
createFramebuffer()378 FramebufferID FramebufferManager::createFramebuffer()
379 {
380     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
381 }
382 
getFramebuffer(FramebufferID handle) const383 Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const
384 {
385     return mObjectMap.query(handle);
386 }
387 
setDefaultFramebuffer(Framebuffer * framebuffer)388 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
389 {
390     ASSERT(framebuffer == nullptr || framebuffer->isDefault());
391     mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer);
392 }
393 
getDefaultFramebuffer() const394 Framebuffer *FramebufferManager::getDefaultFramebuffer() const
395 {
396     return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
397 }
398 
invalidateFramebufferCompletenessCache() const399 void FramebufferManager::invalidateFramebufferCompletenessCache() const
400 {
401     // Note: framebuffer objects are private to context and so the map doesn't need locking
402     for (const auto &framebuffer : UnsafeResourceMapIter(mObjectMap))
403     {
404         if (framebuffer.second)
405         {
406             framebuffer.second->invalidateCompletenessCache();
407         }
408     }
409 }
410 
411 // ProgramPipelineManager Implementation.
412 
413 ProgramPipelineManager::~ProgramPipelineManager() = default;
414 
415 // static
AllocateNewObject(rx::GLImplFactory * factory,ProgramPipelineID handle)416 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
417                                                            ProgramPipelineID handle)
418 {
419     ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
420     pipeline->addRef();
421     return pipeline;
422 }
423 
424 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)425 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
426 {
427     pipeline->release(context);
428 }
429 
createProgramPipeline()430 ProgramPipelineID ProgramPipelineManager::createProgramPipeline()
431 {
432     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
433 }
434 
getProgramPipeline(ProgramPipelineID handle) const435 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const
436 {
437     return mObjectMap.query(handle);
438 }
439 
440 // MemoryObjectManager Implementation.
441 
MemoryObjectManager()442 MemoryObjectManager::MemoryObjectManager() {}
443 
~MemoryObjectManager()444 MemoryObjectManager::~MemoryObjectManager()
445 {
446     ASSERT(UnsafeResourceMapIter(mMemoryObjects).empty());
447 }
448 
reset(const Context * context)449 void MemoryObjectManager::reset(const Context *context)
450 {
451     // Note: this function is called when the last context in the share group is destroyed.  Thus
452     // there are no thread safety concerns.
453     mHandleAllocator.reset();
454     for (const auto &memoryObject : UnsafeResourceMapIter(mMemoryObjects))
455     {
456         if (memoryObject.second)
457         {
458             memoryObject.second->release(context);
459         }
460     }
461     mMemoryObjects.clear();
462 }
463 
createMemoryObject(rx::GLImplFactory * factory)464 MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
465 {
466     MemoryObjectID handle      = MemoryObjectID{mHandleAllocator.allocate()};
467     MemoryObject *memoryObject = new MemoryObject(factory, handle);
468     memoryObject->addRef();
469     mMemoryObjects.assign(handle, memoryObject);
470     return handle;
471 }
472 
deleteMemoryObject(const Context * context,MemoryObjectID handle)473 void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle)
474 {
475     MemoryObject *memoryObject = nullptr;
476     if (!mMemoryObjects.erase(handle, &memoryObject))
477     {
478         return;
479     }
480 
481     // Requires an explicit this-> because of C++ template rules.
482     this->mHandleAllocator.release(handle.value);
483 
484     if (memoryObject)
485     {
486         memoryObject->release(context);
487     }
488 }
489 
getMemoryObject(MemoryObjectID handle) const490 MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const
491 {
492     return mMemoryObjects.query(handle);
493 }
494 
495 // SemaphoreManager Implementation.
496 
SemaphoreManager()497 SemaphoreManager::SemaphoreManager() {}
498 
~SemaphoreManager()499 SemaphoreManager::~SemaphoreManager()
500 {
501     ASSERT(UnsafeResourceMapIter(mSemaphores).empty());
502 }
503 
reset(const Context * context)504 void SemaphoreManager::reset(const Context *context)
505 {
506     // Note: this function is called when the last context in the share group is destroyed.  Thus
507     // there are no thread safety concerns.
508     mHandleAllocator.reset();
509     for (const auto &semaphore : UnsafeResourceMapIter(mSemaphores))
510     {
511         if (semaphore.second)
512         {
513             semaphore.second->release(context);
514         }
515     }
516     mSemaphores.clear();
517 }
518 
createSemaphore(rx::GLImplFactory * factory)519 SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
520 {
521     SemaphoreID handle   = SemaphoreID{mHandleAllocator.allocate()};
522     Semaphore *semaphore = new Semaphore(factory, handle);
523     semaphore->addRef();
524     mSemaphores.assign(handle, semaphore);
525     return handle;
526 }
527 
deleteSemaphore(const Context * context,SemaphoreID handle)528 void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle)
529 {
530     Semaphore *semaphore = nullptr;
531     if (!mSemaphores.erase(handle, &semaphore))
532     {
533         return;
534     }
535 
536     // Requires an explicit this-> because of C++ template rules.
537     this->mHandleAllocator.release(handle.value);
538 
539     if (semaphore)
540     {
541         semaphore->release(context);
542     }
543 }
544 
getSemaphore(SemaphoreID handle) const545 Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const
546 {
547     return mSemaphores.query(handle);
548 }
549 }  // namespace gl
550