xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/mtl_buffer_manager.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2022 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 // mtl_buffer_manager.h:
7 //    BufferManager manages buffers across all contexts for a single
8 //    device.
9 //
10 #ifndef LIBANGLE_RENDERER_METAL_MTL_BUFFER_MANAGER_H_
11 #define LIBANGLE_RENDERER_METAL_MTL_BUFFER_MANAGER_H_
12 
13 #include "common/FixedVector.h"
14 #include "libANGLE/renderer/metal/mtl_resources.h"
15 
16 #include <map>
17 #include <vector>
18 
19 namespace rx
20 {
21 class ContextMtl;
22 
23 namespace mtl
24 {
25 
26 // GL buffers are backed by Metal buffers. Which metal
27 // buffer is backing a particular GL buffer is fluid.
28 // The case being optimized is a loop of something like
29 //
30 //    for 1..4
31 //      glBufferSubData
32 //      glDrawXXX
33 //
34 // You can't update a buffer in the middle of a render pass
35 // in metal so instead we'd end up using multiple buffers.
36 //
37 // Simple case, the call to `glBufferSubData` updates the
38 // entire buffer. In this case we'd end up with each call
39 // to `glBufferSubData` getting a new buffer from this
40 // BufferManager and copying the new data to it. We'd
41 // end up submitting this renderpass
42 //
43 //    draw with buf1
44 //    draw with buf2
45 //    draw with buf3
46 //    draw with buf4
47 //
48 // The GL buffer now references buf4. And buf1, buf2, buf3 and
49 // buf0 (the buffer that was previously referenced by the GL buffer)
50 // are all added to the inuse-list
51 //
52 
53 // This macro enables showing the running totals of the various
54 // buckets of unused buffers.
55 // #define ANGLE_MTL_TRACK_BUFFER_MEM
56 
57 class BufferManager
58 {
59   public:
60     BufferManager();
61 
62     static constexpr size_t kMaxStagingBufferSize = 1024 * 1024;
63 #if TARGET_OS_OSX || TARGET_OS_MACCATALYST
64     static constexpr int kNumCachedStorageModes = 2;
65 #else
66     static constexpr int kNumCachedStorageModes = 1;
67 #endif
68     static constexpr size_t kContextSwitchesBetweenGC      = 120;
69     static constexpr size_t kCommandBufferCommitsBetweenGC = 5000;
70     static constexpr size_t kMinMemBasedGC                 = 1024 * 1024;
71     static constexpr size_t kMemAllocedBetweenGC           = 64 * 1024 * 1024;
72     angle::Result queueBlitCopyDataToBuffer(ContextMtl *contextMtl,
73                                             const void *srcPtr,
74                                             size_t sizeToCopy,
75                                             size_t offset,
76                                             mtl::BufferRef &dstMetalBuffer);
77 
78     angle::Result getBuffer(ContextMtl *contextMtl,
79                             MTLStorageMode storageMode,
80                             size_t size,
81                             mtl::BufferRef &bufferRef);
82     void returnBuffer(ContextMtl *contextMtl, mtl::BufferRef &bufferRef);
83 
84     void incrementNumContextSwitches();
85     void incrementNumCommandBufferCommits();
86 
87   private:
88     typedef std::vector<mtl::BufferRef> BufferList;
89     typedef std::multimap<size_t, mtl::BufferRef> BufferMap;
90     enum class GCReason
91     {
92         ContextSwitches,
93         CommandBufferCommits,
94         TotalMem
95     };
96 
97     void freeUnusedBuffers(ContextMtl *contextMtl);
98     void addBufferRefToFreeLists(mtl::BufferRef &bufferRef);
99     void collectGarbage(GCReason reason);
100 
101     BufferList mInUseBuffers;
102 
103     BufferMap mFreeBuffers[kNumCachedStorageModes];
104 
105     // For garbage collecting expired buffer shadow copies
106     size_t mContextSwitches              = 0;
107     size_t mContextSwitchesAtLastGC      = 0;
108     size_t mCommandBufferCommits         = 0;
109     size_t mCommandBufferCommitsAtLastGC = 0;
110     size_t mTotalMem                     = 0;
111     size_t mTotalMemAtLastGC             = 0;
112 
113 #ifdef ANGLE_MTL_TRACK_BUFFER_MEM
114     std::map<size_t, size_t> mAllocatedSizes;
115 #endif
116 };
117 
118 }  // namespace mtl
119 }  // namespace rx
120 
121 #endif /* LIBANGLE_RENDERER_METAL_MTL_BUFFER_MANAGER_H_ */
122