diff --git a/rpcs3/Emu/RSX/VK/vkutils/buffer_object.cpp b/rpcs3/Emu/RSX/VK/vkutils/buffer_object.cpp index 4dcf51d288..145192d007 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/buffer_object.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/buffer_object.cpp @@ -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(m_device, memory_reqs.size, memory_reqs.alignment, memory_type_index, allocation_pool); + memory = std::make_unique(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(m_device, host_pointer, size, memory_type_index); + memory = std::make_unique(m_device, host_pointer, size, allocation_type_info); CHECK_RESULT(vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset())); } diff --git a/rpcs3/Emu/RSX/VK/vkutils/buffer_object.h b/rpcs3/Emu/RSX/VK/vkutils/buffer_object.h index 2134df9814..03f5659e49 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/buffer_object.h +++ b/rpcs3/Emu/RSX/VK/vkutils/buffer_object.h @@ -29,7 +29,7 @@ namespace vk VkBufferCreateInfo info = {}; std::unique_ptr 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(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.cpp b/rpcs3/Emu/RSX/VK/vkutils/image.cpp index 54cd7853ea..387d4c040d 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/image.cpp @@ -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(m_device, memory_req.size, memory_req.alignment, memory_type_index, allocation_pool); + memory = std::make_shared(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; diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.h b/rpcs3/Emu/RSX/VK/vkutils/image.h index 831d0369d1..360e83b3b2 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.h +++ b/rpcs3/Emu/RSX/VK/vkutils/image.h @@ -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 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, diff --git a/rpcs3/Emu/RSX/VK/vkutils/memory.cpp b/rpcs3/Emu/RSX/VK/vkutils/memory.cpp index 6627c0c891..07aff18bc4 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/memory.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/memory.cpp @@ -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; diff --git a/rpcs3/Emu/RSX/VK/vkutils/memory.h b/rpcs3/Emu/RSX/VK/vkutils/memory.h index 24e228e26d..0c8af6e3a7 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/memory.h +++ b/rpcs3/Emu/RSX/VK/vkutils/memory.h @@ -23,10 +23,10 @@ namespace vk using namespace vk::vmm_allocation_pool_; + class render_device; class memory_type_info { - std::array pools; - u32 num_entries = 0; + std::vector 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;