vulkan_memory_allocator: Add "download" memory usage hint

Allow users of the allocator to hint memory usage for downloads. This
removes the non-descriptive boolean passed for "host visible" or not
host visible memory commits, and uses an enum to hint device local,
upload and download usages.
This commit is contained in:
ReinUsesLisp 2021-01-03 18:38:15 -03:00
parent fade63b58e
commit 72541af3bc
9 changed files with 86 additions and 45 deletions

View file

@ -156,11 +156,13 @@ MemoryAllocator::MemoryAllocator(const Device& device_)
MemoryAllocator::~MemoryAllocator() = default;
MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, bool host_visible) {
MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) {
const u64 chunk_size = GetAllocationChunkSize(requirements.size);
// When a host visible commit is asked, search for host visible and coherent, otherwise search
// for a fast device local type.
// TODO: Deduce memory types from usage in a better way
const bool host_visible = IsHostVisible(usage);
const VkMemoryPropertyFlags wanted_properties =
host_visible ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
: VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
@ -176,14 +178,14 @@ MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, b
return TryAllocCommit(requirements, wanted_properties).value();
}
MemoryCommit MemoryAllocator::Commit(const vk::Buffer& buffer, bool host_visible) {
auto commit = Commit(device.GetLogical().GetBufferMemoryRequirements(*buffer), host_visible);
MemoryCommit MemoryAllocator::Commit(const vk::Buffer& buffer, MemoryUsage usage) {
auto commit = Commit(device.GetLogical().GetBufferMemoryRequirements(*buffer), usage);
buffer.BindMemory(commit.Memory(), commit.Offset());
return commit;
}
MemoryCommit MemoryAllocator::Commit(const vk::Image& image, bool host_visible) {
auto commit = Commit(device.GetLogical().GetImageMemoryRequirements(*image), host_visible);
MemoryCommit MemoryAllocator::Commit(const vk::Image& image, MemoryUsage usage) {
auto commit = Commit(device.GetLogical().GetImageMemoryRequirements(*image), usage);
image.BindMemory(commit.Memory(), commit.Offset());
return commit;
}
@ -224,4 +226,16 @@ std::optional<MemoryCommit> MemoryAllocator::TryAllocCommit(
return std::nullopt;
}
bool IsHostVisible(MemoryUsage usage) noexcept {
switch (usage) {
case MemoryUsage::DeviceLocal:
return false;
case MemoryUsage::Upload:
case MemoryUsage::Download:
return true;
}
UNREACHABLE_MSG("Invalid memory usage={}", usage);
return false;
}
} // namespace Vulkan

View file

@ -17,7 +17,16 @@ class Device;
class MemoryMap;
class MemoryAllocation;
class MemoryCommit final {
/// Hints and requirements for the backing memory type of a commit
enum class MemoryUsage {
DeviceLocal, ///< Hints device local usages, fastest memory type to read and write from the GPU
Upload, ///< Requires a host visible memory type optimized for CPU to GPU uploads
Download, ///< Requires a host visible memory type optimized for GPU to CPU readbacks
};
/// Ownership handle of a memory commitment.
/// Points to a subregion of a memory allocation.
class MemoryCommit {
public:
explicit MemoryCommit() noexcept = default;
explicit MemoryCommit(const Device& device_, MemoryAllocation* allocation_,
@ -54,7 +63,9 @@ private:
std::span<u8> span; ///< Host visible memory span. Empty if not queried before.
};
class MemoryAllocator final {
/// Memory allocator container.
/// Allocates and releases memory allocations on demand.
class MemoryAllocator {
public:
explicit MemoryAllocator(const Device& device_);
~MemoryAllocator();
@ -71,13 +82,13 @@ public:
*
* @returns A memory commit.
*/
MemoryCommit Commit(const VkMemoryRequirements& requirements, bool host_visible);
MemoryCommit Commit(const VkMemoryRequirements& requirements, MemoryUsage usage);
/// Commits memory required by the buffer and binds it.
MemoryCommit Commit(const vk::Buffer& buffer, bool host_visible);
MemoryCommit Commit(const vk::Buffer& buffer, MemoryUsage usage);
/// Commits memory required by the image and binds it.
MemoryCommit Commit(const vk::Image& image, bool host_visible);
MemoryCommit Commit(const vk::Image& image, MemoryUsage usage);
private:
/// Allocates a chunk of memory.
@ -92,4 +103,7 @@ private:
std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations.
};
/// Returns true when a memory usage is guaranteed to be host visible.
bool IsHostVisible(MemoryUsage usage) noexcept;
} // namespace Vulkan