Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
LDAP committed Feb 7, 2025
1 parent b9f6a85 commit 341c6ee
Show file tree
Hide file tree
Showing 12 changed files with 773 additions and 480 deletions.
1 change: 1 addition & 0 deletions include/merian/vk/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,6 @@ class Context : public std::enable_shared_from_this<Context>, public ExtensionCo

} // namespace merian

#include "merian/vk/command/command_buffer.hpp"
#include "merian/vk/command/command_pool.hpp"
#include "merian/vk/command/queue.hpp"
41 changes: 31 additions & 10 deletions include/merian/vk/memory/memory_allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,22 @@ class AllocationFailed : public VulkanException {
*/
class MemoryAllocator : public std::enable_shared_from_this<MemoryAllocator> {
public:
MemoryAllocator(const ContextHandle& context) : context(context) {}
MemoryAllocator(const ContextHandle& context);

// Make sure the dtor is virtual
virtual ~MemoryAllocator() = default;
virtual ~MemoryAllocator();

public:
// Used to get memory requirements for create infos. Attemps to get the requirements without
// actually creating the image.
vk::MemoryRequirements
get_image_memory_requirements(const vk::ImageCreateInfo& image_create_info);

// Used to get memory requirements for create infos. Attemps to get the requirements without
// actually creating the image.
vk::MemoryRequirements
get_buffer_memory_requirements(const vk::BufferCreateInfo& buffer_create_info);

// Direct highly discouraged. Use create_buffer and create_image instead.
//
// Might throw AllocationFailed. The result OutOfDeviceMemory signalizes that there is not
Expand All @@ -112,13 +122,13 @@ class MemoryAllocator : public std::enable_shared_from_this<MemoryAllocator> {
create_buffer(const vk::BufferCreateInfo buffer_create_info,
const MemoryMappingType mapping_type = MemoryMappingType::NONE,
const std::string& debug_name = {},
const std::optional<vk::DeviceSize> min_alignment = std::nullopt) = 0;
const std::optional<vk::DeviceSize> min_alignment = std::nullopt);

// Might throw AllocationFailed. The result OutOfDeviceMemory signalizes that there is not
// enough memory.
virtual ImageHandle create_image(const vk::ImageCreateInfo image_create_info,
const MemoryMappingType mapping_type = MemoryMappingType::NONE,
const std::string& debug_name = {}) = 0;
const std::string& debug_name = {});

// ------------------------------------------------------------------------------------

Expand All @@ -129,6 +139,7 @@ class MemoryAllocator : public std::enable_shared_from_this<MemoryAllocator> {

private:
const ContextHandle context;
bool supports_memory_requirements_without_object;
};

struct MemoryAllocationInfo {
Expand Down Expand Up @@ -208,17 +219,27 @@ class MemoryAllocation : public std::enable_shared_from_this<MemoryAllocation> {
// ------------------------------------------------------------------------------------

// Creates an image that points to this memory
virtual ImageHandle
create_aliasing_image([[maybe_unused]] const vk::ImageCreateInfo& image_create_info) {
throw std::runtime_error{"create aliasing images is unsupported for this memory type"};
virtual ImageHandle create_aliasing_image(const vk::ImageCreateInfo& image_create_info,
const vk::DeviceSize allocation_offset = 0ul) {
const ImageHandle image = Image::create(context, image_create_info);
bind_to_image(image, allocation_offset);
return image;
}

// Creates a buffer that points to this memory
virtual BufferHandle
create_aliasing_buffer([[maybe_unused]] const vk::BufferCreateInfo& buffer_create_info) {
throw std::runtime_error{"create aliasing images is unsupported for this memory type"};
virtual BufferHandle create_aliasing_buffer(const vk::BufferCreateInfo& buffer_create_info,
const vk::DeviceSize allocation_offset = 0ul) {
const BufferHandle buffer = Buffer::create(context, buffer_create_info);
bind_to_buffer(buffer, allocation_offset);
return buffer;
}

virtual void bind_to_image(const ImageHandle& image,
const vk::DeviceSize allocation_offset = 0ul) = 0;

virtual void bind_to_buffer(const BufferHandle& buffer,
const vk::DeviceSize allocation_offset = 0ul) = 0;

// ------------------------------------------------------------------------------------

// Retrieve detailed information about 'memHandle'. This may not be very efficient.
Expand Down
26 changes: 17 additions & 9 deletions include/merian/vk/memory/memory_allocator_vma.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace merian {

class VMAMemoryAllocator;
using VMAMemoryAllocatorHandle = std::shared_ptr<VMAMemoryAllocator>;

class VMAMemoryAllocation : public MemoryAllocation {
public:
Expand Down Expand Up @@ -51,9 +52,17 @@ class VMAMemoryAllocation : public MemoryAllocation {

// ------------------------------------------------------------------------------------

ImageHandle create_aliasing_image(const vk::ImageCreateInfo& image_create_info) override;
ImageHandle create_aliasing_image(const vk::ImageCreateInfo& image_create_info,
const vk::DeviceSize allocation_offset = 0ul) override;

BufferHandle create_aliasing_buffer(const vk::BufferCreateInfo& buffer_create_info) override;
BufferHandle create_aliasing_buffer(const vk::BufferCreateInfo& buffer_create_info,
const vk::DeviceSize allocation_offset = 0ul) override;

void bind_to_image(const ImageHandle& image,
const vk::DeviceSize allocation_offset = 0ul) override;

void bind_to_buffer(const BufferHandle& buffer,
const vk::DeviceSize allocation_offset = 0ul) override;

// ------------------------------------------------------------------------------------

Expand All @@ -78,13 +87,6 @@ class VMAMemoryAllocator : public MemoryAllocator {
private:
friend class VMAMemoryAllocation;

public:
static std::shared_ptr<VMAMemoryAllocator>
// E.g. supply VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT if you want to use the device
// address feature
make_allocator(const ContextHandle& context, const VmaAllocatorCreateFlags flags = {});

private:
VMAMemoryAllocator() = delete;
explicit VMAMemoryAllocator(const ContextHandle& context,
const VmaAllocatorCreateFlags flags = {});
Expand Down Expand Up @@ -117,6 +119,12 @@ class VMAMemoryAllocator : public MemoryAllocator {

private:
VmaAllocator vma_allocator;

public:
// E.g. supply VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT if you want to use the device
// address feature
static std::shared_ptr<VMAMemoryAllocator> create(const ContextHandle& context,
const VmaAllocatorCreateFlags flags = {});
};

} // namespace merian
77 changes: 41 additions & 36 deletions include/merian/vk/memory/memory_suballocator_vma.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
#include "merian/vk/memory/memory_allocator.hpp"

#include <cstdio>
#include <optional>
#include <spdlog/spdlog.h>
#include <vk_mem_alloc.h>

namespace merian {

class VMAMemorySubAllocator;
using VMAMemorySubAllocatorHandle = std::shared_ptr<VMAMemorySubAllocator>;

class VMAMemorySubAllocation : public MemoryAllocation {
private:
friend class VMAMemorySubAllocator;

public:
VMAMemorySubAllocation() = delete;
VMAMemorySubAllocation(const VMAMemorySubAllocation&) = delete;
Expand All @@ -23,15 +26,10 @@ class VMAMemorySubAllocation : public MemoryAllocation {
*/
VMAMemorySubAllocation(const ContextHandle& context,
const std::shared_ptr<VMAMemorySubAllocator>& allocator,
VmaAllocation allocation,
VmaVirtualAllocation allocation,
const vk::DeviceSize offset,
const vk::DeviceSize size)
: MemoryAllocation(context), allocator(allocator), offset(offset), size(size),
m_allocation(allocation) {
SPDLOG_TRACE("create VMA suballocation ({})", fmt::ptr(this));
}
const vk::DeviceSize size);

// frees the memory when called
~VMAMemorySubAllocation();

// ------------------------------------------------------------------------------------
Expand All @@ -54,30 +52,39 @@ class VMAMemorySubAllocation : public MemoryAllocation {

// ------------------------------------------------------------------------------------

ImageHandle create_aliasing_image(const vk::ImageCreateInfo& image_create_info) override;
ImageHandle create_aliasing_image(const vk::ImageCreateInfo& image_create_info,
const vk::DeviceSize allocation_offset = 0ul) override;

BufferHandle create_aliasing_buffer(const vk::BufferCreateInfo& buffer_create_info,
const vk::DeviceSize allocation_offset = 0ul) override;

void bind_to_image(const ImageHandle& image,
const vk::DeviceSize allocation_offset = 0ul) override;

BufferHandle create_aliasing_buffer(const vk::BufferCreateInfo& buffer_create_info) override;
void bind_to_buffer(const BufferHandle& buffer,
const vk::DeviceSize allocation_offset = 0ul) override;

// ------------------------------------------------------------------------------------

MemoryAllocatorHandle get_allocator() const override;

VmaAllocation get_allocation() const {
return m_allocation;
}
const VMAMemorySubAllocatorHandle& get_suballocator() const;

const vk::DeviceSize& get_size() const;

// offset into the get_suballocator()->get_base_buffer()
const vk::DeviceSize& get_offset() const;

void properties(Properties& props) override;

private:
const std::shared_ptr<VMAMemorySubAllocator> allocator;
VmaVirtualAllocation alloc;
VmaVirtualAllocation allocation;

const vk::DeviceSize offset;
const vk::DeviceSize size;

VmaAllocation m_allocation;
mutable std::mutex allocation_mutex;
void* mapped_memory = nullptr;
std::string name;
};

/**
Expand All @@ -86,17 +93,10 @@ class VMAMemorySubAllocation : public MemoryAllocation {
class VMAMemorySubAllocator : public MemoryAllocator {
private:
friend class VMAMemorySubAllocation;
friend class StagingMemoryManager;

public:
static std::shared_ptr<VMAMemorySubAllocator>
// E.g. supply VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT if you want to use the device
// address feature
make_allocator(const ContextHandle& context, const VmaAllocatorCreateFlags flags = {});

private:
VMAMemorySubAllocator() = delete;
explicit VMAMemorySubAllocator(const ContextHandle& context,
const VmaAllocatorCreateFlags flags = {});
explicit VMAMemorySubAllocator(const BufferHandle& buffer);

public:
~VMAMemorySubAllocator();
Expand All @@ -112,20 +112,25 @@ class VMAMemorySubAllocator : public MemoryAllocator {
const bool dedicated = false,
const float dedicated_priority = 1.0) override;

BufferHandle
create_buffer(const vk::BufferCreateInfo buffer_create_info,
const MemoryMappingType mapping_type = MemoryMappingType::NONE,
const std::string& debug_name = {},
const std::optional<vk::DeviceSize> min_alignment = std::nullopt) override;
// ------------------------------------------------------------------------------------

ImageHandle create_image(const vk::ImageCreateInfo image_create_info,
const MemoryMappingType mapping_type = MemoryMappingType::NONE,
const std::string& debug_name = {}) override;
// Returns the buffer from which this allocator allocates from.
const BufferHandle& get_base_buffer() const;

// ------------------------------------------------------------------------------------
// Returns the VMA block for the virtual allocator.
// You should never use this directly.
const VmaVirtualBlock& get_vma_block() const;

private:
VmaAllocator vma_allocator;
const BufferHandle buffer;
const MemoryAllocationInfo buffer_info;
vk::MemoryPropertyFlags buffer_flags;
vk::DeviceSize buffer_alignment;

VmaVirtualBlock block;

public:
static std::shared_ptr<VMAMemorySubAllocator> create(const BufferHandle& buffer);
};

} // namespace merian
Loading

0 comments on commit 341c6ee

Please sign in to comment.