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