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;
}
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)
{
info.size = size;
@ -54,15 +54,13 @@ namespace vk
VkMemoryRequirements 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.
// 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!");
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());
}
@ -84,9 +82,6 @@ namespace vk
CHECK_RESULT(vkCreateBuffer(m_device, &info, nullptr, &value));
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);
VkMemoryHostPointerPropertiesEXT memory_properties{};
@ -104,12 +99,16 @@ namespace vk
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!");
}
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()));
}

View file

@ -29,7 +29,7 @@ namespace vk
VkBufferCreateInfo info = {};
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();

View file

@ -42,7 +42,7 @@ namespace vk
}
image::image(const vk::render_device& dev,
u32 memory_type_index,
const memory_type_info& memory_type,
u32 access_flags,
VkImageType image_type,
VkFormat format,
@ -70,7 +70,7 @@ namespace vk
info.initialLayout = initial_layout;
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);
if (format_class == RSX_FORMAT_CLASS_UNDEFINED)
@ -95,7 +95,7 @@ namespace vk
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);
validate(dev, info);
@ -105,15 +105,13 @@ namespace vk
VkMemoryRequirements 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.
// 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!");
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()));
current_layout = info.initialLayout;

View file

@ -37,7 +37,7 @@ namespace vk
protected:
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:
VkImage value = VK_NULL_HANDLE;
@ -48,7 +48,7 @@ namespace vk
std::shared_ptr<vk::memory_block> memory;
image(const vk::render_device& dev,
u32 memory_type_index,
const memory_type_info& memory_type,
u32 access_flags,
VkImageType image_type,
VkFormat format,

View file

@ -14,29 +14,56 @@ namespace
namespace vk
{
memory_type_info::memory_type_info(u32 index)
: num_entries(0)
{
push(index);
}
void memory_type_info::push(u32 index)
{
ensure(num_entries < pools.size());
pools[num_entries++] = index;
type_ids.push_back(index);
}
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
{
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
{
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)
@ -268,11 +295,11 @@ namespace vk
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_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()
@ -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)
{
VkMemoryAllocateInfo alloc_info{};
VkImportMemoryHostPointerInfoEXT import_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.pNext = &import_info;

View file

@ -23,10 +23,10 @@ namespace vk
using namespace vk::vmm_allocation_pool_;
class render_device;
class memory_type_info
{
std::array<u32, 4> pools;
u32 num_entries = 0;
std::vector<u32> type_ids;
public:
memory_type_info() = default;
@ -37,8 +37,11 @@ namespace vk
using const_iterator = const u32*;
const_iterator begin() const;
const_iterator end() const;
u32 first() const;
operator bool() const;
memory_type_info get(const render_device& dev, u32 access_flags, u32 type_mask) const;
};
class mem_allocator_base
@ -121,7 +124,7 @@ namespace vk
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 VkDeviceMemory get_vk_device_memory();
@ -147,7 +150,7 @@ namespace vk
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();
VkDeviceMemory get_vk_device_memory() override;