[vulkan] bump to vk 1.4 and some features to 1.4 tree

This commit is contained in:
CamilleLaVey 2026-02-14 03:28:00 -04:00
parent 3aa4fb867c
commit 59444d5c48
5 changed files with 91 additions and 27 deletions

View File

@ -112,12 +112,15 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([&](vk::CommandBuffer cmdbuf) {
TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
const VkImageLayout transfer_dst_layout = device.IsKhrUnifiedImageLayoutsSupported()
? VK_IMAGE_LAYOUT_GENERAL
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
TransitionImageLayout(cmdbuf, *image, transfer_dst_layout,
VK_IMAGE_LAYOUT_UNDEFINED);
cmdbuf.CopyBufferToImage(*upload_buffer, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
cmdbuf.CopyBufferToImage(*upload_buffer, *image, transfer_dst_layout,
regions);
TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
transfer_dst_layout);
});
scheduler.Finish();
}

View File

@ -536,6 +536,7 @@ struct RangedBarrierRange {
};
void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage image,
VkImageAspectFlags aspect_mask, bool is_initialized,
bool use_unified_layouts,
std::span<const VkBufferImageCopy> copies) {
static constexpr VkAccessFlags WRITE_ACCESS_FLAGS =
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
@ -550,6 +551,8 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
range.AddLayers(region.imageSubresource);
}
const VkImageSubresourceRange subresource_range = range.SubresourceRange(aspect_mask);
const VkImageLayout transfer_dst_layout =
use_unified_layouts ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
const VkImageMemoryBarrier read_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -557,7 +560,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
.srcAccessMask = WRITE_ACCESS_FLAGS,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = transfer_dst_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
@ -569,7 +572,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = WRITE_ACCESS_FLAGS | READ_ACCESS_FLAGS,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.oldLayout = transfer_dst_layout,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@ -581,7 +584,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
read_barrier);
cmdbuf.CopyBufferToImage(src_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copies);
cmdbuf.CopyBufferToImage(src_buffer, image, transfer_dst_layout, copies);
// TODO: Move this to another API
cmdbuf.PipelineBarrier(
VK_PIPELINE_STAGE_TRANSFER_BIT,
@ -703,7 +706,7 @@ void TryTransformSwizzleIfNeeded(PixelFormat format, std::array<SwizzleSource, 4
void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info,
VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution,
bool up_scaling = true) {
bool use_unified_layouts, bool up_scaling = true) {
const bool is_2d = info.type == ImageType::e2D;
const auto resources = info.resources;
const VkExtent2D extent{
@ -777,6 +780,10 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
};
const VkImageLayout transfer_src_layout =
use_unified_layouts ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
const VkImageLayout transfer_dst_layout =
use_unified_layouts ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
const std::array read_barriers{
VkImageMemoryBarrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -784,7 +791,7 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = transfer_src_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = src_image,
@ -798,7 +805,7 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, // Discard contents
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = transfer_dst_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = dst_image,
@ -812,7 +819,7 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.oldLayout = transfer_src_layout,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@ -825,7 +832,7 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.oldLayout = transfer_dst_layout,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@ -843,8 +850,8 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
VK_PIPELINE_STAGE_TRANSFER_BIT;
cmdbuf.PipelineBarrier(src_stages, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, nullptr, nullptr, read_barriers);
cmdbuf.BlitImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions, vk_filter);
cmdbuf.BlitImage(src_image, transfer_src_layout, dst_image,
transfer_dst_layout, regions, vk_filter);
// After transfer, images may be used in graphics, compute, or as attachments
const VkPipelineStageFlags dst_stages =
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
@ -1743,9 +1750,11 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset,
const VkImage temp_vk_image = *temp_wrapper->original_image;
const VkImageAspectFlags vk_aspect_mask = temp_wrapper->aspect_mask;
scheduler->Record([src_buffer, temp_vk_image, vk_aspect_mask, vk_copies,
const bool use_unified_layouts = runtime->device.IsKhrUnifiedImageLayoutsSupported();
scheduler->Record([src_buffer, temp_vk_image, vk_aspect_mask, vk_copies, use_unified_layouts,
keep = temp_wrapper](vk::CommandBuffer cmdbuf) {
CopyBufferToImage(cmdbuf, src_buffer, temp_vk_image, vk_aspect_mask, false, VideoCommon::FixSmallVectorADL(vk_copies));
CopyBufferToImage(cmdbuf, src_buffer, temp_vk_image, vk_aspect_mask, false,
use_unified_layouts, VideoCommon::FixSmallVectorADL(vk_copies));
});
// Use MSAACopyPass to convert from non-MSAA to MSAA
@ -1782,9 +1791,11 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset,
const VkImageAspectFlags vk_aspect_mask = aspect_mask;
const bool was_initialized = std::exchange(initialized, true);
const bool use_unified_layouts = runtime->device.IsKhrUnifiedImageLayoutsSupported();
scheduler->Record([src_buffer, vk_image, vk_aspect_mask, was_initialized,
vk_copies](vk::CommandBuffer cmdbuf) {
CopyBufferToImage(cmdbuf, src_buffer, vk_image, vk_aspect_mask, was_initialized, VideoCommon::FixSmallVectorADL(vk_copies));
vk_copies, use_unified_layouts](vk::CommandBuffer cmdbuf) {
CopyBufferToImage(cmdbuf, src_buffer, vk_image, vk_aspect_mask, was_initialized,
use_unified_layouts, VideoCommon::FixSmallVectorADL(vk_copies));
});
if (is_rescaled) {
@ -2071,7 +2082,8 @@ bool Image::ScaleUp(bool ignore) {
if (NeedsScaleHelper()) {
return BlitScaleHelper(true);
} else {
BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution);
BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution,
runtime->device.IsKhrUnifiedImageLayoutsSupported());
}
return true;
}
@ -2096,7 +2108,8 @@ bool Image::ScaleDown(bool ignore) {
if (NeedsScaleHelper()) {
return BlitScaleHelper(false);
} else {
BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false);
BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution,
runtime->device.IsKhrUnifiedImageLayoutsSupported(), false);
}
return true;
}

View File

@ -941,6 +941,9 @@ bool Device::GetSuitability(bool requires_swapchain) {
VkPhysicalDeviceVulkan12Features features_1_2{};
VkPhysicalDeviceVulkan13Features features_1_3{};
#ifdef VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES
VkPhysicalDeviceVulkan14Features features_1_4{};
#endif
// Configure properties.
properties.properties = physical.GetProperties();
@ -980,6 +983,11 @@ bool Device::GetSuitability(bool requires_swapchain) {
if (instance_version < VK_API_VERSION_1_3) {
FOR_EACH_VK_FEATURE_1_3(FEATURE_EXTENSION);
}
#ifdef VK_API_VERSION_1_4
if (instance_version < VK_API_VERSION_1_4) {
FOR_EACH_VK_FEATURE_1_4(FEATURE_EXTENSION);
}
#endif
FOR_EACH_VK_FEATURE_EXT(FEATURE_EXTENSION);
FOR_EACH_VK_EXTENSION(EXTENSION);
@ -1015,11 +1023,16 @@ bool Device::GetSuitability(bool requires_swapchain) {
// Set next pointer.
void** next = &features2.pNext;
// Vulkan 1.2 and 1.3 features
// Vulkan 1.2, 1.3 and 1.4 features
if (instance_version >= VK_API_VERSION_1_2) {
features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
#ifdef VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES
features_1_4.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES;
features_1_3.pNext = &features_1_4;
#endif
features_1_2.pNext = &features_1_3;
*next = &features_1_2;
@ -1051,6 +1064,13 @@ bool Device::GetSuitability(bool requires_swapchain) {
} else {
FOR_EACH_VK_FEATURE_1_3(EXT_FEATURE);
}
#ifdef VK_API_VERSION_1_4
if (instance_version >= VK_API_VERSION_1_4) {
FOR_EACH_VK_FEATURE_1_4(FEATURE);
} else {
FOR_EACH_VK_FEATURE_1_4(EXT_FEATURE);
}
#endif
#undef EXT_FEATURE
#undef FEATURE
@ -1488,16 +1508,31 @@ void Device::RemoveUnsuitableExtensions() {
RemoveExtensionFeatureIfUnsuitable(extensions.maintenance6, features.maintenance6,
VK_KHR_MAINTENANCE_6_EXTENSION_NAME);
// VK_KHR_maintenance7 (proposed for Vulkan 1.4, no features)
// VK_KHR_maintenance7
#ifdef VK_API_VERSION_1_4
extensions.maintenance7 = instance_version >= VK_API_VERSION_1_4 ||
loaded_extensions.contains(VK_KHR_MAINTENANCE_7_EXTENSION_NAME);
#else
extensions.maintenance7 = loaded_extensions.contains(VK_KHR_MAINTENANCE_7_EXTENSION_NAME);
#endif
RemoveExtensionIfUnsuitable(extensions.maintenance7, VK_KHR_MAINTENANCE_7_EXTENSION_NAME);
// VK_KHR_maintenance8 (proposed for Vulkan 1.4, no features)
// VK_KHR_maintenance8
#ifdef VK_API_VERSION_1_4
extensions.maintenance8 = instance_version >= VK_API_VERSION_1_4 ||
loaded_extensions.contains(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
#else
extensions.maintenance8 = loaded_extensions.contains(VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
#endif
RemoveExtensionIfUnsuitable(extensions.maintenance8, VK_KHR_MAINTENANCE_8_EXTENSION_NAME);
// VK_KHR_maintenance9 (proposed for Vulkan 1.4, no features)
// VK_KHR_maintenance9
#ifdef VK_API_VERSION_1_4
extensions.maintenance9 = instance_version >= VK_API_VERSION_1_4 ||
loaded_extensions.contains(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
#else
extensions.maintenance9 = loaded_extensions.contains(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
#endif
RemoveExtensionIfUnsuitable(extensions.maintenance9, VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
}

View File

@ -487,6 +487,11 @@ public:
return extensions.workgroup_memory_explicit_layout;
}
/// Returns true if the device supports VK_KHR_unified_image_layouts.
bool IsKhrUnifiedImageLayoutsSupported() const {
return extensions.unified_image_layouts;
}
/// Returns true if the device supports VK_KHR_image_format_list.
bool IsKhrImageFormatListSupported() const {
return extensions.image_format_list || instance_version >= VK_API_VERSION_1_2;

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@ -47,6 +47,14 @@ bool IsMicrosoftDozen(const char* device_name) {
return std::strstr(device_name, "Microsoft") != nullptr;
}
constexpr u32 MaxInstanceApiVersion() {
#ifdef VK_API_VERSION_1_4
return VK_API_VERSION_1_4;
#else
return VK_API_VERSION_1_3;
#endif
}
void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) {
// Sort by name, this will set a base and make GPUs with higher numbers appear first
// (e.g. GTX 1650 will intentionally be listed before a GTX 1080).
@ -437,8 +445,8 @@ Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char
#else
constexpr VkFlags ci_flags{};
#endif
// DO NOT TOUCH, breaks RNDA3!!
// Don't know why, but gloom + yellow line glitch appears
// Keep application and engine tags stable for driver behavior compatibility.
const u32 api_version = std::min(version, MaxInstanceApiVersion());
const VkApplicationInfo application_info{
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
@ -446,7 +454,7 @@ Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char
.applicationVersion = VK_MAKE_VERSION(1, 3, 0),
.pEngineName = "yuzu Emulator",
.engineVersion = VK_MAKE_VERSION(1, 3, 0),
.apiVersion = VK_API_VERSION_1_3,
.apiVersion = api_version,
};
const VkInstanceCreateInfo ci{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,