1 //
2 // Copyright 2020 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/imaging/hgiGL/garbageCollector.h"
25 #include "pxr/imaging/hgiGL/hgi.h"
26
27 #include "pxr/base/arch/hints.h"
28 #include "pxr/base/tf/diagnostic.h"
29
30
31 PXR_NAMESPACE_OPEN_SCOPE
32
33 std::vector<HgiBufferHandleVector*>
34 HgiGLGarbageCollector::_bufferList;
35 std::vector<HgiTextureHandleVector*>
36 HgiGLGarbageCollector::_textureList;
37 std::vector<HgiSamplerHandleVector*>
38 HgiGLGarbageCollector::_samplerList;
39 std::vector<HgiShaderFunctionHandleVector*>
40 HgiGLGarbageCollector::_shaderFunctionList;
41 std::vector<HgiShaderProgramHandleVector*>
42 HgiGLGarbageCollector::_shaderProgramList;
43 std::vector<HgiResourceBindingsHandleVector*>
44 HgiGLGarbageCollector::_resourceBindingsList;
45 std::vector<HgiGraphicsPipelineHandleVector*>
46 HgiGLGarbageCollector::_graphicsPipelineList;
47 std::vector<HgiComputePipelineHandleVector*>
48 HgiGLGarbageCollector::_computePipelineList;
49
50
51 template<class T>
_EmptyTrash(std::vector<std::vector<HgiHandle<T>> * > * list)52 static void _EmptyTrash(std::vector<std::vector<HgiHandle<T>>*>* list) {
53 for (auto vec : *list) {
54 for (auto objectHandle : *vec) {
55 delete objectHandle.Get();
56 }
57 vec->clear();
58 vec->shrink_to_fit();
59 }
60 }
61
HgiGLGarbageCollector(HgiGL * hgi)62 HgiGLGarbageCollector::HgiGLGarbageCollector(HgiGL* hgi)
63 : _hgi(hgi)
64 , _isDestroying(false)
65 {
66 }
67
~HgiGLGarbageCollector()68 HgiGLGarbageCollector::~HgiGLGarbageCollector()
69 {
70 PerformGarbageCollection();
71 }
72
73 /* Multi threaded */
74 HgiBufferHandleVector*
GetBufferList()75 HgiGLGarbageCollector::GetBufferList()
76 {
77 return _GetThreadLocalStorageList(&_bufferList);
78 }
79
80 /* Multi threaded */
81 HgiTextureHandleVector*
GetTextureList()82 HgiGLGarbageCollector::GetTextureList()
83 {
84 return _GetThreadLocalStorageList(&_textureList);
85 }
86
87 /* Multi threaded */
88 HgiSamplerHandleVector*
GetSamplerList()89 HgiGLGarbageCollector::GetSamplerList()
90 {
91 return _GetThreadLocalStorageList(&_samplerList);
92 }
93
94 /* Multi threaded */
95 HgiShaderFunctionHandleVector*
GetShaderFunctionList()96 HgiGLGarbageCollector::GetShaderFunctionList()
97 {
98 return _GetThreadLocalStorageList(&_shaderFunctionList);
99 }
100
101 /* Multi threaded */
102 HgiShaderProgramHandleVector*
GetShaderProgramList()103 HgiGLGarbageCollector::GetShaderProgramList()
104 {
105 return _GetThreadLocalStorageList(&_shaderProgramList);
106 }
107
108 /* Multi threaded */
109 HgiResourceBindingsHandleVector*
GetResourceBindingsList()110 HgiGLGarbageCollector::GetResourceBindingsList()
111 {
112 return _GetThreadLocalStorageList(&_resourceBindingsList);
113 }
114
115 /* Multi threaded */
116 HgiGraphicsPipelineHandleVector*
GetGraphicsPipelineList()117 HgiGLGarbageCollector::GetGraphicsPipelineList()
118 {
119 return _GetThreadLocalStorageList(&_graphicsPipelineList);
120 }
121
122 /* Multi threaded */
123 HgiComputePipelineHandleVector*
GetComputePipelineList()124 HgiGLGarbageCollector::GetComputePipelineList()
125 {
126 return _GetThreadLocalStorageList(&_computePipelineList);
127 }
128
129 /* Single threaded */
130 void
PerformGarbageCollection()131 HgiGLGarbageCollector::PerformGarbageCollection()
132 {
133 _isDestroying = true;
134
135 _EmptyTrash(&_bufferList);
136 _EmptyTrash(&_textureList);
137 _EmptyTrash(&_samplerList);
138 _EmptyTrash(&_shaderFunctionList);
139 _EmptyTrash(&_shaderProgramList);
140 _EmptyTrash(&_resourceBindingsList);
141 _EmptyTrash(&_graphicsPipelineList);
142 _EmptyTrash(&_computePipelineList);
143
144 _isDestroying = false;
145 }
146
147 template<class T>
_GetThreadLocalStorageList(std::vector<T * > * collector)148 T* HgiGLGarbageCollector::_GetThreadLocalStorageList(std::vector<T*>* collector)
149 {
150 if (ARCH_UNLIKELY(_isDestroying)) {
151 TF_CODING_ERROR("Cannot destroy object during garbage collection ");
152 while(_isDestroying);
153 }
154
155 // Only lock and create a new garbage vector if we dont have one in TLS.
156 // Using TLS means this we store per type T, not per T and Hgi instance.
157 // So if you call garbage collect on one Hgi, it destroys objects across
158 // all Hgi's. This should be ok since we only call the destructor of the
159 // garbage object.
160 thread_local T* _tls = nullptr;
161 static std::mutex garbageMutex;
162
163 if (!_tls) {
164 _tls = new T();
165 std::lock_guard<std::mutex> guard(garbageMutex);
166 collector->push_back(_tls);
167 }
168 return _tls;
169 }
170
171
172 PXR_NAMESPACE_CLOSE_SCOPE
173