diff --git a/.gitmodules b/.gitmodules index 352566414..a73061e22 100644 --- a/.gitmodules +++ b/.gitmodules @@ -82,3 +82,6 @@ [submodule "third_party/SPIRV-Tools"] path = third_party/SPIRV-Tools url = https://github.com/KhronosGroup/SPIRV-Tools.git +[submodule "third_party/VulkanMemoryAllocator"] + path = third_party/VulkanMemoryAllocator + url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git diff --git a/src/xenia/gpu/vulkan/vulkan_texture_cache.cc b/src/xenia/gpu/vulkan/vulkan_texture_cache.cc index f2dc4ea29..580696a30 100644 --- a/src/xenia/gpu/vulkan/vulkan_texture_cache.cc +++ b/src/xenia/gpu/vulkan/vulkan_texture_cache.cc @@ -21,6 +21,7 @@ #include "xenia/gpu/texture_util.h" #include "xenia/gpu/vulkan/deferred_command_buffer.h" #include "xenia/gpu/vulkan/vulkan_command_processor.h" +#include "xenia/ui/vulkan/vulkan_mem_alloc.h" #include "xenia/ui/vulkan/vulkan_util.h" namespace xe { @@ -468,6 +469,14 @@ VulkanTextureCache::~VulkanTextureCache() { if (load_pipeline_layout_ != VK_NULL_HANDLE) { dfn.vkDestroyPipelineLayout(device, load_pipeline_layout_, nullptr); } + + // Textures memory is allocated using the Vulkan Memory Allocator, destroy all + // textures before destroying VMA. + DestroyAllTextures(true); + + if (vma_allocator_ != VK_NULL_HANDLE) { + vmaDestroyAllocator(vma_allocator_); + } } void VulkanTextureCache::BeginSubmission(uint64_t new_submission_index) { @@ -1052,21 +1061,19 @@ std::unique_ptr VulkanTextureCache::CreateTexture( image_format_list_create_info.viewFormatCount = 2; image_format_list_create_info.pViewFormats = formats; } - // TODO(Triang3l): Suballocate due to the low memory allocation count limit on - // Windows (use VMA or a custom allocator, possibly based on two-level - // segregated fit just like VMA). + + VmaAllocationCreateInfo allocation_create_info = {}; + allocation_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; + VkImage image; - VkDeviceMemory memory; - VkDeviceSize memory_size; - if (!ui::vulkan::util::CreateDedicatedAllocationImage( - provider, image_create_info, - ui::vulkan::util::MemoryPurpose::kDeviceLocal, image, memory, nullptr, - &memory_size)) { + VmaAllocation allocation; + if (vmaCreateImage(vma_allocator_, &image_create_info, + &allocation_create_info, &image, &allocation, nullptr)) { return nullptr; } return std::unique_ptr( - new VulkanTexture(*this, key, image, memory, memory_size)); + new VulkanTexture(*this, key, image, allocation)); } bool VulkanTextureCache::LoadTextureDataFromResidentMemoryImpl(Texture& texture, @@ -1571,9 +1578,12 @@ void VulkanTextureCache::UpdateTextureBindingsImpl( VulkanTextureCache::VulkanTexture::VulkanTexture( VulkanTextureCache& texture_cache, const TextureKey& key, VkImage image, - VkDeviceMemory memory, VkDeviceSize memory_size) - : Texture(texture_cache, key), image_(image), memory_(memory) { - SetHostMemoryUsage(uint64_t(memory_size)); + VmaAllocation allocation) + : Texture(texture_cache, key), image_(image), allocation_(allocation) { + VmaAllocationInfo allocation_info; + vmaGetAllocationInfo(texture_cache.vma_allocator_, allocation_, + &allocation_info); + SetHostMemoryUsage(uint64_t(allocation_info.size)); } VulkanTextureCache::VulkanTexture::~VulkanTexture() { @@ -1586,8 +1596,7 @@ VulkanTextureCache::VulkanTexture::~VulkanTexture() { for (const auto& view_pair : views_) { dfn.vkDestroyImageView(device, view_pair.second, nullptr); } - dfn.vkDestroyImage(device, image_, nullptr); - dfn.vkFreeMemory(device, memory_, nullptr); + vmaDestroyImage(vulkan_texture_cache.vma_allocator_, image_, allocation_); } VkImageView VulkanTextureCache::VulkanTexture::GetView(bool is_signed, @@ -1708,6 +1717,13 @@ bool VulkanTextureCache::Initialize() { device_portability_subset_features = provider.device_portability_subset_features(); + // Vulkan Memory Allocator. + + vma_allocator_ = ui::vulkan::CreateVmaAllocator(provider, true); + if (vma_allocator_ == VK_NULL_HANDLE) { + return false; + } + // Image formats. // Initialize to the best formats. diff --git a/src/xenia/gpu/vulkan/vulkan_texture_cache.h b/src/xenia/gpu/vulkan/vulkan_texture_cache.h index 79e5db493..448e74d03 100644 --- a/src/xenia/gpu/vulkan/vulkan_texture_cache.h +++ b/src/xenia/gpu/vulkan/vulkan_texture_cache.h @@ -19,6 +19,7 @@ #include "xenia/gpu/texture_cache.h" #include "xenia/gpu/vulkan/vulkan_shader.h" #include "xenia/gpu/vulkan/vulkan_shared_memory.h" +#include "xenia/ui/vulkan/vulkan_mem_alloc.h" #include "xenia/ui/vulkan/vulkan_provider.h" namespace xe { @@ -185,7 +186,7 @@ class VulkanTextureCache final : public TextureCache { // Takes ownership of the image and its memory. explicit VulkanTexture(VulkanTextureCache& texture_cache, const TextureKey& key, VkImage image, - VkDeviceMemory memory, VkDeviceSize memory_size); + VmaAllocation allocation); ~VulkanTexture(); VkImage image() const { return image_; } @@ -255,7 +256,7 @@ class VulkanTextureCache final : public TextureCache { } VkImage image_; - VkDeviceMemory memory_; + VmaAllocation allocation_; Usage usage_ = Usage::kUndefined; @@ -317,6 +318,12 @@ class VulkanTextureCache final : public TextureCache { VulkanCommandProcessor& command_processor_; VkPipelineStageFlags guest_shader_pipeline_stages_; + // Using the Vulkan Memory Allocator because texture count in games is + // naturally pretty much unbounded, while Vulkan implementations, especially + // on Windows versions before 10, may have an allocation count limit as low as + // 4096. + VmaAllocator vma_allocator_ = VK_NULL_HANDLE; + static const HostFormatPair kBestHostFormats[64]; static const HostFormatPair kHostFormatGBGRUnaligned; static const HostFormatPair kHostFormatBGRGUnaligned; diff --git a/src/xenia/ui/vulkan/functions/device_1_0.inc b/src/xenia/ui/vulkan/functions/device_1_0.inc index ae640f61e..4e9eaa83a 100644 --- a/src/xenia/ui/vulkan/functions/device_1_0.inc +++ b/src/xenia/ui/vulkan/functions/device_1_0.inc @@ -66,6 +66,7 @@ XE_UI_VULKAN_FUNCTION(vkGetBufferMemoryRequirements) XE_UI_VULKAN_FUNCTION(vkGetDeviceQueue) XE_UI_VULKAN_FUNCTION(vkGetFenceStatus) XE_UI_VULKAN_FUNCTION(vkGetImageMemoryRequirements) +XE_UI_VULKAN_FUNCTION(vkInvalidateMappedMemoryRanges) XE_UI_VULKAN_FUNCTION(vkMapMemory) XE_UI_VULKAN_FUNCTION(vkResetCommandPool) XE_UI_VULKAN_FUNCTION(vkResetDescriptorPool) diff --git a/src/xenia/ui/vulkan/functions/device_khr_bind_memory2.inc b/src/xenia/ui/vulkan/functions/device_khr_bind_memory2.inc new file mode 100644 index 000000000..ebefbc50f --- /dev/null +++ b/src/xenia/ui/vulkan/functions/device_khr_bind_memory2.inc @@ -0,0 +1,4 @@ +// VK_KHR_bind_memory2 functions used in Xenia. +// Promoted to Vulkan 1.1 core. +XE_UI_VULKAN_FUNCTION_PROMOTED(vkBindBufferMemory2KHR, vkBindBufferMemory2) +XE_UI_VULKAN_FUNCTION_PROMOTED(vkBindImageMemory2KHR, vkBindImageMemory2) diff --git a/src/xenia/ui/vulkan/functions/device_khr_get_memory_requirements2.inc b/src/xenia/ui/vulkan/functions/device_khr_get_memory_requirements2.inc new file mode 100644 index 000000000..11068c485 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/device_khr_get_memory_requirements2.inc @@ -0,0 +1,6 @@ +// VK_KHR_get_memory_requirements2 functions used in Xenia. +// Promoted to Vulkan 1.1 core. +XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetBufferMemoryRequirements2KHR, + vkGetBufferMemoryRequirements2) +XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetImageMemoryRequirements2KHR, + vkGetImageMemoryRequirements2) diff --git a/src/xenia/ui/vulkan/functions/device_khr_maintenance4.inc b/src/xenia/ui/vulkan/functions/device_khr_maintenance4.inc new file mode 100644 index 000000000..11c078792 --- /dev/null +++ b/src/xenia/ui/vulkan/functions/device_khr_maintenance4.inc @@ -0,0 +1,6 @@ +// VK_KHR_maintenance4 functions used in Xenia. +// Promoted to Vulkan 1.3 core. +XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetDeviceBufferMemoryRequirementsKHR, + vkGetDeviceBufferMemoryRequirements) +XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetDeviceImageMemoryRequirementsKHR, + vkGetDeviceImageMemoryRequirements) diff --git a/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc b/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc index 05b2fe800..45153db06 100644 --- a/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc +++ b/src/xenia/ui/vulkan/functions/instance_khr_get_physical_device_properties2.inc @@ -1,4 +1,6 @@ // VK_KHR_get_physical_device_properties2 functions used in Xenia. // Promoted to Vulkan 1.1 core. +XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetPhysicalDeviceMemoryProperties2KHR, + vkGetPhysicalDeviceMemoryProperties2) XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetPhysicalDeviceProperties2KHR, vkGetPhysicalDeviceProperties2) diff --git a/src/xenia/ui/vulkan/vulkan_mem_alloc.cc b/src/xenia/ui/vulkan/vulkan_mem_alloc.cc new file mode 100644 index 000000000..d3be16c5f --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_mem_alloc.cc @@ -0,0 +1,108 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +// Implementing VMA in this translation unit. +#define VMA_IMPLEMENTATION +#include "xenia/ui/vulkan/vulkan_mem_alloc.h" + +#include + +#include "xenia/base/logging.h" +#include "xenia/ui/vulkan/vulkan_provider.h" + +namespace xe { +namespace ui { +namespace vulkan { + +VmaAllocator CreateVmaAllocator(const VulkanProvider& provider, + bool externally_synchronized) { + const VulkanProvider::LibraryFunctions& lfn = provider.lfn(); + const VulkanProvider::InstanceFunctions& ifn = provider.ifn(); + const VulkanProvider::DeviceFunctions& dfn = provider.dfn(); + const VulkanProvider::InstanceExtensions& instance_extensions = + provider.instance_extensions(); + const VulkanProvider::DeviceExtensions& device_extensions = + provider.device_extensions(); + + VmaVulkanFunctions vma_vulkan_functions = {}; + VmaAllocatorCreateInfo allocator_create_info = {}; + + vma_vulkan_functions.vkGetInstanceProcAddr = lfn.vkGetInstanceProcAddr; + vma_vulkan_functions.vkGetDeviceProcAddr = ifn.vkGetDeviceProcAddr; + vma_vulkan_functions.vkGetPhysicalDeviceProperties = + ifn.vkGetPhysicalDeviceProperties; + vma_vulkan_functions.vkGetPhysicalDeviceMemoryProperties = + ifn.vkGetPhysicalDeviceMemoryProperties; + vma_vulkan_functions.vkAllocateMemory = dfn.vkAllocateMemory; + vma_vulkan_functions.vkFreeMemory = dfn.vkFreeMemory; + vma_vulkan_functions.vkMapMemory = dfn.vkMapMemory; + vma_vulkan_functions.vkUnmapMemory = dfn.vkUnmapMemory; + vma_vulkan_functions.vkFlushMappedMemoryRanges = + dfn.vkFlushMappedMemoryRanges; + vma_vulkan_functions.vkInvalidateMappedMemoryRanges = + dfn.vkInvalidateMappedMemoryRanges; + vma_vulkan_functions.vkBindBufferMemory = dfn.vkBindBufferMemory; + vma_vulkan_functions.vkBindImageMemory = dfn.vkBindImageMemory; + vma_vulkan_functions.vkGetBufferMemoryRequirements = + dfn.vkGetBufferMemoryRequirements; + vma_vulkan_functions.vkGetImageMemoryRequirements = + dfn.vkGetImageMemoryRequirements; + vma_vulkan_functions.vkCreateBuffer = dfn.vkCreateBuffer; + vma_vulkan_functions.vkDestroyBuffer = dfn.vkDestroyBuffer; + vma_vulkan_functions.vkCreateImage = dfn.vkCreateImage; + vma_vulkan_functions.vkDestroyImage = dfn.vkDestroyImage; + vma_vulkan_functions.vkCmdCopyBuffer = dfn.vkCmdCopyBuffer; + if (device_extensions.khr_get_memory_requirements2) { + vma_vulkan_functions.vkGetBufferMemoryRequirements2KHR = + dfn.vkGetBufferMemoryRequirements2KHR; + vma_vulkan_functions.vkGetImageMemoryRequirements2KHR = + dfn.vkGetImageMemoryRequirements2KHR; + if (device_extensions.khr_dedicated_allocation) { + allocator_create_info.flags |= + VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; + } + } + if (device_extensions.khr_bind_memory2) { + vma_vulkan_functions.vkBindBufferMemory2KHR = dfn.vkBindBufferMemory2KHR; + vma_vulkan_functions.vkBindImageMemory2KHR = dfn.vkBindImageMemory2KHR; + allocator_create_info.flags |= VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT; + } + if (instance_extensions.khr_get_physical_device_properties2) { + vma_vulkan_functions.vkGetPhysicalDeviceMemoryProperties2KHR = + ifn.vkGetPhysicalDeviceMemoryProperties2KHR; + if (device_extensions.ext_memory_budget) { + allocator_create_info.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; + } + } + if (device_extensions.khr_maintenance4) { + vma_vulkan_functions.vkGetDeviceImageMemoryRequirements = + dfn.vkGetDeviceImageMemoryRequirementsKHR; + } + + if (externally_synchronized) { + allocator_create_info.flags |= + VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT; + } + allocator_create_info.physicalDevice = provider.physical_device(); + allocator_create_info.device = provider.device(); + allocator_create_info.pVulkanFunctions = &vma_vulkan_functions; + allocator_create_info.instance = provider.instance(); + allocator_create_info.vulkanApiVersion = + provider.device_properties().apiVersion; + VmaAllocator allocator; + if (vmaCreateAllocator(&allocator_create_info, &allocator) != VK_SUCCESS) { + XELOGE("Failed to create a Vulkan Memory Allocator instance"); + return VK_NULL_HANDLE; + } + return allocator; +} + +} // namespace vulkan +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/vulkan/vulkan_mem_alloc.h b/src/xenia/ui/vulkan/vulkan_mem_alloc.h new file mode 100644 index 000000000..9ae9db16e --- /dev/null +++ b/src/xenia/ui/vulkan/vulkan_mem_alloc.h @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_VULKAN_VULKAN_MEM_ALLOC_H_ +#define XENIA_UI_VULKAN_VULKAN_MEM_ALLOC_H_ + +// Make sure vulkan.h is included from third_party (rather than from the system +// include directory) before vk_mem_alloc.h. + +#include "xenia/ui/vulkan/vulkan_provider.h" + +#define VMA_STATIC_VULKAN_FUNCTIONS 0 +// Work around the pointer nullability completeness warnings on Clang. +#ifndef VMA_NULLABLE +#define VMA_NULLABLE +#endif +#ifndef VMA_NOT_NULL +#define VMA_NOT_NULL +#endif +#include "third_party/VulkanMemoryAllocator/include/vk_mem_alloc.h" + +namespace xe { +namespace ui { +namespace vulkan { + +VmaAllocator CreateVmaAllocator(const VulkanProvider& provider, + bool externally_synchronized); + +} // namespace vulkan +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_VULKAN_VULKAN_MEM_ALLOC_H_ \ No newline at end of file diff --git a/src/xenia/ui/vulkan/vulkan_provider.cc b/src/xenia/ui/vulkan/vulkan_provider.cc index 95c544925..a08fa7b51 100644 --- a/src/xenia/ui/vulkan/vulkan_provider.cc +++ b/src/xenia/ui/vulkan/vulkan_provider.cc @@ -700,12 +700,17 @@ bool VulkanProvider::Initialize() { } std::memset(&device_extensions_, 0, sizeof(device_extensions_)); if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { + device_extensions_.khr_bind_memory2 = true; device_extensions_.khr_dedicated_allocation = true; + device_extensions_.khr_get_memory_requirements2 = true; device_extensions_.khr_sampler_ycbcr_conversion = true; if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 2, 0)) { device_extensions_.khr_image_format_list = true; device_extensions_.khr_shader_float_controls = true; device_extensions_.khr_spirv_1_4 = true; + if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 3, 0)) { + device_extensions_.khr_maintenance4 = true; + } } } device_extensions_enabled.clear(); @@ -716,12 +721,17 @@ bool VulkanProvider::Initialize() { static const std::pair kUsedDeviceExtensions[] = { {"VK_EXT_fragment_shader_interlock", offsetof(DeviceExtensions, ext_fragment_shader_interlock)}, + {"VK_EXT_memory_budget", offsetof(DeviceExtensions, ext_memory_budget)}, {"VK_EXT_shader_stencil_export", offsetof(DeviceExtensions, ext_shader_stencil_export)}, + {"VK_KHR_bind_memory2", offsetof(DeviceExtensions, khr_bind_memory2)}, {"VK_KHR_dedicated_allocation", offsetof(DeviceExtensions, khr_dedicated_allocation)}, + {"VK_KHR_get_memory_requirements2", + offsetof(DeviceExtensions, khr_get_memory_requirements2)}, {"VK_KHR_image_format_list", offsetof(DeviceExtensions, khr_image_format_list)}, + {"VK_KHR_maintenance4", offsetof(DeviceExtensions, khr_maintenance4)}, {"VK_KHR_portability_subset", offsetof(DeviceExtensions, khr_portability_subset)}, // While vkGetPhysicalDeviceFormatProperties should be used to check the @@ -922,6 +932,48 @@ bool VulkanProvider::Initialize() { } } // Extensions - disable the specific extension if failed to get its functions. + if (device_extensions_.khr_bind_memory2) { + bool functions_loaded = true; + if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_PROMOTE +#include "xenia/ui/vulkan/functions/device_khr_bind_memory2.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } else { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#include "xenia/ui/vulkan/functions/device_khr_bind_memory2.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } + device_extensions_.khr_bind_memory2 = functions_loaded; + } + if (device_extensions_.khr_get_memory_requirements2) { + bool functions_loaded = true; + if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 1, 0)) { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_PROMOTE +#include "xenia/ui/vulkan/functions/device_khr_get_memory_requirements2.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } else { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#include "xenia/ui/vulkan/functions/device_khr_get_memory_requirements2.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } + device_extensions_.khr_get_memory_requirements2 = functions_loaded; + // VK_KHR_dedicated_allocation can still work without the dedicated + // allocation preference getter even though it requires + // VK_KHR_get_memory_requirements2 to be supported and enabled. + } + if (device_extensions_.khr_maintenance4) { + bool functions_loaded = true; + if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 3, 0)) { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_PROMOTE +#include "xenia/ui/vulkan/functions/device_khr_maintenance4.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } else { +#define XE_UI_VULKAN_FUNCTION_PROMOTED XE_UI_VULKAN_FUNCTION_DONT_PROMOTE +#include "xenia/ui/vulkan/functions/device_khr_maintenance4.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED + } + device_extensions_.khr_maintenance4 = functions_loaded; + } if (device_extensions_.khr_swapchain) { bool functions_loaded = true; #include "xenia/ui/vulkan/functions/device_khr_swapchain.inc" @@ -956,12 +1008,20 @@ bool VulkanProvider::Initialize() { XELOGVK("Vulkan device extensions:"); XELOGVK("* VK_EXT_fragment_shader_interlock: {}", device_extensions_.ext_fragment_shader_interlock ? "yes" : "no"); + XELOGVK("* VK_EXT_memory_budget: {}", + device_extensions_.ext_memory_budget ? "yes" : "no"); XELOGVK("* VK_EXT_shader_stencil_export: {}", device_extensions_.ext_shader_stencil_export ? "yes" : "no"); + XELOGVK("* VK_KHR_bind_memory2: {}", + device_extensions_.khr_bind_memory2 ? "yes" : "no"); XELOGVK("* VK_KHR_dedicated_allocation: {}", device_extensions_.khr_dedicated_allocation ? "yes" : "no"); + XELOGVK("* VK_KHR_get_memory_requirements2: {}", + device_extensions_.khr_get_memory_requirements2 ? "yes" : "no"); XELOGVK("* VK_KHR_image_format_list: {}", device_extensions_.khr_image_format_list ? "yes" : "no"); + XELOGVK("* VK_KHR_maintenance4: {}", + device_extensions_.khr_maintenance4 ? "yes" : "no"); XELOGVK("* VK_KHR_portability_subset: {}", device_extensions_.khr_portability_subset ? "yes" : "no"); if (device_extensions_.khr_portability_subset) { diff --git a/src/xenia/ui/vulkan/vulkan_provider.h b/src/xenia/ui/vulkan/vulkan_provider.h index 0680b5766..8dc83283c 100644 --- a/src/xenia/ui/vulkan/vulkan_provider.h +++ b/src/xenia/ui/vulkan/vulkan_provider.h @@ -132,11 +132,18 @@ class VulkanProvider : public GraphicsProvider { } struct DeviceExtensions { bool ext_fragment_shader_interlock; + bool ext_memory_budget; bool ext_shader_stencil_export; // Core since 1.1.0. + bool khr_bind_memory2; + // Core since 1.1.0. bool khr_dedicated_allocation; + // Core since 1.1.0. + bool khr_get_memory_requirements2; // Core since 1.2.0. bool khr_image_format_list; + // Core since 1.3.0. + bool khr_maintenance4; // Requires the VK_KHR_get_physical_device_properties2 instance extension. bool khr_portability_subset; // Core since 1.1.0. @@ -217,8 +224,14 @@ class VulkanProvider : public GraphicsProvider { VkDevice device() const { return device_; } struct DeviceFunctions { #define XE_UI_VULKAN_FUNCTION(name) PFN_##name name; +#define XE_UI_VULKAN_FUNCTION_PROMOTED(extension_name, core_name) \ + PFN_##extension_name extension_name; #include "xenia/ui/vulkan/functions/device_1_0.inc" +#include "xenia/ui/vulkan/functions/device_khr_bind_memory2.inc" +#include "xenia/ui/vulkan/functions/device_khr_get_memory_requirements2.inc" +#include "xenia/ui/vulkan/functions/device_khr_maintenance4.inc" #include "xenia/ui/vulkan/functions/device_khr_swapchain.inc" +#undef XE_UI_VULKAN_FUNCTION_PROMOTED #undef XE_UI_VULKAN_FUNCTION }; const DeviceFunctions& dfn() const { return dfn_; } diff --git a/third_party/VulkanMemoryAllocator b/third_party/VulkanMemoryAllocator new file mode 160000 index 000000000..51c8b5601 --- /dev/null +++ b/third_party/VulkanMemoryAllocator @@ -0,0 +1 @@ +Subproject commit 51c8b56011303e94840370089f816b19dbe7edf0