• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "memory/rs_memory_manager.h"
17 
18 #include <malloc.h>
19 #include "include/core/SkGraphics.h"
20 #include "rs_trace.h"
21 
22 #include "memory/rs_dfx_string.h"
23 #include "skia_adapter/rs_skia_memory_tracer.h"
24 #include "skia_adapter/skia_graphics.h"
25 #include "memory/rs_memory_graphic.h"
26 #include "include/gpu/GrDirectContext.h"
27 #include "src/gpu/GrDirectContextPriv.h"
28 
29 #include "common/rs_obj_abs_geometry.h"
30 #include "memory/rs_tag_tracker.h"
31 #ifdef NEW_RENDER_CONTEXT
32 #include "render_context/memory_handler.h"
33 #endif
34 #include "pipeline/rs_main_thread.h"
35 #include "pipeline/rs_surface_render_node.h"
36 #include "platform/common/rs_log.h"
37 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
38 
39 #ifdef USE_ROSEN_DRAWING
40 #include "image/gpu_context.h"
41 #endif
42 
43 #ifdef RS_ENABLE_VK
44 #include "pipeline/rs_vk_image_manager.h"
45 #include "platform/ohos/backend/rs_vulkan_context.h"
46 #endif
47 
48 namespace OHOS::Rosen {
49 namespace {
50 constexpr uint32_t MEMUNIT_RATE = 1024;
51 constexpr const char* MEM_RS_TYPE = "renderservice";
52 constexpr const char* MEM_CPU_TYPE = "cpu";
53 constexpr const char* MEM_GPU_TYPE = "gpu";
54 constexpr const char* MEM_JEMALLOC_TYPE = "jemalloc";
55 }
56 
57 #ifndef USE_ROSEN_DRAWING
DumpMemoryUsage(DfxString & log,const GrDirectContext * grContext,std::string & type)58 void MemoryManager::DumpMemoryUsage(DfxString& log, const GrDirectContext* grContext, std::string& type)
59 {
60     if (type.empty() || type == MEM_RS_TYPE) {
61         DumpRenderServiceMemory(log);
62     }
63     if (type.empty() || type == MEM_CPU_TYPE) {
64         DumpDrawingCpuMemory(log);
65     }
66     if (type.empty() || type == MEM_GPU_TYPE) {
67         DumpDrawingGpuMemory(log, grContext);
68     }
69     if (type.empty() || type == MEM_JEMALLOC_TYPE) {
70         std::string out;
71         DumpMallocStat(out);
72         log.AppendFormat("%s\n... detail dump at hilog\n", out.c_str());
73     }
74 }
75 #else
DumpMemoryUsage(DfxString & log,const Drawing::GPUContext * gpuContext,std::string & type)76 void MemoryManager::DumpMemoryUsage(DfxString& log, const Drawing::GPUContext* gpuContext, std::string& type)
77 {
78     if (type.empty() || type == MEM_RS_TYPE) {
79         DumpRenderServiceMemory(log);
80     }
81     if (type.empty() || type == MEM_CPU_TYPE) {
82         DumpDrawingCpuMemory(log);
83     }
84     if (type.empty() || type == MEM_GPU_TYPE) {
85         DumpDrawingGpuMemory(log, gpuContext);
86     }
87     if (type.empty() || type == MEM_JEMALLOC_TYPE) {
88         std::string out;
89         DumpMallocStat(out);
90         log.AppendFormat("%s\n... detail dump at hilog\n", out.c_str());
91     }
92 }
93 #endif // USE_ROSEN_DRAWING
94 
95 #ifndef USE_ROSEN_DRAWING
ReleaseAllGpuResource(GrDirectContext * grContext,GrGpuResourceTag & tag)96 void MemoryManager::ReleaseAllGpuResource(GrDirectContext* grContext, GrGpuResourceTag& tag)
97 {
98 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
99     if (!grContext) {
100         RS_LOGE("ReleaseGpuResByTag fail, grContext is nullptr");
101         return;
102     }
103     RS_TRACE_NAME_FMT("ReleaseAllGpuResource [Pid:%d Tid:%d Nid:%d Funcid:%d]",
104         tag.fPid, tag.fTid, tag.fWid, tag.fFid);
105     grContext->releaseByTag(tag);
106 #endif
107 }
108 #else
ReleaseAllGpuResource(Drawing::GPUContext * gpuContext,Drawing::GPUResourceTag & tag)109 void MemoryManager::ReleaseAllGpuResource(Drawing::GPUContext* gpuContext, Drawing::GPUResourceTag& tag)
110 {
111 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
112     if (!gpuContext) {
113         RS_LOGE("ReleaseGpuResByTag fail, gpuContext is nullptr");
114         return;
115     }
116     RS_TRACE_NAME_FMT("ReleaseAllGpuResource [Pid:%d Tid:%d Nid:%d Funcid:%d]",
117         tag.fPid, tag.fTid, tag.fWid, tag.fFid);
118     gpuContext->ReleaseByTag(tag);
119 #endif
120 }
121 #endif
122 
123 #ifndef USE_ROSEN_DRAWING
ReleaseAllGpuResource(GrDirectContext * grContext,pid_t pid)124 void MemoryManager::ReleaseAllGpuResource(GrDirectContext* grContext, pid_t pid)
125 {
126 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
127     GrGpuResourceTag tag(pid, 0, 0, 0);
128     ReleaseAllGpuResource(grContext, tag);
129 #endif
130 }
131 #else
ReleaseAllGpuResource(Drawing::GPUContext * gpuContext,pid_t pid)132 void MemoryManager::ReleaseAllGpuResource(Drawing::GPUContext* gpuContext, pid_t pid)
133 {
134 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
135     Drawing::GPUResourceTag tag(pid, 0, 0, 0);
136     ReleaseAllGpuResource(gpuContext, tag);
137 #endif
138 }
139 #endif
140 
141 #ifndef USE_ROSEN_DRAWING
ReleaseUnlockGpuResource(GrDirectContext * grContext,GrGpuResourceTag & tag)142 void MemoryManager::ReleaseUnlockGpuResource(GrDirectContext* grContext, GrGpuResourceTag& tag)
143 {
144 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
145     if (!grContext) {
146         RS_LOGE("ReleaseGpuResByTag fail, grContext is nullptr");
147         return;
148     }
149     RS_TRACE_NAME_FMT("ReleaseUnlockGpuResource [Pid:%d Tid:%d Nid:%d Funcid:%d]",
150         tag.fPid, tag.fTid, tag.fWid, tag.fFid);
151     grContext->purgeUnlockedResourcesByTag(false, tag);
152 #endif
153 }
154 #else
ReleaseUnlockGpuResource(Drawing::GPUContext * gpuContext,Drawing::GPUResourceTag & tag)155 void MemoryManager::ReleaseUnlockGpuResource(Drawing::GPUContext* gpuContext, Drawing::GPUResourceTag& tag)
156 {
157 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
158     if (!gpuContext) {
159         RS_LOGE("ReleaseGpuResByTag fail, gpuContext is nullptr");
160         return;
161     }
162     RS_TRACE_NAME_FMT("ReleaseUnlockGpuResource [Pid:%d Tid:%d Nid:%d Funcid:%d]",
163         tag.fPid, tag.fTid, tag.fWid, tag.fFid);
164     gpuContext->PurgeUnlockedResourcesByTag(false, tag);
165 #endif
166 }
167 #endif
168 
169 #ifndef USE_ROSEN_DRAWING
ReleaseUnlockGpuResource(GrDirectContext * grContext,NodeId surfaceNodeId)170 void MemoryManager::ReleaseUnlockGpuResource(GrDirectContext* grContext, NodeId surfaceNodeId)
171 {
172 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
173     GrGpuResourceTag tag(ExtractPid(surfaceNodeId), 0, 0, 0);
174     ReleaseUnlockGpuResource(grContext, tag); // clear gpu resource by pid
175 #endif
176 }
177 #else
ReleaseUnlockGpuResource(Drawing::GPUContext * grContext,NodeId surfaceNodeId)178 void MemoryManager::ReleaseUnlockGpuResource(Drawing::GPUContext* grContext, NodeId surfaceNodeId)
179 {
180 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
181     Drawing::GPUResourceTag tag(ExtractPid(surfaceNodeId), 0, 0, 0);
182     ReleaseUnlockGpuResource(grContext, tag);
183 #endif
184 }
185 #endif
186 
187 #ifndef USE_ROSEN_DRAWING
ReleaseUnlockGpuResource(GrDirectContext * grContext,pid_t pid)188 void MemoryManager::ReleaseUnlockGpuResource(GrDirectContext* grContext, pid_t pid)
189 {
190 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
191     GrGpuResourceTag tag(pid, 0, 0, 0);
192     ReleaseUnlockGpuResource(grContext, tag); // clear gpu resource by pid
193 #endif
194 }
195 #else
ReleaseUnlockGpuResource(Drawing::GPUContext * grContext,pid_t pid)196 void MemoryManager::ReleaseUnlockGpuResource(Drawing::GPUContext* grContext, pid_t pid)
197 {
198 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
199     Drawing::GPUResourceTag tag(pid, 0, 0, 0);
200     ReleaseUnlockGpuResource(grContext, tag); // clear gpu resource by pid
201 #endif
202 }
203 #endif
204 
205 #ifndef USE_ROSEN_DRAWING
ReleaseUnlockGpuResource(GrDirectContext * grContext,bool scratchResourcesOnly)206 void MemoryManager::ReleaseUnlockGpuResource(GrDirectContext* grContext, bool scratchResourcesOnly)
207 {
208 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
209     if (!grContext) {
210         RS_LOGE("ReleaseGpuResByTag fail, grContext is nullptr");
211         return;
212     }
213     RS_TRACE_NAME_FMT("ReleaseUnlockGpuResource scratchResourcesOnly:%d", scratchResourcesOnly);
214     grContext->purgeUnlockedResources(scratchResourcesOnly);
215 #endif
216 }
217 #else
ReleaseUnlockGpuResource(Drawing::GPUContext * gpuContext,bool scratchResourcesOnly)218 void MemoryManager::ReleaseUnlockGpuResource(Drawing::GPUContext* gpuContext, bool scratchResourcesOnly)
219 {
220 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
221     if (!gpuContext) {
222         RS_LOGE("ReleaseGpuResByTag fail, gpuContext is nullptr");
223         return;
224     }
225     RS_TRACE_NAME_FMT("ReleaseUnlockGpuResource scratchResourcesOnly:%d", scratchResourcesOnly);
226     gpuContext->PurgeUnlockedResources(scratchResourcesOnly);
227 #endif
228 }
229 #endif
230 
231 #ifndef USE_ROSEN_DRAWING
ReleaseUnlockAndSafeCacheGpuResource(GrDirectContext * grContext)232 void MemoryManager::ReleaseUnlockAndSafeCacheGpuResource(GrDirectContext* grContext)
233 {
234 #if defined (RS_ENABLE_GL) || defined(RS_ENABLE_VK)
235     if (!grContext) {
236         RS_LOGE("ReleaseUnlockAndSafeCacheGpuResource fail, grContext is nullptr");
237         return;
238     }
239     RS_TRACE_NAME_FMT("ReleaseUnlockAndSafeCacheGpuResource");
240     grContext->purgeUnlockAndSafeCacheGpuResources();
241 #endif
242 }
243 #else
ReleaseUnlockAndSafeCacheGpuResource(Drawing::GPUContext * gpuContext)244 void MemoryManager::ReleaseUnlockAndSafeCacheGpuResource(Drawing::GPUContext* gpuContext)
245 {
246 #if defined (RS_ENABLE_GL) || defined(RS_ENABLE_VK)
247     if (!gpuContext) {
248         RS_LOGE("ReleaseUnlockAndSafeCacheGpuResource fail, gpuContext is nullptr");
249         return;
250     }
251     RS_TRACE_NAME_FMT("ReleaseUnlockAndSafeCacheGpuResource");
252     gpuContext->PurgeUnlockAndSafeCacheGpuResources();
253 #endif
254 }
255 #endif
256 
257 #ifndef USE_ROSEN_DRAWING
GetAppGpuMemoryInMB(GrDirectContext * grContext)258 float MemoryManager::GetAppGpuMemoryInMB(GrDirectContext* grContext)
259 {
260     if (!grContext) {
261         return 0.f;
262     }
263 #if defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)
264     SkiaMemoryTracer trace("category", true);
265     grContext->dumpMemoryStatistics(&trace);
266     auto total = trace.GetGpuMemorySizeInMB();
267     float rsMemSize = 0.f;
268     for (uint32_t tagtype = RSTagTracker::TAG_SAVELAYER_DRAW_NODE; tagtype <= RSTagTracker::TAG_CAPTURE; tagtype++) {
269         GrGpuResourceTag resourceTag(0, 0, 0, tagtype);
270         SkiaMemoryTracer gpuTrace("category", true);
271         grContext->dumpMemoryStatisticsByTag(&gpuTrace, resourceTag);
272         rsMemSize += gpuTrace.GetGpuMemorySizeInMB();
273     }
274     return total - rsMemSize;
275 #else
276     return 0.f;
277 #endif
278 }
279 #else
GetAppGpuMemoryInMB(Drawing::GPUContext * gpuContext)280 float MemoryManager::GetAppGpuMemoryInMB(Drawing::GPUContext* gpuContext)
281 {
282     if (!gpuContext) {
283         return 0.f;
284     }
285 #if defined (RS_ENABLE_GL) || defined(RS_ENABLE_VK)
286     Drawing::TraceMemoryDump trace("category", true);
287     gpuContext->DumpMemoryStatistics(&trace);
288     auto total = trace.GetGpuMemorySizeInMB();
289     float rsMemSize = 0.f;
290     for (uint32_t tagtype = RSTagTracker::TAG_SAVELAYER_DRAW_NODE; tagtype <= RSTagTracker::TAG_CAPTURE; tagtype++) {
291         Drawing::GPUResourceTag resourceTag(0, 0, 0, tagtype);
292         Drawing::TraceMemoryDump gpuTrace("category", true);
293         gpuContext->DumpMemoryStatisticsByTag(&gpuTrace, resourceTag);
294         rsMemSize += gpuTrace.GetGpuMemorySizeInMB();
295     }
296     return total - rsMemSize;
297 #else
298     return 0.f;
299 #endif
300 }
301 #endif
302 
303 #ifndef USE_ROSEN_DRAWING
DumpPidMemory(DfxString & log,int pid,const GrDirectContext * grContext)304 void MemoryManager::DumpPidMemory(DfxString& log, int pid, const GrDirectContext* grContext)
305 {
306     //MemoryTrack::Instance().DumpMemoryStatistics(log, pid);
307     MemoryGraphic mem = CountPidMemory(pid, grContext);
308     log.AppendFormat("GPU Mem(MB):%f\n", mem.GetGpuMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
309     log.AppendFormat("CPU Mem(MB):%f\n", mem.GetCpuMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
310     log.AppendFormat("Total Mem(MB):%f\n", mem.GetTotalMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
311 }
312 #else
DumpPidMemory(DfxString & log,int pid,const Drawing::GPUContext * gpuContext)313 void MemoryManager::DumpPidMemory(DfxString& log, int pid, const Drawing::GPUContext* gpuContext)
314 {
315     MemoryGraphic mem = CountPidMemory(pid, gpuContext);
316     log.AppendFormat("GPU Mem(MB):%f\n", mem.GetGpuMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
317     log.AppendFormat("CPU Mem(KB):%f\n", mem.GetCpuMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
318     log.AppendFormat("Total Mem(MB):%f\n", mem.GetTotalMemorySize() / (MEMUNIT_RATE * MEMUNIT_RATE));
319 }
320 #endif
321 
322 #ifndef USE_ROSEN_DRAWING
CountSubMemory(int pid,const GrDirectContext * grContext)323 MemoryGraphic MemoryManager::CountSubMemory(int pid, const GrDirectContext* grContext)
324 {
325     MemoryGraphic memoryGraphic;
326     auto subThreadManager = RSSubThreadManager::Instance();
327     std::vector<MemoryGraphic> subMems = subThreadManager->CountSubMem(pid);
328     for (const auto& mem : subMems) {
329         memoryGraphic += mem;
330     }
331     return memoryGraphic;
332 }
333 #else
CountSubMemory(int pid,const Drawing::GPUContext * gpuContext)334 MemoryGraphic MemoryManager::CountSubMemory(int pid, const Drawing::GPUContext* gpuContext)
335 {
336     MemoryGraphic memoryGraphic;
337     auto subThreadManager = RSSubThreadManager::Instance();
338     std::vector<MemoryGraphic> subMems = subThreadManager->CountSubMem(pid);
339     for (const auto& mem : subMems) {
340         memoryGraphic += mem;
341     }
342     return memoryGraphic;
343 }
344 #endif
345 
346 #ifndef USE_ROSEN_DRAWING
CountPidMemory(int pid,const GrDirectContext * grContext)347 MemoryGraphic MemoryManager::CountPidMemory(int pid, const GrDirectContext* grContext)
348 {
349     MemoryGraphic totalMemGraphic;
350 
351     // Count mem of RS
352     totalMemGraphic.SetPid(pid);
353 
354 #if defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)
355     // Count mem of Skia GPU
356     if (grContext) {
357         SkiaMemoryTracer gpuTracer("category", true);
358         GrGpuResourceTag tag(pid, 0, 0, 0);
359         grContext->dumpMemoryStatisticsByTag(&gpuTracer, tag);
360         float gpuMem = gpuTracer.GetGLMemorySize();
361         totalMemGraphic.IncreaseGpuMemory(gpuMem);
362     }
363 #endif
364 
365     return totalMemGraphic;
366 }
367 #else
CountPidMemory(int pid,const Drawing::GPUContext * gpuContext)368 MemoryGraphic MemoryManager::CountPidMemory(int pid, const Drawing::GPUContext* gpuContext)
369 {
370     MemoryGraphic totalMemGraphic;
371 
372     // Count mem of RS
373     totalMemGraphic.SetPid(pid);
374 
375 #if defined (RS_ENABLE_GL) || defined(RS_ENABLE_VK)
376     // Count mem of Skia GPU
377     if (gpuContext) {
378         Drawing::TraceMemoryDump gpuTracer("category", true);
379         Drawing::GPUResourceTag tag(pid, 0, 0, 0);
380         gpuContext->DumpMemoryStatisticsByTag(&gpuTracer, tag);
381         float gpuMem = gpuTracer.GetGLMemorySize();
382         totalMemGraphic.IncreaseGpuMemory(gpuMem);
383     }
384 #endif
385 
386     return totalMemGraphic;
387 }
388 #endif
389 
390 #ifndef USE_ROSEN_DRAWING
CountMemory(std::vector<pid_t> pids,const GrDirectContext * grContext,std::vector<MemoryGraphic> & mems)391 void MemoryManager::CountMemory(std::vector<pid_t> pids, const GrDirectContext* grContext,
392     std::vector<MemoryGraphic>& mems)
393 {
394     auto countMem = [&grContext, &mems] (pid_t pid) {
395         mems.emplace_back(CountPidMemory(pid, grContext));
396     };
397     // Count mem of Skia GPU
398     std::for_each(pids.begin(), pids.end(), countMem);
399 }
400 #else
CountMemory(std::vector<pid_t> pids,const Drawing::GPUContext * gpuContext,std::vector<MemoryGraphic> & mems)401 void MemoryManager::CountMemory(
402     std::vector<pid_t> pids, const Drawing::GPUContext* gpuContext, std::vector<MemoryGraphic>& mems)
403 {
404     auto countMem = [&gpuContext, &mems] (pid_t pid) {
405         mems.emplace_back(CountPidMemory(pid, gpuContext));
406     };
407     // Count mem of Skia GPU
408     std::for_each(pids.begin(), pids.end(), countMem);
409 }
410 #endif
411 
FindGeoById(uint64_t nodeId)412 static std::tuple<uint64_t, std::string, RectI> FindGeoById(uint64_t nodeId)
413 {
414     const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
415     auto node = nodeMap.GetRenderNode<RSRenderNode>(nodeId);
416     uint64_t windowId = nodeId;
417     std::string windowName = "NONE";
418     RectI nodeFrameRect;
419     if (!node) {
420         return { windowId, windowName, nodeFrameRect };
421     }
422     nodeFrameRect =
423         (node->GetRenderProperties().GetBoundsGeometry())->GetAbsRect();
424     // Obtain the window according to childId
425     auto parent = node->GetParent().lock();
426     while (parent) {
427         if (parent->IsInstanceOf<RSSurfaceRenderNode>()) {
428             const auto& surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(parent);
429             windowName = surfaceNode->GetName();
430             windowId = surfaceNode->GetId();
431             break;
432         }
433         parent = parent->GetParent().lock();
434     }
435     return { windowId, windowName, nodeFrameRect };
436 }
437 
DumpRenderServiceMemory(DfxString & log)438 void MemoryManager::DumpRenderServiceMemory(DfxString& log)
439 {
440     log.AppendFormat("\n----------\nRenderService caches:\n");
441     MemoryTrack::Instance().DumpMemoryStatistics(log, FindGeoById);
442 }
443 
DumpDrawingCpuMemory(DfxString & log)444 void MemoryManager::DumpDrawingCpuMemory(DfxString& log)
445 {
446 #ifndef USE_ROSEN_DRAWING
447     // CPU
448     log.AppendFormat("\n----------\nSkia CPU caches:\n");
449     log.AppendFormat("Font Cache (CPU):\n");
450     log.AppendFormat("  Size: %.2f kB \n", SkGraphics::GetFontCacheUsed() / MEMUNIT_RATE);
451     log.AppendFormat("  Glyph Count: %d \n", SkGraphics::GetFontCacheCountUsed());
452 
453     std::vector<ResourcePair> cpuResourceMap = {
454         { "skia/sk_resource_cache/bitmap_", "Bitmaps" },
455         { "skia/sk_resource_cache/rrect-blur_", "Masks" },
456         { "skia/sk_resource_cache/rects-blur_", "Masks" },
457         { "skia/sk_resource_cache/tessellated", "Shadows" },
458         { "skia/sk_resource_cache/yuv-planes_", "YUVPlanes" },
459         { "skia/sk_resource_cache/budget_glyph_count", "Bitmaps" },
460     };
461     SkiaMemoryTracer cpuTracer(cpuResourceMap, true);
462     SkGraphics::DumpMemoryStatistics(&cpuTracer);
463     log.AppendFormat("CPU Cachesxx:\n");
464     cpuTracer.LogOutput(log);
465     log.AppendFormat("Total CPU memory usage:\n");
466     cpuTracer.LogTotals(log);
467 
468     // cache limit
469     size_t cacheLimit = SkGraphics::GetResourceCacheTotalByteLimit();
470     size_t fontCacheLimit = SkGraphics::GetFontCacheLimit();
471     log.AppendFormat("\ncpu cache limit = %zu ( fontcache = %zu ):\n", cacheLimit, fontCacheLimit);
472 #else
473     // CPU
474     log.AppendFormat("\n----------\nSkia CPU caches:\n");
475     log.AppendFormat("Font Cache (CPU):\n");
476     log.AppendFormat("  Size: %.2f kB \n", Drawing::SkiaGraphics::GetFontCacheUsed() / MEMUNIT_RATE);
477     log.AppendFormat("  Glyph Count: %d \n", Drawing::SkiaGraphics::GetFontCacheCountUsed());
478 
479     std::vector<ResourcePair> cpuResourceMap = {
480         { "skia/sk_resource_cache/bitmap_", "Bitmaps" },
481         { "skia/sk_resource_cache/rrect-blur_", "Masks" },
482         { "skia/sk_resource_cache/rects-blur_", "Masks" },
483         { "skia/sk_resource_cache/tessellated", "Shadows" },
484         { "skia/sk_resource_cache/yuv-planes_", "YUVPlanes" },
485         { "skia/sk_resource_cache/budget_glyph_count", "Bitmaps" },
486     };
487     SkiaMemoryTracer cpuTracer(cpuResourceMap, true);
488     Drawing::SkiaGraphics::DumpMemoryStatistics(&cpuTracer);
489     log.AppendFormat("CPU Cachesxx:\n");
490     cpuTracer.LogOutput(log);
491     log.AppendFormat("Total CPU memory usage:\n");
492     cpuTracer.LogTotals(log);
493 
494     // cache limit
495     size_t cacheLimit = Drawing::SkiaGraphics::GetResourceCacheTotalByteLimit();
496     size_t fontCacheLimit = Drawing::SkiaGraphics::GetFontCacheLimit();
497     log.AppendFormat("\ncpu cache limit = %zu ( fontcache = %zu ):\n", cacheLimit, fontCacheLimit);
498 #endif
499 }
500 
501 #ifndef USE_ROSEN_DRAWING
DumpGpuCache(DfxString & log,const GrDirectContext * grContext,GrGpuResourceTag * tag,std::string & name)502 void MemoryManager::DumpGpuCache(
503     DfxString& log, const GrDirectContext* grContext, GrGpuResourceTag* tag, std::string& name)
504 {
505     if (!grContext) {
506         log.AppendFormat("grContext is nullptr.\n");
507         return;
508     }
509     /////////////////////////////GPU/////////////////////////
510 #if defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)
511     log.AppendFormat("\n---------------\nSkia GPU Caches:%s\n", name.c_str());
512     SkiaMemoryTracer gpuTracer("category", true);
513     if (tag) {
514         grContext->dumpMemoryStatisticsByTag(&gpuTracer, *tag);
515     } else {
516         grContext->dumpMemoryStatistics(&gpuTracer);
517     }
518     gpuTracer.LogOutput(log);
519     log.AppendFormat("Total GPU memory usage:\n");
520     gpuTracer.LogTotals(log);
521 #endif
522 }
523 #else
DumpGpuCache(DfxString & log,const Drawing::GPUContext * gpuContext,Drawing::GPUResourceTag * tag,std::string & name)524 void MemoryManager::DumpGpuCache(
525     DfxString& log, const Drawing::GPUContext* gpuContext, Drawing::GPUResourceTag* tag, std::string& name)
526 {
527     if (!gpuContext) {
528         log.AppendFormat("gpuContext is nullptr.\n");
529         return;
530     }
531     /* GPU */
532 #if defined (RS_ENABLE_GL) || defined(RS_ENABLE_VK)
533     log.AppendFormat("\n---------------\nSkia GPU Caches:%s\n", name.c_str());
534     Drawing::TraceMemoryDump gpuTracer("category", true);
535     if (tag) {
536         gpuContext->DumpMemoryStatisticsByTag(&gpuTracer, *tag);
537     } else {
538         gpuContext->DumpMemoryStatistics(&gpuTracer);
539     }
540     gpuTracer.LogOutput(log);
541     log.AppendFormat("Total GPU memory usage:\n");
542     gpuTracer.LogTotals(log);
543 #endif
544 }
545 #endif
546 
547 #ifndef USE_ROSEN_DRAWING
DumpAllGpuInfo(DfxString & log,const GrDirectContext * grContext)548 void MemoryManager::DumpAllGpuInfo(DfxString& log, const GrDirectContext* grContext)
549 {
550     if (!grContext) {
551         log.AppendFormat("No valid gpu cache instance.\n");
552         return;
553     }
554 #if defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)
555     const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
556     nodeMap.TraverseSurfaceNodes([&log, &grContext](const std::shared_ptr<RSSurfaceRenderNode> node) {
557         GrGpuResourceTag tag(ExtractPid(node->GetId()), 0, node->GetId(), 0);
558         std::string name = node->GetName() + " " + std::to_string(node->GetId());
559         DumpGpuCache(log, grContext, &tag, name);
560     });
561 #endif
562 }
563 #else
DumpAllGpuInfo(DfxString & log,const Drawing::GPUContext * gpuContext)564 void MemoryManager::DumpAllGpuInfo(DfxString& log, const Drawing::GPUContext* gpuContext)
565 {
566     if (!gpuContext) {
567         log.AppendFormat("No valid gpu cache instance.\n");
568         return;
569     }
570 #if defined (RS_ENABLE_GL) || defined(RS_ENABLE_VK)
571     const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
572     nodeMap.TraverseSurfaceNodes([&log, &gpuContext](const std::shared_ptr<RSSurfaceRenderNode> node) {
573         Drawing::GPUResourceTag tag(ExtractPid(node->GetId()), 0, node->GetId(), 0);
574         std::string name = node->GetName() + " " + std::to_string(node->GetId());
575         DumpGpuCache(log, gpuContext, &tag, name);
576     });
577 #endif
578 }
579 #endif
580 
581 #ifndef USE_ROSEN_DRAWING
DumpDrawingGpuMemory(DfxString & log,const GrDirectContext * grContext)582 void MemoryManager::DumpDrawingGpuMemory(DfxString& log, const GrDirectContext* grContext)
583 {
584     if (!grContext) {
585         log.AppendFormat("No valid gpu cache instance.\n");
586         return;
587     }
588     /////////////////////////////GPU/////////////////////////
589 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
590     std::string gpuInfo;
591     // total
592     DumpGpuCache(log, grContext, nullptr, gpuInfo);
593     // Get memory of window by tag
594     DumpAllGpuInfo(log, grContext);
595     for (uint32_t tagtype = RSTagTracker::TAG_SAVELAYER_DRAW_NODE; tagtype <= RSTagTracker::TAG_CAPTURE; tagtype++) {
596         GrGpuResourceTag tag(0, 0, 0, tagtype);
597         std::string tagType = RSTagTracker::TagType2String(static_cast<RSTagTracker::TAGTYPE>(tagtype));
598         DumpGpuCache(log, grContext, &tag, tagType);
599     }
600     // cache limit
601     size_t cacheLimit = 0;
602     size_t cacheUsed = 0;
603     grContext->getResourceCacheLimits(nullptr, &cacheLimit);
604     grContext->getResourceCacheUsage(nullptr, &cacheUsed);
605     log.AppendFormat("\ngpu limit = %zu ( used = %zu ):\n", cacheLimit, cacheUsed);
606 
607     //////////////////////////ShaderCache///////////////////
608     log.AppendFormat("\n---------------\nShader Caches:\n");
609 #ifdef NEW_RENDER_CONTEXT
610     log.AppendFormat(MemoryHandler::QuerryShader().c_str());
611 #else
612     std::shared_ptr<RenderContext> rendercontext = std::make_shared<RenderContext>();
613     log.AppendFormat(rendercontext->GetShaderCacheSize().c_str());
614 #endif
615     // gpu stat
616     log.AppendFormat("\n---------------\ndumpGpuStats:\n");
617     SkString stat;
618     grContext->priv().dumpGpuStats(&stat);
619 
620     log.AppendFormat("%s\n", stat.c_str());
621 #endif
622 }
623 #else
DumpDrawingGpuMemory(DfxString & log,const Drawing::GPUContext * gpuContext)624 void MemoryManager::DumpDrawingGpuMemory(DfxString& log, const Drawing::GPUContext* gpuContext)
625 {
626     if (!gpuContext) {
627         log.AppendFormat("No valid gpu cache instance.\n");
628         return;
629     }
630     /* GPU */
631 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
632     std::string gpuInfo;
633     // total
634     DumpGpuCache(log, gpuContext, nullptr, gpuInfo);
635     // Get memory of window by tag
636     DumpAllGpuInfo(log, gpuContext);
637     for (uint32_t tagtype = RSTagTracker::TAG_SAVELAYER_DRAW_NODE; tagtype <= RSTagTracker::TAG_CAPTURE; tagtype++) {
638         Drawing::GPUResourceTag tag(0, 0, 0, tagtype);
639         std::string tagType = RSTagTracker::TagType2String(static_cast<RSTagTracker::TAGTYPE>(tagtype));
640         DumpGpuCache(log, gpuContext, &tag, tagType);
641     }
642     // cache limit
643     size_t cacheLimit = 0;
644     size_t cacheUsed = 0;
645     gpuContext->GetResourceCacheLimits(nullptr, &cacheLimit);
646     gpuContext->GetResourceCacheUsage(nullptr, &cacheUsed);
647     log.AppendFormat("\ngpu limit = %zu ( used = %zu ):\n", cacheLimit, cacheUsed);
648 
649     /* ShaderCache */
650     log.AppendFormat("\n---------------\nShader Caches:\n");
651 #ifdef NEW_RENDER_CONTEXT
652     log.AppendFormat(MemoryHandler::QuerryShader().c_str());
653 #else
654     std::shared_ptr<RenderContext> rendercontext = std::make_shared<RenderContext>();
655     log.AppendFormat(rendercontext->GetShaderCacheSize().c_str());
656 #endif
657     // gpu stat
658     log.AppendFormat("\n---------------\ndumpGpuStats:\n");
659     std::string stat;
660     gpuContext->DumpGpuStats(stat);
661 
662     log.AppendFormat("%s\n", stat.c_str());
663 #endif
664 }
665 #endif // USE_ROSEN_DRAWING
666 
DumpMallocStat(std::string & log)667 void MemoryManager::DumpMallocStat(std::string& log)
668 {
669     malloc_stats_print(
670         [](void* fp, const char* str) {
671             if (!fp) {
672                 RS_LOGE("DumpMallocStat fp is nullptr");
673                 return;
674             }
675             std::string* sp = static_cast<std::string*>(fp);
676             if (str) {
677                 // cause log only support 2096 len. we need to only output critical log
678                 // and only put total log in RSLOG
679                 // get allocated string
680                 if (strncmp(str, "Allocated", strlen("Allocated")) == 0) {
681                     sp->append(str);
682                 }
683                 RS_LOGW("[mallocstat]:%{public}s", str);
684             }
685         },
686         &log, nullptr);
687 }
688 } // namespace OHOS::Rosen