//
// 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.cpp:
//    Implements the class methods in MemoryTracking.h.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/renderer/vulkan/MemoryTracking.h"

#include "common/debug.h"
#include "libANGLE/renderer/vulkan/vk_renderer.h"

// Consts
namespace
{
// This flag is used for memory allocation tracking using allocation size counters.
constexpr bool kTrackMemoryAllocationSizes = true;
#if defined(ANGLE_ENABLE_MEMORY_ALLOC_LOGGING)
// Flag used for logging memory allocations and deallocations.
constexpr bool kTrackMemoryAllocationDebug = true;
static_assert(kTrackMemoryAllocationSizes,
              "kTrackMemoryAllocationSizes must be enabled to use kTrackMemoryAllocationDebug.");
#else
// Only the allocation size counters are used (if enabled).
constexpr bool kTrackMemoryAllocationDebug = false;
#endif
}  // namespace

namespace rx
{

namespace
{
// Output memory log stream based on level of severity.
void OutputMemoryLogStream(std::stringstream &outStream, vk::MemoryLogSeverity severity)
{
    if (!kTrackMemoryAllocationSizes)
    {
        return;
    }

    switch (severity)
    {
        case vk::MemoryLogSeverity::INFO:
            INFO() << outStream.str();
            break;
        case vk::MemoryLogSeverity::WARN:
            WARN() << outStream.str();
            break;
        default:
            UNREACHABLE();
            break;
    }
}

// Check for currently allocated memory. It is used at the end of the renderer object and when
// there is an allocation error (from ANGLE_VK_TRY()).
void CheckForCurrentMemoryAllocations(vk::Renderer *renderer, vk::MemoryLogSeverity severity)
{
    if (kTrackMemoryAllocationSizes)
    {
        for (uint32_t i = 0; i < vk::kMemoryAllocationTypeCount; i++)
        {
            if (renderer->getMemoryAllocationTracker()->getActiveMemoryAllocationsSize(i) == 0)
            {
                continue;
            }

            std::stringstream outStream;

            outStream << "Currently allocated size for memory allocation type ("
                      << vk::kMemoryAllocationTypeMessage[i] << "): "
                      << renderer->getMemoryAllocationTracker()->getActiveMemoryAllocationsSize(i)
                      << " | Count: "
                      << renderer->getMemoryAllocationTracker()->getActiveMemoryAllocationsCount(i)
                      << std::endl;

            for (uint32_t heapIndex = 0;
                 heapIndex < renderer->getMemoryProperties().getMemoryHeapCount(); heapIndex++)
            {
                outStream
                    << "--> Heap index " << heapIndex << ": "
                    << renderer->getMemoryAllocationTracker()->getActiveHeapMemoryAllocationsSize(
                           i, heapIndex)
                    << " | Count: "
                    << renderer->getMemoryAllocationTracker()->getActiveHeapMemoryAllocationsCount(
                           i, heapIndex)
                    << std::endl;
            }

            // Output the log stream based on the level of severity.
            OutputMemoryLogStream(outStream, severity);
        }
    }
}

// In case of an allocation error, log pending memory allocation if the size in non-zero.
void LogPendingMemoryAllocation(vk::Renderer *renderer, vk::MemoryLogSeverity severity)
{
    if (!kTrackMemoryAllocationSizes)
    {
        return;
    }

    vk::MemoryAllocationType allocInfo =
        renderer->getMemoryAllocationTracker()->getPendingMemoryAllocationType();
    VkDeviceSize allocSize =
        renderer->getMemoryAllocationTracker()->getPendingMemoryAllocationSize();
    uint32_t memoryTypeIndex = renderer->getMemoryAllocationTracker()->getPendingMemoryTypeIndex();
    uint32_t memoryHeapIndex =
        renderer->getMemoryProperties().getHeapIndexForMemoryType(memoryTypeIndex);

    if (allocSize != 0)
    {
        std::stringstream outStream;

        outStream << "Pending allocation size for memory allocation type ("
                  << vk::kMemoryAllocationTypeMessage[ToUnderlying(allocInfo)]
                  << ") for heap index " << memoryHeapIndex << " (type index " << memoryTypeIndex
                  << "): " << allocSize;

        // Output the log stream based on the level of severity.
        OutputMemoryLogStream(outStream, severity);
    }
}

void LogMemoryHeapStats(vk::Renderer *renderer, vk::MemoryLogSeverity severity)
{
    if (!kTrackMemoryAllocationSizes)
    {
        return;
    }

    // Log stream for the heap information.
    std::stringstream outStream;

    // VkPhysicalDeviceMemoryProperties2 enables the use of memory budget properties if
    // supported.
    VkPhysicalDeviceMemoryProperties2KHR memoryProperties;
    memoryProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR;
    memoryProperties.pNext = nullptr;

    VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudgetProperties;
    memoryBudgetProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
    memoryBudgetProperties.pNext = nullptr;

    if (renderer->getFeatures().supportsMemoryBudget.enabled)
    {
        vk::AddToPNextChain(&memoryProperties, &memoryBudgetProperties);
    }

    vkGetPhysicalDeviceMemoryProperties2(renderer->getPhysicalDevice(), &memoryProperties);

    // Add memory heap information to the stream.
    outStream << "Memory heap info" << std::endl;

    outStream << std::endl << "* Available memory heaps:" << std::endl;
    for (uint32_t i = 0; i < memoryProperties.memoryProperties.memoryHeapCount; i++)
    {
        outStream << std::dec << i
                  << " | Heap size: " << memoryProperties.memoryProperties.memoryHeaps[i].size
                  << " | Flags: 0x" << std::hex
                  << memoryProperties.memoryProperties.memoryHeaps[i].flags << std::endl;
    }

    if (renderer->getFeatures().supportsMemoryBudget.enabled)
    {
        outStream << std::endl << "* Available memory budget and usage per heap:" << std::endl;
        for (uint32_t i = 0; i < memoryProperties.memoryProperties.memoryHeapCount; i++)
        {
            outStream << std::dec << i << " | Heap budget: " << memoryBudgetProperties.heapBudget[i]
                      << " | Heap usage: " << memoryBudgetProperties.heapUsage[i] << std::endl;
        }
    }

    outStream << std::endl << "* Available memory types:" << std::endl;
    for (uint32_t i = 0; i < memoryProperties.memoryProperties.memoryTypeCount; i++)
    {
        outStream << std::dec << i
                  << " | Heap index: " << memoryProperties.memoryProperties.memoryTypes[i].heapIndex
                  << " | Property flags: 0x" << std::hex
                  << memoryProperties.memoryProperties.memoryTypes[i].propertyFlags << std::endl;
    }

    // Output the log stream based on the level of severity.
    OutputMemoryLogStream(outStream, severity);
}
}  // namespace

MemoryAllocationTracker::MemoryAllocationTracker(vk::Renderer *renderer)
    : mRenderer(renderer), mMemoryAllocationID(0)
{}

void MemoryAllocationTracker::initMemoryTrackers()
{
    // Allocation counters are initialized here to keep track of the size and count of the memory
    // allocations.
    for (size_t allocTypeIndex = 0; allocTypeIndex < mActiveMemoryAllocationsSize.size();
         allocTypeIndex++)
    {
        mActiveMemoryAllocationsSize[allocTypeIndex]  = 0;
        mActiveMemoryAllocationsCount[allocTypeIndex] = 0;

        // Per-heap allocation counters are initialized here.
        for (size_t heapIndex = 0;
             heapIndex < mRenderer->getMemoryProperties().getMemoryHeapCount(); heapIndex++)
        {
            mActivePerHeapMemoryAllocationsSize[allocTypeIndex][heapIndex]  = 0;
            mActivePerHeapMemoryAllocationsCount[allocTypeIndex][heapIndex] = 0;
        }
    }

    resetPendingMemoryAlloc();
}

void MemoryAllocationTracker::onDestroy()
{
    if (kTrackMemoryAllocationDebug)
    {
        CheckForCurrentMemoryAllocations(mRenderer, vk::MemoryLogSeverity::INFO);
    }
}

void MemoryAllocationTracker::onDeviceInit()
{
    if (kTrackMemoryAllocationDebug)
    {
        LogMemoryHeapStats(mRenderer, vk::MemoryLogSeverity::INFO);
    }
}

void MemoryAllocationTracker::logMemoryStatsOnError()
{
    CheckForCurrentMemoryAllocations(mRenderer, vk::MemoryLogSeverity::WARN);
    LogPendingMemoryAllocation(mRenderer, vk::MemoryLogSeverity::WARN);
    LogMemoryHeapStats(mRenderer, vk::MemoryLogSeverity::WARN);
}

void MemoryAllocationTracker::onMemoryAllocImpl(vk::MemoryAllocationType allocType,
                                                VkDeviceSize size,
                                                uint32_t memoryTypeIndex,
                                                void *handle)
{
    ASSERT(allocType != vk::MemoryAllocationType::InvalidEnum && size != 0);

    if (kTrackMemoryAllocationDebug)
    {
        // If enabled (debug layers), we keep more details in the memory tracker, such as handle,
        // and log the action to the output.
        std::unique_lock<angle::SimpleMutex> lock(mMemoryAllocationMutex);

        uint32_t allocTypeIndex = ToUnderlying(allocType);
        uint32_t memoryHeapIndex =
            mRenderer->getMemoryProperties().getHeapIndexForMemoryType(memoryTypeIndex);
        mActiveMemoryAllocationsCount[allocTypeIndex]++;
        mActiveMemoryAllocationsSize[allocTypeIndex] += size;
        mActivePerHeapMemoryAllocationsCount[allocTypeIndex][memoryHeapIndex]++;
        mActivePerHeapMemoryAllocationsSize[allocTypeIndex][memoryHeapIndex] += size;

        // Add the new allocation to the memory tracker.
        vk::MemoryAllocationInfo memAllocLogInfo;
        memAllocLogInfo.id              = ++mMemoryAllocationID;
        memAllocLogInfo.allocType       = allocType;
        memAllocLogInfo.memoryHeapIndex = memoryHeapIndex;
        memAllocLogInfo.size            = size;
        memAllocLogInfo.handle          = handle;

        vk::MemoryAllocInfoMapKey memoryAllocInfoMapKey(memAllocLogInfo.handle);
        mMemoryAllocationRecord[angle::getBacktraceInfo()].insert(
            std::make_pair(memoryAllocInfoMapKey, memAllocLogInfo));

        INFO() << "Memory allocation: (id " << memAllocLogInfo.id << ") for object "
               << memAllocLogInfo.handle << " | Size: " << memAllocLogInfo.size
               << " | Type: " << vk::kMemoryAllocationTypeMessage[allocTypeIndex]
               << " | Memory type index: " << memoryTypeIndex
               << " | Heap index: " << memAllocLogInfo.memoryHeapIndex;

        resetPendingMemoryAlloc();
    }
    else if (kTrackMemoryAllocationSizes)
    {
        // Add the new allocation size to the allocation counter.
        uint32_t allocTypeIndex = ToUnderlying(allocType);
        mActiveMemoryAllocationsCount[allocTypeIndex]++;
        mActiveMemoryAllocationsSize[allocTypeIndex] += size;

        uint32_t memoryHeapIndex =
            mRenderer->getMemoryProperties().getHeapIndexForMemoryType(memoryTypeIndex);
        mActivePerHeapMemoryAllocationsCount[allocTypeIndex][memoryHeapIndex].fetch_add(
            1, std::memory_order_relaxed);
        mActivePerHeapMemoryAllocationsSize[allocTypeIndex][memoryHeapIndex].fetch_add(
            size, std::memory_order_relaxed);

        resetPendingMemoryAlloc();
    }
}

void MemoryAllocationTracker::onMemoryDeallocImpl(vk::MemoryAllocationType allocType,
                                                  VkDeviceSize size,
                                                  uint32_t memoryTypeIndex,
                                                  void *handle)
{
    ASSERT(allocType != vk::MemoryAllocationType::InvalidEnum && size != 0);

    if (kTrackMemoryAllocationDebug)
    {
        // If enabled (debug layers), we keep more details in the memory tracker, such as handle,
        // and log the action to the output. The memory allocation tracker uses the backtrace info
        // as key, if available.
        for (auto &memInfoPerBacktrace : mMemoryAllocationRecord)
        {
            vk::MemoryAllocInfoMapKey memoryAllocInfoMapKey(handle);
            MemoryAllocInfoMap &memInfoMap = memInfoPerBacktrace.second;
            std::unique_lock<angle::SimpleMutex> lock(mMemoryAllocationMutex);

            if (memInfoMap.find(memoryAllocInfoMapKey) != memInfoMap.end())
            {
                // Object found; remove it from the allocation tracker.
                vk::MemoryAllocationInfo *memInfoEntry = &memInfoMap[memoryAllocInfoMapKey];
                ASSERT(memInfoEntry->allocType == allocType && memInfoEntry->size == size);

                uint32_t allocTypeIndex = ToUnderlying(memInfoEntry->allocType);
                uint32_t memoryHeapIndex =
                    mRenderer->getMemoryProperties().getHeapIndexForMemoryType(memoryTypeIndex);
                ASSERT(mActiveMemoryAllocationsCount[allocTypeIndex] != 0 &&
                       mActiveMemoryAllocationsSize[allocTypeIndex] >= size);
                ASSERT(memoryHeapIndex == memInfoEntry->memoryHeapIndex &&
                       mActivePerHeapMemoryAllocationsCount[allocTypeIndex][memoryHeapIndex] != 0 &&
                       mActivePerHeapMemoryAllocationsSize[allocTypeIndex][memoryHeapIndex] >=
                           size);
                mActiveMemoryAllocationsCount[allocTypeIndex]--;
                mActiveMemoryAllocationsSize[allocTypeIndex] -= size;
                mActivePerHeapMemoryAllocationsCount[allocTypeIndex][memoryHeapIndex]--;
                mActivePerHeapMemoryAllocationsSize[allocTypeIndex][memoryHeapIndex] -= size;

                INFO() << "Memory deallocation: (id " << memInfoEntry->id << ") for object "
                       << memInfoEntry->handle << " | Size: " << memInfoEntry->size
                       << " | Type: " << vk::kMemoryAllocationTypeMessage[allocTypeIndex]
                       << " | Memory type index: " << memoryTypeIndex
                       << " | Heap index: " << memInfoEntry->memoryHeapIndex;

                memInfoMap.erase(memoryAllocInfoMapKey);
            }
        }
    }
    else if (kTrackMemoryAllocationSizes)
    {
        // Remove the allocation size from the allocation counter.
        uint32_t allocTypeIndex = ToUnderlying(allocType);
        ASSERT(mActiveMemoryAllocationsCount[allocTypeIndex] != 0 &&
               mActiveMemoryAllocationsSize[allocTypeIndex] >= size);
        mActiveMemoryAllocationsCount[allocTypeIndex]--;
        mActiveMemoryAllocationsSize[allocTypeIndex] -= size;

        uint32_t memoryHeapIndex =
            mRenderer->getMemoryProperties().getHeapIndexForMemoryType(memoryTypeIndex);
        ASSERT(mActivePerHeapMemoryAllocationsSize[allocTypeIndex][memoryHeapIndex] >= size);
        mActivePerHeapMemoryAllocationsCount[allocTypeIndex][memoryHeapIndex].fetch_add(
            -1, std::memory_order_relaxed);
        mActivePerHeapMemoryAllocationsSize[allocTypeIndex][memoryHeapIndex].fetch_add(
            -size, std::memory_order_relaxed);
    }
}

VkDeviceSize MemoryAllocationTracker::getActiveMemoryAllocationsSize(uint32_t allocTypeIndex) const
{
    if (!kTrackMemoryAllocationSizes)
    {
        return 0;
    }

    ASSERT(allocTypeIndex < vk::kMemoryAllocationTypeCount);
    return mActiveMemoryAllocationsSize[allocTypeIndex];
}

VkDeviceSize MemoryAllocationTracker::getActiveHeapMemoryAllocationsSize(uint32_t allocTypeIndex,
                                                                         uint32_t heapIndex) const
{
    if (!kTrackMemoryAllocationSizes)
    {
        return 0;
    }

    ASSERT(allocTypeIndex < vk::kMemoryAllocationTypeCount &&
           heapIndex < mRenderer->getMemoryProperties().getMemoryHeapCount());
    return mActivePerHeapMemoryAllocationsSize[allocTypeIndex][heapIndex];
}

uint64_t MemoryAllocationTracker::getActiveMemoryAllocationsCount(uint32_t allocTypeIndex) const
{
    if (!kTrackMemoryAllocationSizes)
    {
        return 0;
    }

    ASSERT(allocTypeIndex < vk::kMemoryAllocationTypeCount);
    return mActiveMemoryAllocationsCount[allocTypeIndex];
}

uint64_t MemoryAllocationTracker::getActiveHeapMemoryAllocationsCount(uint32_t allocTypeIndex,
                                                                      uint32_t heapIndex) const
{
    if (!kTrackMemoryAllocationSizes)
    {
        return 0;
    }

    ASSERT(allocTypeIndex < vk::kMemoryAllocationTypeCount &&
           heapIndex < mRenderer->getMemoryProperties().getMemoryHeapCount());
    return mActivePerHeapMemoryAllocationsCount[allocTypeIndex][heapIndex];
}

void MemoryAllocationTracker::compareExpectedFlagsWithAllocatedFlags(
    VkMemoryPropertyFlags requiredFlags,
    VkMemoryPropertyFlags preferredFlags,
    VkMemoryPropertyFlags allocatedFlags,
    void *handle)
{
    if (!kTrackMemoryAllocationDebug)
    {
        return;
    }

    ASSERT((requiredFlags & ~allocatedFlags) == 0);
    if (((preferredFlags | requiredFlags) & ~allocatedFlags) != 0)
    {
        INFO() << "Memory type index chosen for object " << handle
               << " lacks some of the preferred property flags.";
    }

    if ((~allocatedFlags & preferredFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
    {
        WARN() << "Device-local memory allocation fallback to system memory.";
    }
}

void MemoryAllocationTracker::onExceedingMaxMemoryAllocationSize(VkDeviceSize size)
{
    VkDeviceSize maxAllocationSize = mRenderer->getMaxMemoryAllocationSize();
    ASSERT(size > maxAllocationSize);

    WARN() << "Attempted allocation size (" << size
           << ") is greater than the maximum allocation size allowed (" << maxAllocationSize
           << ").";
}

VkDeviceSize MemoryAllocationTracker::getPendingMemoryAllocationSize() const
{
    if (!kTrackMemoryAllocationSizes)
    {
        return 0;
    }

    return mPendingMemoryAllocationSize;
}

vk::MemoryAllocationType MemoryAllocationTracker::getPendingMemoryAllocationType() const
{
    if (!kTrackMemoryAllocationSizes)
    {
        return vk::MemoryAllocationType::Unspecified;
    }

    return mPendingMemoryAllocationType;
}

uint32_t MemoryAllocationTracker::getPendingMemoryTypeIndex() const
{
    if (!kTrackMemoryAllocationSizes)
    {
        return 0;
    }

    return mPendingMemoryTypeIndex;
}

void MemoryAllocationTracker::setPendingMemoryAlloc(vk::MemoryAllocationType allocType,
                                                    VkDeviceSize size,
                                                    uint32_t memoryTypeIndex)
{
    if (!kTrackMemoryAllocationSizes)
    {
        return;
    }

    ASSERT(allocType != vk::MemoryAllocationType::InvalidEnum && size != 0);
    mPendingMemoryAllocationType = allocType;
    mPendingMemoryAllocationSize = size;
    mPendingMemoryTypeIndex      = memoryTypeIndex;
}

void MemoryAllocationTracker::resetPendingMemoryAlloc()
{
    if (!kTrackMemoryAllocationSizes)
    {
        return;
    }

    mPendingMemoryAllocationType = vk::MemoryAllocationType::Unspecified;
    mPendingMemoryAllocationSize = 0;
    mPendingMemoryTypeIndex      = kInvalidMemoryTypeIndex;
}

namespace vk
{
MemoryReport::MemoryReport()
    : mCurrentTotalAllocatedMemory(0),
      mMaxTotalAllocatedMemory(0),
      mCurrentTotalImportedMemory(0),
      mMaxTotalImportedMemory(0)
{}

void MemoryReport::processCallback(const VkDeviceMemoryReportCallbackDataEXT &callbackData,
                                   bool logCallback)
{
    std::unique_lock<angle::SimpleMutex> lock(mMemoryReportMutex);
    VkDeviceSize size = 0;
    std::string reportType;
    switch (callbackData.type)
    {
        case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT:
            reportType = "Allocate";
            if ((mUniqueIDCounts[callbackData.memoryObjectId] += 1) > 1)
            {
                break;
            }
            size = mSizesPerType[callbackData.objectType].allocatedMemory + callbackData.size;
            mSizesPerType[callbackData.objectType].allocatedMemory = size;
            if (mSizesPerType[callbackData.objectType].allocatedMemoryMax < size)
            {
                mSizesPerType[callbackData.objectType].allocatedMemoryMax = size;
            }
            mCurrentTotalAllocatedMemory += callbackData.size;
            if (mMaxTotalAllocatedMemory < mCurrentTotalAllocatedMemory)
            {
                mMaxTotalAllocatedMemory = mCurrentTotalAllocatedMemory;
            }
            break;
        case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT:
            reportType = "Free";
            ASSERT(mUniqueIDCounts[callbackData.memoryObjectId] > 0);
            mUniqueIDCounts[callbackData.memoryObjectId] -= 1;
            size = mSizesPerType[callbackData.objectType].allocatedMemory - callbackData.size;
            mSizesPerType[callbackData.objectType].allocatedMemory = size;
            mCurrentTotalAllocatedMemory -= callbackData.size;
            break;
        case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT:
            reportType = "Import";
            if ((mUniqueIDCounts[callbackData.memoryObjectId] += 1) > 1)
            {
                break;
            }
            size = mSizesPerType[callbackData.objectType].importedMemory + callbackData.size;
            mSizesPerType[callbackData.objectType].importedMemory = size;
            if (mSizesPerType[callbackData.objectType].importedMemoryMax < size)
            {
                mSizesPerType[callbackData.objectType].importedMemoryMax = size;
            }
            mCurrentTotalImportedMemory += callbackData.size;
            if (mMaxTotalImportedMemory < mCurrentTotalImportedMemory)
            {
                mMaxTotalImportedMemory = mCurrentTotalImportedMemory;
            }
            break;
        case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT:
            reportType = "Un-Import";
            ASSERT(mUniqueIDCounts[callbackData.memoryObjectId] > 0);
            mUniqueIDCounts[callbackData.memoryObjectId] -= 1;
            size = mSizesPerType[callbackData.objectType].importedMemory - callbackData.size;
            mSizesPerType[callbackData.objectType].importedMemory = size;
            mCurrentTotalImportedMemory -= callbackData.size;
            break;
        case VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT:
            reportType = "allocFail";
            break;
        default:
            UNREACHABLE();
            return;
    }
    if (logCallback)
    {
        INFO() << std::right << std::setw(9) << reportType << ": size=" << std::setw(10)
               << callbackData.size << "; type=" << std::setw(15) << std::left
               << Renderer::GetVulkanObjectTypeName(callbackData.objectType)
               << "; heapIdx=" << callbackData.heapIndex << "; id=" << std::hex
               << callbackData.memoryObjectId << "; handle=" << std::hex
               << callbackData.objectHandle << ": Total=" << std::right << std::setw(10) << std::dec
               << size;
    }
}

void MemoryReport::logMemoryReportStats() const
{
    std::unique_lock<angle::SimpleMutex> lock(mMemoryReportMutex);

    INFO() << std::right << "GPU Memory Totals:       Allocated=" << std::setw(10)
           << mCurrentTotalAllocatedMemory << " (max=" << std::setw(10) << mMaxTotalAllocatedMemory
           << ");  Imported=" << std::setw(10) << mCurrentTotalImportedMemory
           << " (max=" << std::setw(10) << mMaxTotalImportedMemory << ")";
    INFO() << "Sub-Totals per type:";
    for (const auto &it : mSizesPerType)
    {
        VkObjectType objectType         = it.first;
        MemorySizes memorySizes         = it.second;
        VkDeviceSize allocatedMemory    = memorySizes.allocatedMemory;
        VkDeviceSize allocatedMemoryMax = memorySizes.allocatedMemoryMax;
        VkDeviceSize importedMemory     = memorySizes.importedMemory;
        VkDeviceSize importedMemoryMax  = memorySizes.importedMemoryMax;
        INFO() << std::right << "- Type=" << std::setw(15)
               << Renderer::GetVulkanObjectTypeName(objectType) << ":  Allocated=" << std::setw(10)
               << allocatedMemory << " (max=" << std::setw(10) << allocatedMemoryMax
               << ");  Imported=" << std::setw(10) << importedMemory << " (max=" << std::setw(10)
               << importedMemoryMax << ")";
    }
}
}  // namespace vk
}  // namespace rx
