2019-11-26 09:42:44 +00:00
|
|
|
/*
|
|
|
|
Created on: Nov 24, 2019
|
|
|
|
|
|
|
|
Copyright 2019 flyinghead
|
|
|
|
|
|
|
|
This file is part of Flycast.
|
|
|
|
|
|
|
|
Flycast is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Flycast is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#pragma once
|
2021-01-04 17:56:15 +00:00
|
|
|
#include <cinttypes>
|
2019-11-26 09:42:44 +00:00
|
|
|
#include "vulkan.h"
|
|
|
|
#include "vk_mem_alloc.h"
|
|
|
|
|
2021-01-21 21:44:51 +00:00
|
|
|
#if !defined(PRIu64) && defined(_WIN32)
|
|
|
|
#define PRIu64 "I64u"
|
|
|
|
#endif
|
|
|
|
|
2019-11-26 09:42:44 +00:00
|
|
|
class VMAllocator;
|
|
|
|
|
|
|
|
class Allocation
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Allocation() = default;
|
|
|
|
Allocation(const Allocation& other) = delete;
|
|
|
|
Allocation& operator=(const Allocation& other) = delete;
|
|
|
|
|
|
|
|
Allocation(Allocation&& other) : allocator(other.allocator), allocation(other.allocation),
|
|
|
|
allocInfo(other.allocInfo) {
|
|
|
|
other.allocator = VK_NULL_HANDLE;
|
|
|
|
other.allocation = VK_NULL_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Allocation& operator=(Allocation&& other) {
|
|
|
|
std::swap(this->allocator, other.allocator);
|
|
|
|
std::swap(this->allocation, other.allocation);
|
|
|
|
std::swap(this->allocInfo, other.allocInfo);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~Allocation() {
|
|
|
|
if (allocator != VK_NULL_HANDLE)
|
|
|
|
vmaFreeMemory(allocator, allocation);
|
|
|
|
}
|
|
|
|
bool IsHostVisible() const {
|
|
|
|
VkMemoryPropertyFlags flags;
|
|
|
|
vmaGetMemoryTypeProperties(allocator, allocInfo.memoryType, &flags);
|
|
|
|
return flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
|
|
|
}
|
|
|
|
void *MapMemory() const {
|
|
|
|
return allocInfo.pMappedData;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Allocation(VmaAllocator allocator, VmaAllocation allocation, VmaAllocationInfo allocInfo)
|
|
|
|
: allocator(allocator), allocation(allocation), allocInfo(allocInfo)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
VmaAllocator allocator = VK_NULL_HANDLE;
|
|
|
|
VmaAllocation allocation = VK_NULL_HANDLE;
|
|
|
|
VmaAllocationInfo allocInfo;
|
|
|
|
|
|
|
|
friend class VMAllocator;
|
|
|
|
};
|
|
|
|
|
|
|
|
class VMAllocator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void Init(vk::PhysicalDevice physicalDevice, vk::Device device);
|
|
|
|
|
|
|
|
void Term()
|
|
|
|
{
|
|
|
|
if (allocator != VK_NULL_HANDLE)
|
|
|
|
{
|
|
|
|
vmaDestroyAllocator(allocator);
|
|
|
|
allocator = VK_NULL_HANDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Allocation AllocateMemory(const vk::MemoryRequirements& memoryRequirements, const VmaAllocationCreateInfo& allocCreateInfo) const
|
|
|
|
{
|
|
|
|
VmaAllocation vmaAllocation;
|
|
|
|
VmaAllocationInfo allocInfo;
|
|
|
|
VkResult rc = vmaAllocateMemory(allocator, (VkMemoryRequirements*)&memoryRequirements, &allocCreateInfo, &vmaAllocation, &allocInfo);
|
|
|
|
if (rc != VK_SUCCESS)
|
|
|
|
throwResultException((vk::Result)rc, "vmaAllocateMemory failed");
|
|
|
|
return Allocation(allocator, vmaAllocation, allocInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
Allocation AllocateForImage(const vk::Image image, const VmaAllocationCreateInfo& allocCreateInfo) const
|
|
|
|
{
|
|
|
|
VmaAllocation vmaAllocation;
|
|
|
|
VmaAllocationInfo allocInfo;
|
|
|
|
VkResult rc = vmaAllocateMemoryForImage(allocator, (VkImage)image, &allocCreateInfo, &vmaAllocation, &allocInfo);
|
|
|
|
if (rc != VK_SUCCESS)
|
|
|
|
throwResultException((vk::Result)rc, "vmaAllocateMemoryForImage failed");
|
2019-11-26 11:12:43 +00:00
|
|
|
vmaBindImageMemory(allocator, vmaAllocation, (VkImage)image);
|
2019-11-26 09:42:44 +00:00
|
|
|
|
|
|
|
return Allocation(allocator, vmaAllocation, allocInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
Allocation AllocateForBuffer(const vk::Buffer buffer, const VmaAllocationCreateInfo& allocCreateInfo) const
|
|
|
|
{
|
|
|
|
VmaAllocation vmaAllocation;
|
|
|
|
VmaAllocationInfo allocInfo;
|
|
|
|
VkResult rc = vmaAllocateMemoryForBuffer(allocator, (VkBuffer)buffer, &allocCreateInfo, &vmaAllocation, &allocInfo);
|
|
|
|
if (rc != VK_SUCCESS)
|
|
|
|
throwResultException((vk::Result)rc, "vmaAllocateMemoryForBuffer failed");
|
2019-11-26 11:12:43 +00:00
|
|
|
vmaBindBufferMemory(allocator, vmaAllocation, (VkBuffer)buffer);
|
2019-11-26 09:42:44 +00:00
|
|
|
|
|
|
|
return Allocation(allocator, vmaAllocation, allocInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrintStats() const
|
|
|
|
{
|
|
|
|
VmaStats stats;
|
|
|
|
vmaCalculateStats(allocator, &stats);
|
2021-01-04 17:56:15 +00:00
|
|
|
NOTICE_LOG(RENDERER, "Vma stats: %d chunks, %d allocs, %" PRIu64 " bytes used, %" PRIu64 " free", stats.total.blockCount,
|
|
|
|
stats.total.allocationCount, stats.total.usedBytes, stats.total.unusedBytes);
|
2019-11-26 09:42:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
VmaAllocator allocator = VK_NULL_HANDLE;
|
|
|
|
};
|