2019-02-19 04:46:06 +01:00
|
|
|
// Copyright 2019 yuzu Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <memory>
|
2020-12-30 06:25:23 +01:00
|
|
|
#include <span>
|
2019-02-19 04:46:06 +01:00
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
#include "common/common_types.h"
|
2020-12-25 01:30:11 +01:00
|
|
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
2019-02-19 04:46:06 +01:00
|
|
|
|
|
|
|
namespace Vulkan {
|
|
|
|
|
2020-01-06 21:14:41 +01:00
|
|
|
class MemoryMap;
|
2019-02-19 04:46:06 +01:00
|
|
|
class VKDevice;
|
|
|
|
class VKMemoryAllocation;
|
|
|
|
class VKMemoryCommitImpl;
|
|
|
|
|
|
|
|
using VKMemoryCommit = std::unique_ptr<VKMemoryCommitImpl>;
|
|
|
|
|
|
|
|
class VKMemoryManager final {
|
|
|
|
public:
|
2020-12-05 10:51:14 +01:00
|
|
|
explicit VKMemoryManager(const VKDevice& device_);
|
2020-01-06 21:14:41 +01:00
|
|
|
VKMemoryManager(const VKMemoryManager&) = delete;
|
2019-02-19 04:46:06 +01:00
|
|
|
~VKMemoryManager();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Commits a memory with the specified requeriments.
|
2020-01-06 21:14:41 +01:00
|
|
|
* @param requirements Requirements returned from a Vulkan call.
|
2019-02-19 04:46:06 +01:00
|
|
|
* @param host_visible Signals the allocator that it *must* use host visible and coherent
|
2020-01-06 21:14:41 +01:00
|
|
|
* memory. When passing false, it will try to allocate device local memory.
|
2019-02-19 04:46:06 +01:00
|
|
|
* @returns A memory commit.
|
|
|
|
*/
|
2020-04-16 04:33:27 +02:00
|
|
|
VKMemoryCommit Commit(const VkMemoryRequirements& requirements, bool host_visible);
|
2019-02-19 04:46:06 +01:00
|
|
|
|
|
|
|
/// Commits memory required by the buffer and binds it.
|
2020-03-27 05:33:21 +01:00
|
|
|
VKMemoryCommit Commit(const vk::Buffer& buffer, bool host_visible);
|
2019-02-19 04:46:06 +01:00
|
|
|
|
|
|
|
/// Commits memory required by the image and binds it.
|
2020-03-27 05:33:21 +01:00
|
|
|
VKMemoryCommit Commit(const vk::Image& image, bool host_visible);
|
2019-02-19 04:46:06 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
/// Allocates a chunk of memory.
|
2020-03-27 05:33:21 +01:00
|
|
|
bool AllocMemory(VkMemoryPropertyFlags wanted_properties, u32 type_mask, u64 size);
|
2019-02-19 04:46:06 +01:00
|
|
|
|
2020-01-06 21:14:41 +01:00
|
|
|
/// Tries to allocate a memory commit.
|
2020-03-27 05:33:21 +01:00
|
|
|
VKMemoryCommit TryAllocCommit(const VkMemoryRequirements& requirements,
|
|
|
|
VkMemoryPropertyFlags wanted_properties);
|
2020-01-06 21:14:41 +01:00
|
|
|
|
2020-04-22 02:46:58 +02:00
|
|
|
const VKDevice& device; ///< Device handler.
|
|
|
|
const VkPhysicalDeviceMemoryProperties properties; ///< Physical device properties.
|
2020-01-06 21:14:41 +01:00
|
|
|
std::vector<std::unique_ptr<VKMemoryAllocation>> allocations; ///< Current allocations.
|
2019-02-19 04:46:06 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class VKMemoryCommitImpl final {
|
|
|
|
friend VKMemoryAllocation;
|
2020-01-06 21:14:41 +01:00
|
|
|
friend MemoryMap;
|
2019-02-19 04:46:06 +01:00
|
|
|
|
|
|
|
public:
|
2020-12-05 10:51:14 +01:00
|
|
|
explicit VKMemoryCommitImpl(const VKDevice& device_, VKMemoryAllocation* allocation_,
|
|
|
|
const vk::DeviceMemory& memory_, u64 begin_, u64 end_);
|
2019-02-19 04:46:06 +01:00
|
|
|
~VKMemoryCommitImpl();
|
|
|
|
|
2020-01-06 21:14:41 +01:00
|
|
|
/// Maps a memory region and returns a pointer to it.
|
|
|
|
/// It's illegal to have more than one memory map at the same time.
|
|
|
|
MemoryMap Map(u64 size, u64 offset = 0) const;
|
|
|
|
|
|
|
|
/// Maps the whole commit and returns a pointer to it.
|
|
|
|
/// It's illegal to have more than one memory map at the same time.
|
|
|
|
MemoryMap Map() const;
|
2019-02-19 04:46:06 +01:00
|
|
|
|
|
|
|
/// Returns the Vulkan memory handler.
|
2020-03-27 05:33:21 +01:00
|
|
|
VkDeviceMemory GetMemory() const {
|
|
|
|
return *memory;
|
2019-02-19 04:46:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the start position of the commit relative to the allocation.
|
2020-03-27 05:33:21 +01:00
|
|
|
VkDeviceSize GetOffset() const {
|
|
|
|
return static_cast<VkDeviceSize>(interval.first);
|
2019-02-19 04:46:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2020-01-06 21:14:41 +01:00
|
|
|
/// Unmaps memory.
|
|
|
|
void Unmap() const;
|
|
|
|
|
|
|
|
const VKDevice& device; ///< Vulkan device.
|
2020-03-27 05:33:21 +01:00
|
|
|
const vk::DeviceMemory& memory; ///< Vulkan device memory handler.
|
2019-02-19 04:46:06 +01:00
|
|
|
std::pair<u64, u64> interval{}; ///< Interval where the commit exists.
|
|
|
|
VKMemoryAllocation* allocation{}; ///< Pointer to the large memory allocation.
|
2020-01-06 21:14:41 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Holds ownership of a memory map.
|
|
|
|
class MemoryMap final {
|
|
|
|
public:
|
2020-12-30 06:25:23 +01:00
|
|
|
explicit MemoryMap(const VKMemoryCommitImpl* commit_, std::span<u8> span_)
|
|
|
|
: commit{commit_}, span{span_} {}
|
2020-01-06 21:14:41 +01:00
|
|
|
|
|
|
|
~MemoryMap() {
|
|
|
|
if (commit) {
|
|
|
|
commit->Unmap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Prematurely releases the memory map.
|
|
|
|
void Release() {
|
|
|
|
commit->Unmap();
|
|
|
|
commit = nullptr;
|
|
|
|
}
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
/// Returns a span to the memory map.
|
|
|
|
[[nodiscard]] std::span<u8> Span() const noexcept {
|
|
|
|
return span;
|
|
|
|
}
|
|
|
|
|
2020-01-06 21:14:41 +01:00
|
|
|
/// Returns the address of the memory map.
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] u8* Address() const noexcept {
|
|
|
|
return span.data();
|
2020-01-06 21:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the address of the memory map;
|
2020-12-30 06:25:23 +01:00
|
|
|
[[nodiscard]] operator u8*() const noexcept {
|
|
|
|
return span.data();
|
2020-01-06 21:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const VKMemoryCommitImpl* commit{}; ///< Mapped memory commit.
|
2020-12-30 06:25:23 +01:00
|
|
|
std::span<u8> span; ///< Address to the mapped memory.
|
2019-02-19 04:46:06 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Vulkan
|