[Vulkan] VMA for textures
This commit is contained in:
parent
636585e0aa
commit
001f64852c
|
@ -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
|
||||
|
|
|
@ -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<TextureCache::Texture> 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<Texture>(
|
||||
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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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 <cstring>
|
||||
|
||||
#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
|
|
@ -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_
|
|
@ -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<const char*, size_t> 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) {
|
||||
|
|
|
@ -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_; }
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 51c8b56011303e94840370089f816b19dbe7edf0
|
Loading…
Reference in New Issue