vk: Make use of multi-pool memory types

This commit is contained in:
kd-11 2021-07-23 19:46:45 +03:00 committed by kd-11
parent de7ed1cbe9
commit 69bdbe97a8
6 changed files with 65 additions and 38 deletions

View file

@ -39,7 +39,7 @@ namespace vk
return false; return false;
} }
buffer::buffer(const vk::render_device& dev, u64 size, u32 memory_type_index, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags, vmm_allocation_pool allocation_pool) buffer::buffer(const vk::render_device& dev, u64 size, const memory_type_info& memory_type, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags, vmm_allocation_pool allocation_pool)
: m_device(dev) : m_device(dev)
{ {
info.size = size; info.size = size;
@ -54,15 +54,13 @@ namespace vk
VkMemoryRequirements memory_reqs; VkMemoryRequirements memory_reqs;
vkGetBufferMemoryRequirements(m_device, value, &memory_reqs); vkGetBufferMemoryRequirements(m_device, value, &memory_reqs);
if (!(memory_reqs.memoryTypeBits & (1 << memory_type_index))) memory_type_info allocation_type_info = memory_type.get(dev, access_flags, memory_reqs.memoryTypeBits);
if (!allocation_type_info)
{ {
// Suggested memory type is incompatible with this memory type. fmt::throw_exception("No compatible memory type was found!");
// Go through the bitset and test for requested props.
if (!dev.get_compatible_memory_type(memory_reqs.memoryTypeBits, access_flags, &memory_type_index))
fmt::throw_exception("No compatible memory type was found!");
} }
memory = std::make_unique<memory_block>(m_device, memory_reqs.size, memory_reqs.alignment, memory_type_index, allocation_pool); memory = std::make_unique<memory_block>(m_device, memory_reqs.size, memory_reqs.alignment, allocation_type_info, allocation_pool);
vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset()); vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset());
} }
@ -84,9 +82,6 @@ namespace vk
CHECK_RESULT(vkCreateBuffer(m_device, &info, nullptr, &value)); CHECK_RESULT(vkCreateBuffer(m_device, &info, nullptr, &value));
auto& memory_map = dev.get_memory_mapping(); auto& memory_map = dev.get_memory_mapping();
u32 memory_type_index = memory_map.host_visible_coherent;
VkFlags access_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
ensure(memory_map._vkGetMemoryHostPointerPropertiesEXT); ensure(memory_map._vkGetMemoryHostPointerPropertiesEXT);
VkMemoryHostPointerPropertiesEXT memory_properties{}; VkMemoryHostPointerPropertiesEXT memory_properties{};
@ -104,12 +99,16 @@ namespace vk
required_memory_type_bits = memory_properties.memoryTypeBits; required_memory_type_bits = memory_properties.memoryTypeBits;
} }
if (!dev.get_compatible_memory_type(required_memory_type_bits, access_flags, &memory_type_index)) const auto allocation_type_info = memory_map.host_visible_coherent.get(dev,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
required_memory_type_bits);
if (!allocation_type_info)
{ {
fmt::throw_exception("No compatible memory type was found!"); fmt::throw_exception("No compatible memory type was found!");
} }
memory = std::make_unique<memory_block_host>(m_device, host_pointer, size, memory_type_index); memory = std::make_unique<memory_block_host>(m_device, host_pointer, size, allocation_type_info);
CHECK_RESULT(vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset())); CHECK_RESULT(vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset()));
} }

View file

@ -29,7 +29,7 @@ namespace vk
VkBufferCreateInfo info = {}; VkBufferCreateInfo info = {};
std::unique_ptr<vk::memory_block> memory; std::unique_ptr<vk::memory_block> memory;
buffer(const vk::render_device& dev, u64 size, u32 memory_type_index, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags, vmm_allocation_pool allocation_pool); buffer(const vk::render_device& dev, u64 size, const memory_type_info& memory_type, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags, vmm_allocation_pool allocation_pool);
buffer(const vk::render_device& dev, VkBufferUsageFlags usage, void* host_pointer, u64 size); buffer(const vk::render_device& dev, VkBufferUsageFlags usage, void* host_pointer, u64 size);
~buffer(); ~buffer();

View file

