1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef GPU_CONTEXT_H
17 #define GPU_CONTEXT_H
18 #include <functional>
19 #include <set>
20 
21 #include "trace_memory_dump.h"
22 
23 #include "impl_interface/gpu_context_impl.h"
24 #include "utils/data.h"
25 #include "utils/drawing_macros.h"
26 
27 typedef void* EGLContext;
28 namespace OHOS {
29 namespace Rosen {
30 namespace Drawing {
31 enum class PathRenderers : uint32_t {
32     NONE              = 0,
33     DASHLINE          = 1 << 0,
34     STENCILANDCOVER   = 1 << 1,
35     COVERAGECOUNTING  = 1 << 2,
36     AAHAIRLINE        = 1 << 3,
37     AACONVEX          = 1 << 4,
38     AALINEARIZING     = 1 << 5,
39     SMALL             = 1 << 6,
40     TESSELLATING      = 1 << 7,
41 
42     ALL               = (TESSELLATING | (TESSELLATING - 1)),
43     DEFAULT           = ALL & ~COVERAGECOUNTING
44 };
45 
46 struct GPUResourceTag {
GPUResourceTagOHOS::Rosen::Drawing::PathRenderers::GPUResourceTag47     GPUResourceTag()
48         : fPid(0), fTid(0), fWid(0), fFid(0) {}
GPUResourceTagOHOS::Rosen::Drawing::PathRenderers::GPUResourceTag49     GPUResourceTag(uint32_t pid, uint32_t tid, uint32_t wid, uint32_t fid, const std::string& name)
50         : fPid(pid), fTid(tid), fWid(wid), fFid(fid), fName(name) {}
51     uint32_t fPid;
52     uint32_t fTid;
53     uint32_t fWid;
54     uint32_t fFid;
55     std::string fName;
56 };
57 
58 /**
59  * @brief Option to create a GPUContext. Currently only supports setting persistent cache,
60  * other options may be expanded in the future
61  */
62 class DRAWING_API GPUContextOptions {
63 public:
64     /**
65      * @brief Cache compiled shaders for use between sessions.
66      */
67     class PersistentCache {
68     public:
69         PersistentCache() = default;
70         virtual ~PersistentCache() = default;
71 
72         /**
73          * @brief Returns the data for the key if it exists in the cache.
74          */
75         virtual std::shared_ptr<Data> Load(const Data& key) = 0;
76 
77         /**
78          * @brief Stores the data and key.
79          */
80         virtual void Store(const Data& key, const Data& data) = 0;
81     };
82 
83     /**
84      * @brief Gets persistent cache object.
85      */
86     PersistentCache* GetPersistentCache() const;
87 
88     /**
89      * @brief Sets persistent cache object.
90      * @param persistentCache A pointer to persistent cache object.
91      */
92     void SetPersistentCache(PersistentCache* persistentCache);
93 
94     void SetAllowPathMaskCaching(bool allowPathMaskCaching);
95     bool GetAllowPathMaskCaching() const;
96 
97 private:
98     PersistentCache* persistentCache_ = nullptr;
99     bool allowPathMaskCaching_ = true;
100 };
101 
102 class DRAWING_API GPUContext {
103 public:
104     GPUContext();
~GPUContext()105     ~GPUContext() {}
106 
107     /**
108      * @brief           Creates a GL GPUContext for a backend context.
109      * @param options   Option to create a GL GPUContext.
110      */
111     bool BuildFromGL(const GPUContextOptions& options);
112 
113 #ifdef RS_ENABLE_VK
114     bool BuildFromVK(const GrVkBackendContext& context);
115 
116     /**
117      * @brief           Creates a VK GPUContext for a backend context.
118      * @param context   An existed VK Context used to create a VK GPUContext.
119      * @param options   Option to create a VK GPUContext.
120      */
121     bool BuildFromVK(const GrVkBackendContext& context, const GPUContextOptions& options);
122 #endif
123 
124     /**
125      * @brief   Call to ensure all drawing to the context has been flushed to underlying 3D API specific objects.
126      */
127     void Flush();
128 
129     /**
130      * @brief   Call to ensure all drawing to the context has been submitted to underlying 3D API.
131      */
132     void Submit();
133 
134     /**
135      * @brief           Call to ensure all drawing to the context has been flushed and submitted to underlying 3D API.
136      * @param syncCpu   Whether to sync CPU or not.
137      */
138     void FlushAndSubmit(bool syncCpu = false);
139 
140     /**
141      * @brief             Purge GPU resources that haven't been used in the past 'msNotUsed' milliseconds
142                           or are otherwise marked for deletion.
143      * @param msNotUsed   Only unlocked resources not used in these last milliseconds will be cleaned up.
144      */
145     void PerformDeferredCleanup(std::chrono::milliseconds msNotUsed);
146 
147     /**
148      * @brief                   Gets the current GPU resource cache limits.
149      * @param maxResource       If non-null, returns maximum number of resources that can be held in the cache.
150      * @param maxResourceBytes  If non-null, returns maximum number of bytes of video memory
151                                 that can be held in the cache.
152      */
153     void GetResourceCacheLimits(int* maxResource, size_t* maxResourceBytes) const;
154 
155     /**
156      * @brief                   Specify the GPU resource cache limits.
157      * @param maxResource       The maximum number of resources that can be held in the cache.
158      * @param maxResourceBytes  The maximum number of bytes of video memory that can be held in the cache.
159      */
160     void SetResourceCacheLimits(int maxResource, size_t maxResourceBytes);
161 
162     /**
163      * @brief                   Gets the current GPU resource cache usage.
164      * @param resourceCount     If non-null, returns the number of resources that are held in the cache.
165      * @param resourceBytes     If non-null, returns the total number of bytes of video memory held in the cache.
166      */
167     void GetResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const;
168 
169     /**
170      * @brief                   Free GPU created by the contetx.
171      */
172     void FreeGpuResources();
173 
174     /**
175      * @brief                   Dump GPU stats.
176      * @param out               Dump GPU stat string.
177      */
178     void DumpGpuStats(std::string& out) const;
179 
180     /**
181      * @brief                   After returning it will assume that the underlying context may no longer be valid.
182      */
183     void ReleaseResourcesAndAbandonContext();
184 
185     /**
186      * @brief                         Purge unlocked resources from the cache until
187      *                                the provided byte count has been reached or we have purged all unlocked resources.
188      * @param scratchResourcesOnly    Whether to scratch the resources only or not.
189      */
190     void PurgeUnlockedResources(bool scratchResourcesOnly);
191 
192     /**
193      * @brief                         Purge unlocked resources by tag from the cache until
194      *                                the provided byte count has been reached or we have purged all unlocked resources.
195      * @param scratchResourcesOnly    Whether to scratch the resources only or not.
196      * @param tag                     GPU resource tag used to purge unlocked resources.
197      */
198     void PurgeUnlockedResourcesByTag(bool scratchResourcesOnly, const GPUResourceTag &tag);
199 
200     /**
201      * @brief                         Purge unlocked resources by pid from the cache until
202      *                                the provided byte count has been reached or we have purged all unlocked resources.
203      * @param scratchResourcesOnly    Whether to scratch the resources only or not.
204      * @param exitedPidSet            GPU resource exitedPidSet used to purge unlocked resources.
205      */
206     void PurgeUnlockedResourcesByPid(bool scratchResourcesOnly, const std::set<pid_t>& exitedPidSet);
207 
208     /**
209      * @brief                       Purge unlocked resources in every frame
210      * @param scratchResourcesOnly  Whether to scratch the resources only or not.
211      * @param exitedPidSet          GPU resource of exited PidSet used to purge unlocked resources.
212      * @param protectedPidSet       GPU resource of protectedPidSet will not be purged.
213      */
214     void PurgeCacheBetweenFrames(bool scratchResourcesOnly, const std::set<pid_t>& exitedPidSet,
215         const std::set<pid_t>& protectedPidSet);
216 
217     /**
218      * @brief                   Purge unlocked resources from the safe cache until
219      *                          the provided byte count has been reached or we have purged all unlocked resources.
220      */
221     void PurgeUnlockAndSafeCacheGpuResources();
222 
223     /**
224      * @brief                   Releases GPUResource objects and removes them from the cache by tag.
225      * @param tag               GPU resource tag used to release.
226      */
227     void ReleaseByTag(const GPUResourceTag &tag);
228 
229     /**
230      * @brief                   Enumerates all cached GPU resources and dumps their memory to traceMemoryDump.
231      * @param traceMemoryDump   A trace to memory dump.
232      * @param tag               GPU resource tag used to dump memory statistics.
233      */
234     void DumpMemoryStatisticsByTag(TraceMemoryDump* traceMemoryDump, GPUResourceTag &tag) const;
235 
236     /**
237      * @brief                   Enumerates all cached GPU resources and dumps their memory to traceMemoryDump.
238      * @param traceMemoryDump   A trace to memory dump.
239      */
240     void DumpMemoryStatistics(TraceMemoryDump* traceMemoryDump) const;
241 
242     /**
243      * @brief                   Reset GPU contect cache.
244      */
245     void ResetContext();
246 
247     /**
248      * @brief                   Set current resource tag for gpu cache recycle.
249      * @param tag               GPU resource tag used to set current GPU resource tag.
250      */
251     void SetCurrentGpuResourceTag(const GPUResourceTag &tag);
252 
253     /**
254      * @brief                   Get updated memory map.
255      * @param out               Updated memory map.
256      */
257     void GetUpdatedMemoryMap(std::unordered_map<pid_t, size_t> &out);
258 
259     /**
260      * @brief                   Init gpu memory limit.
261      * @param callback          Memory overflow calllback.
262      * @param size              Memory size limit.
263      */
264     void InitGpuMemoryLimit(MemoryOverflowCalllback callback, uint64_t size);
265 
266 #ifdef RS_ENABLE_VK
267     /**
268      * @brief                   Store vulkan pipeline cache
269      */
270     void StoreVkPipelineCacheData();
271 #endif
272 
273     void BeginFrame();
274 
275     void EndFrame();
276 
277     void SetGpuCacheSuppressWindowSwitch(bool enabled);
278 
279     void SetGpuMemoryAsyncReclaimerSwitch(bool enabled);
280 
281     void FlushGpuMemoryInWaitQueue();
282 
283     void SuppressGpuCacheBelowCertainRatio(const std::function<bool(void)>& nextFrameHasArrived);
284 
285     /**
286      * @brief       Get the adaptation layer instance, called in the adaptation layer.
287      * @param T     The name of Impl class.
288      * @return      Adaptation Layer instance.
289      */
290     template<typename T>
GetImpl() const291     T* GetImpl() const
292     {
293         return impl_->DowncastingTo<T>();
294     }
295 
296     void RegisterPostFunc(const std::function<void(const std::function<void()>& task)>& func);
297 
298     /**
299      * @brief                   Defragment or clear Vma Cache if needed
300      */
301     void VmaDefragment();
302 private:
303     std::shared_ptr<GPUContextImpl> impl_;
304 };
305 } // namespace Drawing
306 } // namespace Rosen
307 } // namespace OHOS
308 
309 #endif // !GPU_CONTEXT_H
310