diff --git a/rpcs3/Emu/RSX/VK/VKDMA.cpp b/rpcs3/Emu/RSX/VK/VKDMA.cpp index bb480100e0..32c79b3d52 100644 --- a/rpcs3/Emu/RSX/VK/VKDMA.cpp +++ b/rpcs3/Emu/RSX/VK/VKDMA.cpp @@ -67,7 +67,8 @@ namespace vk allocated_memory = std::make_unique(dev, size, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0); + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0, + VMM_ALLOCATION_POOL_UNDEFINED); s_allocated_dma_pool_size += allocated_memory->size(); } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 6153b691c6..80dac3cade 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -481,7 +481,7 @@ VKGSRender::VKGSRender() : GSRender() } const auto& memory_map = m_device->get_memory_mapping(); - null_buffer = std::make_unique(*m_device, 32, memory_map.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0); + null_buffer = std::make_unique(*m_device, 32, memory_map.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); null_buffer_view = std::make_unique(*m_device, null_buffer->value, VK_FORMAT_R8_UINT, 0, 32); vk::initialize_compiler_context(); @@ -2461,7 +2461,7 @@ void VKGSRender::begin_conditional_rendering(const std::vector( *m_device, 4, memory_props.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - usage_flags, 0); + usage_flags, 0, VMM_ALLOCATION_POOL_UNDEFINED); } VkPipelineStageFlags dst_stage; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 558043d898..5ef5157c66 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -365,6 +365,8 @@ private: deadlock = 2 }; + using enum vk::vmm_allocation_pool; + private: VKFragmentProgram m_fragment_prog; VKVertexProgram m_vertex_prog; diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.cpp b/rpcs3/Emu/RSX/VK/VKOverlays.cpp index 9b4860d8df..14071fd479 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.cpp +++ b/rpcs3/Emu/RSX/VK/VKOverlays.cpp @@ -514,7 +514,7 @@ namespace vk auto tex = std::make_unique(dev, dev.get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_TYPE_2D, format, std::max(w, 1u), std::max(h, 1u), 1, 1, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - 0); + 0, VMM_ALLOCATION_POOL_UNDEFINED); if (pixel_src && data_size) std::memcpy(addr, pixel_src, data_size); diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index c3fffabe65..fbc5e55acf 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -655,8 +655,8 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) const usz sshot_size = buffer_height * buffer_width * 4; - vk::buffer sshot_vkbuf(*m_device, utils::align(sshot_size, 0x100000), m_device->get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0); + vk::buffer sshot_vkbuf(*m_device, utils::align(sshot_size, 0x100000), m_device->get_memory_mapping().host_visible_coherent, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); VkBufferImageCopy copy_info; copy_info.bufferOffset = 0; diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp index 632b174318..99953b18f6 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp @@ -26,6 +26,7 @@ namespace vk VK_IMAGE_TILING_OPTIMAL, usage, 0, + VMM_ALLOCATION_POOL_SURFACE_CACHE, format_class())); resolve_surface->native_component_map = native_component_map; diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index c82c5d390e..96a0494202 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -9,6 +9,7 @@ #include "vkutils/data_heap.h" #include "vkutils/device.h" #include "vkutils/image.h" +#include "vkutils/memory.h" #include "vkutils/scratch.h" #include @@ -120,7 +121,7 @@ namespace rsx VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, usage_flags, - 0, RSX_FORMAT_CLASS_COLOR); + 0, vk::VMM_ALLOCATION_POOL_SURFACE_CACHE, RSX_FORMAT_CLASS_COLOR); rtt->set_debug_name(fmt::format("RTV @0x%x", address)); rtt->change_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -181,7 +182,7 @@ namespace rsx VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, usage_flags, - 0, rsx::classify_format(format)); + 0, vk::VMM_ALLOCATION_POOL_SURFACE_CACHE, rsx::classify_format(format)); ds->set_debug_name(fmt::format("DSV @0x%x", address)); ds->change_layout(cmd, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); @@ -223,6 +224,7 @@ namespace rsx VK_IMAGE_TILING_OPTIMAL, ref->info.usage, ref->info.flags, + vk::VMM_ALLOCATION_POOL_SURFACE_CACHE, ref->format_class()); sink->add_ref(); diff --git a/rpcs3/Emu/RSX/VK/VKResourceManager.cpp b/rpcs3/Emu/RSX/VK/VKResourceManager.cpp index 9e00172714..5ff1634c71 100644 --- a/rpcs3/Emu/RSX/VK/VKResourceManager.cpp +++ b/rpcs3/Emu/RSX/VK/VKResourceManager.cpp @@ -54,7 +54,7 @@ namespace vk return size / (1024.f * 1024.f * 1024.f); } - void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size) + void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size, vmm_allocation_pool pool) { auto key = reinterpret_cast(handle); const vmm_allocation_t info = { memory_size, memory_type }; diff --git a/rpcs3/Emu/RSX/VK/VKTextOut.h b/rpcs3/Emu/RSX/VK/VKTextOut.h index 9556fa80ea..a169ecf275 100644 --- a/rpcs3/Emu/RSX/VK/VKTextOut.h +++ b/rpcs3/Emu/RSX/VK/VKTextOut.h @@ -264,8 +264,8 @@ namespace vk //At worst case, 1 char = 16*16*8 bytes (average about 24*8), so ~256K for 128 chars. Allocating 512k for verts //uniform params are 8k in size, allocating for 120 lines (max lines at 4k, one column per row. Can be expanded - m_vertex_buffer = std::make_unique(dev, 524288, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 0); - m_uniforms_buffer = std::make_unique(dev, 983040, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 0); + m_vertex_buffer = std::make_unique(dev, 524288, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); + m_uniforms_buffer = std::make_unique(dev, 983040, dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); m_render_pass = render_pass; m_uniform_buffer_size = 983040; diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index db1bef53c7..2496d82058 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -576,7 +576,7 @@ namespace vk dst_format, w, h, d, mips, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, image_flags, - rsx::classify_format(gcm_format)); + VMM_ALLOCATION_POOL_TEXTURE_CACHE, rsx::classify_format(gcm_format)); } //This method is almost exclusively used to work on framebuffer resources @@ -871,7 +871,7 @@ namespace vk vk_format, width, height, depth, mipmaps, layer, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, usage_flags, is_cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, - rsx::classify_format(gcm_format)); + VMM_ALLOCATION_POOL_TEXTURE_CACHE, rsx::classify_format(gcm_format)); // New section, we must prepare it region.reset(rsx_range); @@ -1220,7 +1220,8 @@ namespace vk VK_IMAGE_TYPE_2D, format, width, height, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED, - VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0); + VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + 0, VMM_ALLOCATION_POOL_TEXTURE_CACHE); VkImageSubresource subresource{}; subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; diff --git a/rpcs3/Emu/RSX/VK/vkutils/buffer_object.cpp b/rpcs3/Emu/RSX/VK/vkutils/buffer_object.cpp index f78aa143c6..4dcf51d288 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/buffer_object.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/buffer_object.cpp @@ -5,7 +5,7 @@ namespace vk { buffer_view::buffer_view(VkDevice dev, VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize size) - : m_device(dev) + : m_device(dev) { info.buffer = buffer; info.format = format; @@ -39,97 +39,97 @@ namespace vk return false; } - buffer::buffer(const vk::render_device& dev, u64 size, u32 memory_type_index, u32 access_flags, VkBufferUsageFlags usage, VkBufferCreateFlags flags) - : m_device(dev) + 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) + : m_device(dev) + { + info.size = size; + info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.flags = flags; + info.usage = usage; + + CHECK_RESULT(vkCreateBuffer(m_device, &info, nullptr, &value)); + + // Allocate vram for this buffer + VkMemoryRequirements memory_reqs; + vkGetBufferMemoryRequirements(m_device, value, &memory_reqs); + + if (!(memory_reqs.memoryTypeBits & (1 << memory_type_index))) { - info.size = size; - info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - info.flags = flags; - info.usage = usage; - - CHECK_RESULT(vkCreateBuffer(m_device, &info, nullptr, &value)); - - //Allocate vram for this buffer - VkMemoryRequirements memory_reqs; - vkGetBufferMemoryRequirements(m_device, value, &memory_reqs); - - if (!(memory_reqs.memoryTypeBits & (1 << memory_type_index))) - { - //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!"); - } - - memory = std::make_unique(m_device, memory_reqs.size, memory_reqs.alignment, memory_type_index); - vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset()); - } - - buffer::buffer(const vk::render_device& dev, VkBufferUsageFlags usage, void* host_pointer, u64 size) - : m_device(dev) - { - info.size = size; - info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - info.flags = 0; - info.usage = usage; - - VkExternalMemoryBufferCreateInfoKHR ex_info; - ex_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR; - ex_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; - ex_info.pNext = nullptr; - - info.pNext = &ex_info; - 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{}; - memory_properties.sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT; - CHECK_RESULT(memory_map._vkGetMemoryHostPointerPropertiesEXT(dev, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, host_pointer, &memory_properties)); - - VkMemoryRequirements memory_reqs; - vkGetBufferMemoryRequirements(m_device, value, &memory_reqs); - - auto required_memory_type_bits = memory_reqs.memoryTypeBits & memory_properties.memoryTypeBits; - if (!required_memory_type_bits) - { - // AMD driver bug. Buffers created with external memory extension return type bits of 0 - rsx_log.warning("Could not match buffer requirements and host pointer properties."); - required_memory_type_bits = memory_properties.memoryTypeBits; - } - - if (!dev.get_compatible_memory_type(required_memory_type_bits, access_flags, &memory_type_index)) - { + // 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!"); - } - - memory = std::make_unique(m_device, host_pointer, size, memory_type_index); - CHECK_RESULT(vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset())); } - buffer::~buffer() + memory = std::make_unique(m_device, memory_reqs.size, memory_reqs.alignment, memory_type_index, allocation_pool); + vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset()); + } + + buffer::buffer(const vk::render_device& dev, VkBufferUsageFlags usage, void* host_pointer, u64 size) + : m_device(dev) + { + info.size = size; + info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.flags = 0; + info.usage = usage; + + VkExternalMemoryBufferCreateInfoKHR ex_info; + ex_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR; + ex_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + ex_info.pNext = nullptr; + + info.pNext = &ex_info; + 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{}; + memory_properties.sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT; + CHECK_RESULT(memory_map._vkGetMemoryHostPointerPropertiesEXT(dev, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, host_pointer, &memory_properties)); + + VkMemoryRequirements memory_reqs; + vkGetBufferMemoryRequirements(m_device, value, &memory_reqs); + + auto required_memory_type_bits = memory_reqs.memoryTypeBits & memory_properties.memoryTypeBits; + if (!required_memory_type_bits) { - vkDestroyBuffer(m_device, value, nullptr); + // AMD driver bug. Buffers created with external memory extension return type bits of 0 + rsx_log.warning("Could not match buffer requirements and host pointer properties."); + required_memory_type_bits = memory_properties.memoryTypeBits; } - void* buffer::map(u64 offset, u64 size) + if (!dev.get_compatible_memory_type(required_memory_type_bits, access_flags, &memory_type_index)) { - return memory->map(offset, size); + fmt::throw_exception("No compatible memory type was found!"); } - void buffer::unmap() - { - memory->unmap(); - } + memory = std::make_unique(m_device, host_pointer, size, memory_type_index); + CHECK_RESULT(vkBindBufferMemory(dev, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset())); + } - u32 buffer::size() const - { - return static_cast(info.size); - } + buffer::~buffer() + { + vkDestroyBuffer(m_device, value, nullptr); + } + + void* buffer::map(u64 offset, u64 size) + { + return memory->map(offset, size); + } + + void buffer::unmap() + { + memory->unmap(); + } + + u32 buffer::size() const + { + return static_cast(info.size); + } } diff --git a/rpcs3/Emu/RSX/VK/vkutils/buffer_object.h b/rpcs3/Emu/RSX/VK/vkutils/buffer_object.h index f82c9819ef..2134df9814 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); + 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, VkBufferUsageFlags usage, void* host_pointer, u64 size); ~buffer(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp b/rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp index bb8ee2b349..21d96064a0 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp @@ -26,13 +26,13 @@ namespace vk { rsx_log.warning("Buffer usage %u is not heap-compatible using this driver, explicit staging buffer in use", usage); - shadow = std::make_unique(*g_render_device, size, memory_index, memory_flags, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0); + shadow = std::make_unique(*g_render_device, size, memory_index, memory_flags, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0, VMM_ALLOCATION_POOL_SYSTEM); usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; memory_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; memory_index = memory_map.device_local; } - heap = std::make_unique(*g_render_device, size, memory_index, memory_flags, usage, 0); + heap = std::make_unique(*g_render_device, size, memory_index, memory_flags, usage, 0, VMM_ALLOCATION_POOL_SYSTEM); initial_size = size; notify_on_grow = bool(notify); @@ -87,7 +87,7 @@ namespace vk // Discard old heap and create a new one. Old heap will be garbage collected when no longer needed get_resource_manager()->dispose(heap); - heap = std::make_unique(*g_render_device, aligned_new_size, memory_index, memory_flags, usage, 0); + heap = std::make_unique(*g_render_device, aligned_new_size, memory_index, memory_flags, usage, 0, VMM_ALLOCATION_POOL_SYSTEM); if (notify_on_grow) { diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.cpp b/rpcs3/Emu/RSX/VK/vkutils/image.cpp index 0ea2ff921f..6bcccdfcaa 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/image.cpp @@ -53,9 +53,9 @@ namespace vk VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags image_flags, + vmm_allocation_pool allocation_pool, rsx::format_class format_class) - : current_layout(initial_layout) - , m_device(dev) + : m_device(dev) { info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; info.imageType = image_type; @@ -70,23 +70,7 @@ namespace vk info.initialLayout = initial_layout; info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - validate(dev, info); - CHECK_RESULT(vkCreateImage(m_device, &info, nullptr, &value)); - - VkMemoryRequirements memory_req; - vkGetImageMemoryRequirements(m_device, value, &memory_req); - - if (!(memory_req.memoryTypeBits & (1 << memory_type_index))) - { - //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!"); - } - - memory = std::make_shared(m_device, memory_req.size, memory_req.alignment, memory_type_index); - CHECK_RESULT(vkBindImageMemory(m_device, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset())); - + create_impl(dev, access_flags, memory_type_index, allocation_pool); m_storage_aspect = get_aspect_flags(format); if (format_class == RSX_FORMAT_CLASS_UNDEFINED) @@ -111,6 +95,30 @@ 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) + { + ensure(!value && !memory); + validate(dev, info); + + CHECK_RESULT(vkCreateImage(m_device, &info, nullptr, &value)); + + VkMemoryRequirements memory_req; + vkGetImageMemoryRequirements(m_device, value, &memory_req); + + if (!(memory_req.memoryTypeBits & (1 << memory_type_index))) + { + //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!"); + } + + memory = std::make_shared(m_device, memory_req.size, memory_req.alignment, memory_type_index, allocation_pool); + CHECK_RESULT(vkBindImageMemory(m_device, value, memory->get_vk_device_memory(), memory->get_vk_device_memory_offset())); + + current_layout = info.initialLayout; + } + u32 image::width() const { return info.extent.width; @@ -330,6 +338,20 @@ namespace vk #endif } + viewable_image* viewable_image::clone() + { + // Destructive cloning. The clone grabs the GPU objects owned by this instance. + // This instance can be rebuilt in-place by calling create_impl() which will create a duplicate now owned by this. + auto result = new viewable_image(); + result->m_device = this->m_device; + result->info = this->info; + result->value = this->value; + result->memory = std::move(this->memory); + result->views = std::move(this->views); + this->value = VK_NULL_HANDLE; + return result; + } + image_view* viewable_image::get_view(u32 remap_encoding, const std::pair, std::array>& remap, VkImageAspectFlags mask) { if (remap_encoding == VK_REMAP_IDENTITY) diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.h b/rpcs3/Emu/RSX/VK/vkutils/image.h index 0a8e89a097..831d0369d1 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.h +++ b/rpcs3/Emu/RSX/VK/vkutils/image.h @@ -35,6 +35,10 @@ namespace vk void validate(const vk::render_device& dev, const VkImageCreateInfo& info) const; + protected: + image() = default; + void create_impl(const vk::render_device& dev, u32 access_flags, u32 memory_type_index, vmm_allocation_pool allocation_pool); + public: VkImage value = VK_NULL_HANDLE; VkComponentMapping native_component_map = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; @@ -55,6 +59,7 @@ namespace vk VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags image_flags, + vmm_allocation_pool allocation_pool, rsx::format_class format_class = RSX_FORMAT_CLASS_UNDEFINED); virtual ~image(); @@ -84,7 +89,7 @@ namespace vk // Debug utils void set_debug_name(const std::string& name); - private: + protected: VkDevice m_device; }; @@ -118,8 +123,9 @@ namespace vk class viewable_image : public image { - private: + protected: std::unordered_multimap> views; + viewable_image* clone(); public: using image::image; diff --git a/rpcs3/Emu/RSX/VK/vkutils/memory.cpp b/rpcs3/Emu/RSX/VK/vkutils/memory.cpp index 78f2a6f67b..abefe3712a 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/memory.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/memory.cpp @@ -22,7 +22,10 @@ namespace vk allocatorInfo.physicalDevice = pdev; allocatorInfo.device = dev; - vmaCreateAllocator(&allocatorInfo, &m_allocator); + CHECK_RESULT(vmaCreateAllocator(&allocatorInfo, &m_allocator)); + + // Allow fastest possible allocation on start + set_fastest_allocation_flags(); } void mem_allocator_vma::destroy() @@ -30,7 +33,7 @@ namespace vk vmaDestroyAllocator(m_allocator); } - mem_allocator_vk::mem_handle_t mem_allocator_vma::alloc(u64 block_sz, u64 alignment, u32 memory_type_index) + mem_allocator_vk::mem_handle_t mem_allocator_vma::alloc(u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool) { VmaAllocation vma_alloc; VkMemoryRequirements mem_req = {}; @@ -40,7 +43,7 @@ namespace vk mem_req.size = ::align2(block_sz, alignment); mem_req.alignment = alignment; create_info.memoryTypeBits = 1u << memory_type_index; - create_info.flags = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT; + create_info.flags = m_allocation_flags; if (VkResult result = vmaAllocateMemory(m_allocator, &mem_req, &create_info, &vma_alloc, nullptr); result != VK_SUCCESS) @@ -62,7 +65,7 @@ namespace vk } } - vmm_notify_memory_allocated(vma_alloc, memory_type_index, block_sz); + vmm_notify_memory_allocated(vma_alloc, memory_type_index, block_sz, pool); return vma_alloc; } @@ -123,7 +126,17 @@ namespace vk return max_usage; } - mem_allocator_vk::mem_handle_t mem_allocator_vk::alloc(u64 block_sz, u64 /*alignment*/, u32 memory_type_index) + void mem_allocator_vma::set_safest_allocation_flags() + { + m_allocation_flags = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT; + } + + void mem_allocator_vma::set_fastest_allocation_flags() + { + m_allocation_flags = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT; + } + + mem_allocator_vk::mem_handle_t mem_allocator_vk::alloc(u64 block_sz, u64 /*alignment*/, u32 memory_type_index, vmm_allocation_pool pool) { VkDeviceMemory memory; VkMemoryAllocateInfo info = {}; @@ -149,7 +162,7 @@ namespace vk } } - vmm_notify_memory_allocated(memory, memory_type_index, block_sz); + vmm_notify_memory_allocated(memory, memory_type_index, block_sz, pool); return memory; } @@ -191,11 +204,11 @@ namespace vk return g_render_device->get_allocator(); } - memory_block::memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index) - : m_device(dev) + memory_block::memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index, 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); + m_mem_handle = m_mem_allocator->alloc(block_sz, alignment, memory_type_index, pool); } memory_block::~memory_block() @@ -259,6 +272,11 @@ namespace vk return m_mem_allocator->get_vk_device_memory_offset(m_mem_handle); } + u64 memory_block::size() const + { + return m_size; + } + void* memory_block::map(u64 offset, u64 size) { return m_mem_allocator->map(m_mem_handle, offset, size); diff --git a/rpcs3/Emu/RSX/VK/vkutils/memory.h b/rpcs3/Emu/RSX/VK/vkutils/memory.h index 7452f85ad3..02dadb0c6b 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/memory.h +++ b/rpcs3/Emu/RSX/VK/vkutils/memory.h @@ -8,17 +8,27 @@ namespace vk { + enum vmm_allocation_pool + { + VMM_ALLOCATION_POOL_UNDEFINED = 0, + VMM_ALLOCATION_POOL_SYSTEM, + VMM_ALLOCATION_POOL_SURFACE_CACHE, + VMM_ALLOCATION_POOL_TEXTURE_CACHE, + VMM_ALLOCATION_POOL_SWAPCHAIN, + VMM_ALLOCATION_POOL_SCRATCH, + }; + class mem_allocator_base { public: using mem_handle_t = void*; - mem_allocator_base(VkDevice dev, VkPhysicalDevice /*pdev*/) : m_device(dev) {} + mem_allocator_base(VkDevice dev, VkPhysicalDevice /*pdev*/) : m_device(dev), m_allocation_flags(0) {} virtual ~mem_allocator_base() = default; virtual void destroy() = 0; - virtual mem_handle_t alloc(u64 block_sz, u64 alignment, u32 memory_type_index) = 0; + virtual mem_handle_t alloc(u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool) = 0; virtual void free(mem_handle_t mem_handle) = 0; virtual void* map(mem_handle_t mem_handle, u64 offset, u64 size) = 0; virtual void unmap(mem_handle_t mem_handle) = 0; @@ -26,8 +36,12 @@ namespace vk virtual u64 get_vk_device_memory_offset(mem_handle_t mem_handle) = 0; virtual f32 get_memory_usage() = 0; + virtual void set_safest_allocation_flags() {} + virtual void set_fastest_allocation_flags() {} + protected: VkDevice m_device; + VkFlags m_allocation_flags; }; @@ -42,7 +56,7 @@ namespace vk void destroy() override; - mem_handle_t alloc(u64 block_sz, u64 alignment, u32 memory_type_index) override; + mem_handle_t alloc(u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool) override; void free(mem_handle_t mem_handle) override; void* map(mem_handle_t mem_handle, u64 offset, u64 /*size*/) override; @@ -52,6 +66,9 @@ namespace vk u64 get_vk_device_memory_offset(mem_handle_t mem_handle) override; f32 get_memory_usage() override; + void set_safest_allocation_flags() override; + void set_fastest_allocation_flags() override; + private: VmaAllocator m_allocator; std::array stats; @@ -68,7 +85,7 @@ namespace vk void destroy() override {} - mem_handle_t alloc(u64 block_sz, u64 /*alignment*/, u32 memory_type_index) override; + mem_handle_t alloc(u64 block_sz, u64 /*alignment*/, u32 memory_type_index, vmm_allocation_pool pool) override; void free(mem_handle_t mem_handle) override; void* map(mem_handle_t mem_handle, u64 offset, u64 size) override; @@ -81,7 +98,7 @@ namespace vk struct memory_block { - memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index); + memory_block(VkDevice dev, u64 block_sz, u64 alignment, u32 memory_type_index, vmm_allocation_pool pool); virtual ~memory_block(); virtual VkDeviceMemory get_vk_device_memory(); @@ -90,6 +107,8 @@ namespace vk virtual void* map(u64 offset, u64 size); virtual void unmap(); + u64 size() const; + memory_block(const memory_block&) = delete; memory_block(memory_block&&) = delete; @@ -100,6 +119,7 @@ namespace vk VkDevice m_device; vk::mem_allocator_base* m_mem_allocator = nullptr; mem_allocator_base::mem_handle_t m_mem_handle; + u64 m_size; }; struct memory_block_host : public memory_block @@ -122,11 +142,14 @@ namespace vk void* m_host_pointer; }; - void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size); + void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size, vmm_allocation_pool pool); void vmm_notify_memory_freed(void* handle); void vmm_reset(); void vmm_check_memory_usage(); + u64 vmm_get_application_memory_usage(u32 memory_type); + u64 vmm_get_application_pool_usage(vmm_allocation_pool pool); bool vmm_handle_memory_pressure(rsx::problem_severity severity); + rsx::problem_severity vmm_determine_memory_load_severity(); mem_allocator_base* get_current_mem_allocator(); } diff --git a/rpcs3/Emu/RSX/VK/vkutils/scratch.cpp b/rpcs3/Emu/RSX/VK/vkutils/scratch.cpp index 6a600ace90..bb2966e4c6 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/scratch.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/scratch.cpp @@ -97,7 +97,7 @@ namespace vk auto& tex = g_null_image_views[type]; tex = std::make_unique(*g_render_device, g_render_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image_type, VK_FORMAT_B8G8R8A8_UNORM, size, size, 1, 1, num_layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, flags); + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, flags, VMM_ALLOCATION_POOL_SCRATCH); // Initialize memory to transparent black tex->change_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); @@ -122,7 +122,7 @@ namespace vk return new vk::image(*g_render_device, g_render_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_TYPE_2D, format, new_width, new_height, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0); + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0, VMM_ALLOCATION_POOL_SCRATCH); }; const u32 key = (format_class << 24u) | format; @@ -160,7 +160,7 @@ namespace vk scratch_buffer = std::make_unique(*g_render_device, alloc_size, g_render_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 0); + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_SCRATCH); } return scratch_buffer.get(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/swapchain.hpp b/rpcs3/Emu/RSX/VK/vkutils/swapchain.hpp index d2f201f57d..0a8903f986 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/swapchain.hpp +++ b/rpcs3/Emu/RSX/VK/vkutils/swapchain.hpp @@ -27,14 +27,14 @@ namespace vk swapchain_image_RPCS3(render_device& dev, const memory_type_mapping& memory_map, u32 width, u32 height) :image(dev, memory_map.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_TYPE_2D, VK_FORMAT_B8G8R8A8_UNORM, width, height, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0) + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, VMM_ALLOCATION_POOL_SWAPCHAIN) { m_width = width; m_height = height; current_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; m_dma_buffer = std::make_unique(dev, m_width * m_height * 4, memory_map.host_visible_coherent, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0); + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, 0, VMM_ALLOCATION_POOL_SWAPCHAIN); } void do_dma_transfer(command_buffer& cmd) diff --git a/rpcs3/Emu/RSX/VK/vkutils/sync.cpp b/rpcs3/Emu/RSX/VK/vkutils/sync.cpp index 9379979f96..874217545a 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/sync.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/sync.cpp @@ -84,7 +84,8 @@ namespace vk dev.get_memory_mapping().host_visible_coherent, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT, - 0 + 0, + VMM_ALLOCATION_POOL_SYSTEM ); m_value = reinterpret_cast(m_buffer->map(0, 4));