@ -42,7 +42,7 @@ namespace vk
} }
image::image(const vk::render_device& dev, image::image(const vk::render_device& dev,
u32 memory_type_index, const memory_type_info& memory_type,
u32 access_flags, u32 access_flags,
VkImageType image_type, VkImageType image_type,
VkFormat format, VkFormat format,
@ -70,7 +70,7 @@ namespace vk
info.initialLayout = initial_layout; info.initialLayout = initial_layout;
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
create_impl(dev, access_flags, memory_type_index, allocation_pool); create_impl(dev, access_flags, memory_type, allocation_pool);
m_storage_aspect = get_aspect_flags(format); m_storage_aspect = get_aspect_flags(format);
if (format_class == RSX_FORMAT_CLASS_UNDEFINED) if (format_class == RSX_FORMAT_CLASS_UNDEFINED)
@ -95,7 +95,7 @@ namespace vk
vkDestroyImage(m_device, value, nullptr); vkDestroyImage(m_device, value, nullptr);
} }
void image::create_impl(const vk::render_device& dev, u32 access_flags, u32 memory_type_index, vmm_allocation_pool allocation_pool) void image::create_impl(const vk::render_device& dev, u32 access_flags, const memory_type_info& memory_type, vmm_allocation_pool allocation_pool)
{ {
ensure(!value && !memory); ensure(!value && !memory);
validate(dev, info); validate(dev, info);
@ -105,15 +105,13 @@ namespace vk
VkMemoryRequirements memory_req; VkMemoryRequirements memory_req;
vkGetImageMemoryRequirements(m_device, value, &memory_req); vkGetImageMemoryRequirements(m_device, value, &memory_req);
if (!(memory_req.memoryTypeBits & (1 << memory_type_index))) const auto allocation_type_info = memory_type.get(dev, access_flags, memory_req.memoryTypeBits);
if (!allocation_type_info)
{ {
// Suggested memory type is incompatible with this memory type. fmt::throw_exception("No compatible memory type was found!");
// Go through the bitset and test for requested props.
if (!dev.get_compatible_memory_type(memory_req.memoryTypeBits, access_flags, &memory_type_index))
fmt::throw_exception("No compatible memory type was found!");
} }
memory = std::make_shared<vk::memory_block>(m_device, memory_req.size, memory_req.alignment, memory_type_index, allocation_pool); memory = std::make_shared<vk::memory_block>(m_device, memory_req.size, memory_req.alignment, allocation_type_info, allocation_pool);
CHECK_RESULT(vkBindImageMemory(m_device, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset())); CHECK_RESULT(vkBindImageMemory(m_device, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset()));
current_layout = info.initialLayout; current_layout = info.initialLayout;

View file

@ -37,7 +37,7 @@ namespace vk
protected: protected:
image() = default; image() = default;
void create_impl(const vk::render_device& dev, u32 access_flags, u32 memory_type_index, vmm_allocation_pool allocation_pool); void create_impl(const vk::render_device& dev, u32 access_flags, const memory_type_info& memory_type, vmm_allocation_pool allocation_pool);
public: public:
VkImage value = VK_NULL_HANDLE; VkImage value = VK_NULL_HANDLE;
@ -48,7 +48,7 @@ namespace vk
std::shared_ptr<vk::memory_block> memory; std::shared_ptr<vk::memory_block> memory;
image(const vk::render_device& dev, image(const vk::render_device& dev,
u32 memory_type_index, const memory_type_info& memory_type,
u32 access_flags, u32 access_flags,
VkImageType image_type, VkImageType image_type,
VkFormat format, VkFormat format,

View file

@ -14,29 +14,56 @@ namespace
namespace vk namespace vk
{ {
memory_type_info::memory_type_info(u32 index) memory_type_info::memory_type_info(u32 index)
: num_entries(0)
{ {
push(index); push(index);
} }
void memory_type_info::push(u32 index) void memory_type_info::push(u32 index)
{ {
ensure(num_entries < pools.size()); type_ids.push_back(index);
pools[num_entries++] = index;
} }
memory_type_info::const_iterator memory_type_info::begin() const memory_type_info::const_iterator memory_type_info::begin() const
{ {
return pools.data(); return type_ids.data();
} }
memory_type_info::const_iterator memory_type_info::end() const memory_type_info::const_iterator memory_type_info::end() const
{ {
return pools.data() + num_entries; return type_ids.data() + type_ids.size();
}
u32 memory_type_info::first() const
{
ensure(!type_ids.empty());
return type_ids.front();
} }
memory_type_info::operator bool() const memory_type_info::operator bool() const
{ {
return (num_entries > 0); return !type_ids.empty();
}
memory_type_info memory_type_info::get(const render_device& dev, u32 access_flags, u32 type_mask) const
{
memory_type_info result{};
for (const auto& type : type_ids)
{
if (type_mask & (1 << type))
{
result.push(type);
}
}
if (!result)
{
u32 type;
if (dev.get_compatible_memory_type(type_mask, access_flags, &type))
{
result = type;
}
}
return result;
} }
mem_allocator_vma::mem_allocator_vma(VkDevice dev, VkPhysicalDevice pdev) : mem_allocator_base(dev, pdev) mem_allocator_vma::mem_allocator_vma(VkDevice dev, VkPhysicalDevice pdev) : mem_allocator_base(dev, pdev)
@ -268,11 +295,11 @@ namespace vk
return g_render_device->get_allocator(); return g_render_device->get_allocator();
} }
memory_block::memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool) memory_block::memory_block(VkDevice dev, u64 block_sz, u64 alignment, const memory_type_info& memory_type, vmm_allocation_pool pool)
: m_device(dev), m_size(block_sz) : m_device(dev), m_size(block_sz)
{ {
m_mem_allocator = get_current_mem_allocator(); m_mem_allocator = get_current_mem_allocator();
m_mem_handle = m_mem_allocator->alloc(block_sz, alignment, memory_type_index, pool); m_mem_handle = m_mem_allocator->alloc(block_sz, alignment, memory_type, pool);
} }
memory_block::~memory_block() memory_block::~memory_block()
@ -283,14 +310,14 @@ namespace vk
} }
} }
memory_block_host::memory_block_host(VkDevice dev, void* host_pointer, u64 size, u32 memory_type_index) : memory_block_host::memory_block_host(VkDevice dev, void* host_pointer, u64 size, const memory_type_info& memory_type) :
m_device(dev), m_mem_handle(VK_NULL_HANDLE), m_host_pointer(host_pointer) m_device(dev), m_mem_handle(VK_NULL_HANDLE), m_host_pointer(host_pointer)
{ {
VkMemoryAllocateInfo alloc_info{}; VkMemoryAllocateInfo alloc_info{};
VkImportMemoryHostPointerInfoEXT import_info{}; VkImportMemoryHostPointerInfoEXT import_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.memoryTypeIndex = memory_type_index; alloc_info.memoryTypeIndex = memory_type.first();
alloc_info.allocationSize = size; alloc_info.allocationSize = size;
alloc_info.pNext = &import_info; alloc_info.pNext = &import_info;

View file

@ -23,10 +23,10 @@ namespace vk
using namespace vk::vmm_allocation_pool_; using namespace vk::vmm_allocation_pool_;
class render_device;
class memory_type_info class memory_type_info
{ {
std::array<u32, 4> pools; std::vector<u32> type_ids;
u32 num_entries = 0;
public: public:
memory_type_info() = default; memory_type_info() = default;
@ -37,8 +37,11 @@ namespace vk
using const_iterator = const u32*; using const_iterator = const u32*;
const_iterator begin() const; const_iterator begin() const;
const_iterator end() const; const_iterator end() const;
u32 first() const;
operator bool() const; operator bool() const;
memory_type_info get(const render_device& dev, u32 access_flags, u32 type_mask) const;
}; };
class mem_allocator_base class mem_allocator_base
@ -121,7 +124,7 @@ namespace vk
struct memory_block struct memory_block
{ {
memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool); memory_block(VkDevice dev, u64 block_sz, u64 alignment, const memory_type_info& memory_type, vmm_allocation_pool pool);
virtual ~memory_block(); virtual ~memory_block();
virtual VkDeviceMemory get_vk_device_memory(); virtual VkDeviceMemory get_vk_device_memory();
@ -147,7 +150,7 @@ namespace vk
struct memory_block_host : public memory_block struct memory_block_host : public memory_block
{ {
memory_block_host(VkDevice dev, void* host_pointer, u64 size, u32 memory_type_index); memory_block_host(VkDevice dev, void* host_pointer, u64 size, const memory_type_info& memory_type);
~memory_block_host(); ~memory_block_host();
VkDeviceMemory get_vk_device_memory() override; VkDeviceMemory get_vk_device_memory() override;