Hash :
df90bbc5
Author :
Date :
2024-07-12T18:04:53
Refactoring: move angle::HashMap and HashSet to own header Underlying abseil includes pull in a large set of headers Bug: angleproject:42266508 Change-Id: Icee47143a8a59bb0795a054b67c0aa4ddcfca4d4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5704137 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
//
// Copyright 2023 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// MemoryTracking.h:
// Defines the classes used for memory tracking in ANGLE.
//
#ifndef LIBANGLE_RENDERER_VULKAN_MEMORYTRACKING_H_
#define LIBANGLE_RENDERER_VULKAN_MEMORYTRACKING_H_
#include <array>
#include <atomic>
#include "common/SimpleMutex.h"
#include "common/angleutils.h"
#include "common/backtrace_utils.h"
#include "common/hash_containers.h"
#include "common/vulkan/vk_headers.h"
namespace rx
{
namespace vk
{
class Renderer;
// Used to designate memory allocation type for tracking purposes.
enum class MemoryAllocationType
{
Unspecified = 0,
ImageExternal = 1,
OffscreenSurfaceAttachmentImage = 2,
SwapchainMSAAImage = 3,
SwapchainDepthStencilImage = 4,
StagingImage = 5,
ImplicitMultisampledRenderToTextureImage = 6,
TextureImage = 7,
FontImage = 8,
RenderBufferStorageImage = 9,
Buffer = 10,
BufferExternal = 11,
InvalidEnum = 12,
EnumCount = InvalidEnum,
};
constexpr const char *kMemoryAllocationTypeMessage[] = {
"Unspecified",
"ImageExternal",
"OffscreenSurfaceAttachmentImage",
"SwapchainMSAAImage",
"SwapchainDepthStencilImage",
"StagingImage",
"ImplicitMultisampledRenderToTextureImage",
"TextureImage",
"FontImage",
"RenderBufferStorageImage",
"Buffer",
"BufferExternal",
"Invalid",
};
constexpr const uint32_t kMemoryAllocationTypeCount =
static_cast<uint32_t>(MemoryAllocationType::EnumCount);
// Used to select the severity for memory allocation logs.
enum class MemoryLogSeverity
{
INFO,
WARN,
};
// Used to store memory allocation information for tracking purposes.
struct MemoryAllocationInfo
{
MemoryAllocationInfo() = default;
uint64_t id;
MemoryAllocationType allocType;
uint32_t memoryHeapIndex;
void *handle;
VkDeviceSize size;
};
class MemoryAllocInfoMapKey
{
public:
MemoryAllocInfoMapKey() : handle(nullptr) {}
MemoryAllocInfoMapKey(void *handle) : handle(handle) {}
bool operator==(const MemoryAllocInfoMapKey &rhs) const
{
return reinterpret_cast<uint64_t>(handle) == reinterpret_cast<uint64_t>(rhs.handle);
}
size_t hash() const;
private:
void *handle;
};
// Process GPU memory reports
class MemoryReport final : angle::NonCopyable
{
public:
MemoryReport();
void processCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData, bool logCallback);
void logMemoryReportStats() const;
private:
struct MemorySizes
{
VkDeviceSize allocatedMemory;
VkDeviceSize allocatedMemoryMax;
VkDeviceSize importedMemory;
VkDeviceSize importedMemoryMax;
};
mutable angle::SimpleMutex mMemoryReportMutex;
VkDeviceSize mCurrentTotalAllocatedMemory;
VkDeviceSize mMaxTotalAllocatedMemory;
angle::HashMap<VkObjectType, MemorySizes> mSizesPerType;
VkDeviceSize mCurrentTotalImportedMemory;
VkDeviceSize mMaxTotalImportedMemory;
angle::HashMap<uint64_t, int> mUniqueIDCounts;
};
} // namespace vk
} // namespace rx
// Introduce std::hash for MemoryAllocInfoMapKey.
namespace std
{
template <>
struct hash<rx::vk::MemoryAllocInfoMapKey>
{
size_t operator()(const rx::vk::MemoryAllocInfoMapKey &key) const { return key.hash(); }
};
} // namespace std
namespace rx
{
// Memory tracker for allocations and deallocations, which is used in vk::Renderer.
class MemoryAllocationTracker : angle::NonCopyable
{
public:
MemoryAllocationTracker(vk::Renderer *renderer);
void initMemoryTrackers();
void onDeviceInit();
void onDestroy();
// Memory statistics are logged when handling a context error.
void logMemoryStatsOnError();
// Collect information regarding memory allocations and deallocations.
void onMemoryAllocImpl(vk::MemoryAllocationType allocType,
VkDeviceSize size,
uint32_t memoryTypeIndex,
void *handle);
void onMemoryDeallocImpl(vk::MemoryAllocationType allocType,
VkDeviceSize size,
uint32_t memoryTypeIndex,
void *handle);
// Memory allocation statistics functions.
VkDeviceSize getActiveMemoryAllocationsSize(uint32_t allocTypeIndex) const;
VkDeviceSize getActiveHeapMemoryAllocationsSize(uint32_t allocTypeIndex,
uint32_t heapIndex) const;
uint64_t getActiveMemoryAllocationsCount(uint32_t allocTypeIndex) const;
uint64_t getActiveHeapMemoryAllocationsCount(uint32_t allocTypeIndex, uint32_t heapIndex) const;
// Compare the expected flags with the flags of the allocated memory.
void compareExpectedFlagsWithAllocatedFlags(VkMemoryPropertyFlags requiredFlags,
VkMemoryPropertyFlags preferredFlags,
VkMemoryPropertyFlags allocatedFlags,
void *handle);
// Pending memory allocation information is used for logging in case of an unsuccessful
// allocation. It is cleared in onMemoryAlloc().
VkDeviceSize getPendingMemoryAllocationSize() const;
vk::MemoryAllocationType getPendingMemoryAllocationType() const;
uint32_t getPendingMemoryTypeIndex() const;
void resetPendingMemoryAlloc();
void setPendingMemoryAlloc(vk::MemoryAllocationType allocType,
VkDeviceSize size,
uint32_t memoryTypeIndex);
private:
// Pointer to parent renderer object.
vk::Renderer *const mRenderer;
// For tracking the overall memory allocation sizes and counts per memory allocation type.
std::array<std::atomic<VkDeviceSize>, vk::kMemoryAllocationTypeCount>
mActiveMemoryAllocationsSize;
std::array<std::atomic<uint64_t>, vk::kMemoryAllocationTypeCount> mActiveMemoryAllocationsCount;
// Memory allocation data per memory heap.
using PerHeapMemoryAllocationSizeArray =
std::array<std::atomic<VkDeviceSize>, VK_MAX_MEMORY_HEAPS>;
using PerHeapMemoryAllocationCountArray =
std::array<std::atomic<uint64_t>, VK_MAX_MEMORY_HEAPS>;
std::array<PerHeapMemoryAllocationSizeArray, vk::kMemoryAllocationTypeCount>
mActivePerHeapMemoryAllocationsSize;
std::array<PerHeapMemoryAllocationCountArray, vk::kMemoryAllocationTypeCount>
mActivePerHeapMemoryAllocationsCount;
// Pending memory allocation information is used for logging in case of an allocation error.
// It includes the size and type of the last attempted allocation, which are cleared after
// the allocation is successful.
std::atomic<VkDeviceSize> mPendingMemoryAllocationSize;
std::atomic<vk::MemoryAllocationType> mPendingMemoryAllocationType;
std::atomic<uint32_t> mPendingMemoryTypeIndex;
// Mutex is used to update the data when debug layers are enabled.
angle::SimpleMutex mMemoryAllocationMutex;
// Additional information regarding memory allocation with debug layers enabled, including
// allocation ID and a record of all active allocations.
uint64_t mMemoryAllocationID;
using MemoryAllocInfoMap = angle::HashMap<vk::MemoryAllocInfoMapKey, vk::MemoryAllocationInfo>;
std::unordered_map<angle::BacktraceInfo, MemoryAllocInfoMap> mMemoryAllocationRecord;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_MEMORYTRACKING_H_