GS:VK: Formatting

This commit is contained in:
TellowKrinkle
2026-10-11 19:59:12 +02:00
committed by lightningterror
parent c53b0c9c92
commit b18c0007a4
2 changed files with 333 additions and 325 deletions
+250 -271
View File
@@ -126,12 +126,12 @@ static VkAttachmentLoadOp GetLoadOpForTexture(GSTextureVK* tex)
// clang-format off
switch (tex->GetState())
{
case GSTextureVK::State::Cleared: tex->SetState(GSTexture::State::Dirty); return VK_ATTACHMENT_LOAD_OP_CLEAR;
case GSTextureVK::State::Invalidated: tex->SetState(GSTexture::State::Dirty); return VK_ATTACHMENT_LOAD_OP_DONT_CARE;
case GSTextureVK::State::Dirty: return VK_ATTACHMENT_LOAD_OP_LOAD;
default: return VK_ATTACHMENT_LOAD_OP_LOAD;
case GSTextureVK::State::Cleared: tex->SetState(GSTexture::State::Dirty); return VK_ATTACHMENT_LOAD_OP_CLEAR;
case GSTextureVK::State::Invalidated: tex->SetState(GSTexture::State::Dirty); return VK_ATTACHMENT_LOAD_OP_DONT_CARE;
case GSTextureVK::State::Dirty: return VK_ATTACHMENT_LOAD_OP_LOAD;
}
// clang-format on
return VK_ATTACHMENT_LOAD_OP_LOAD;
}
static constexpr VkClearValue s_present_clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
@@ -162,26 +162,18 @@ VkInstance GSDeviceVK::CreateVulkanInstance(const WindowInfo& wi, OptionalExtens
if (!SelectInstanceExtensions(&enabled_extensions, wi, oe, enable_debug_utils))
return VK_NULL_HANDLE;
VkApplicationInfo app_info = {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pNext = nullptr;
uint32_t version = VK_MAKE_VERSION(BuildVersion::GitTagHi, BuildVersion::GitTagMid, BuildVersion::GitTagLo);
VkApplicationInfo app_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
app_info.pApplicationName = "PCSX2";
app_info.applicationVersion = VK_MAKE_VERSION(
BuildVersion::GitTagHi, BuildVersion::GitTagMid, BuildVersion::GitTagLo);
app_info.applicationVersion = version;
app_info.pEngineName = "PCSX2";
app_info.engineVersion = VK_MAKE_VERSION(
BuildVersion::GitTagHi, BuildVersion::GitTagMid, BuildVersion::GitTagLo);
app_info.engineVersion = version;
app_info.apiVersion = VK_API_VERSION_1_1;
VkInstanceCreateInfo instance_create_info = {};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.pNext = nullptr;
instance_create_info.flags = 0;
VkInstanceCreateInfo instance_create_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
instance_create_info.pApplicationInfo = &app_info;
instance_create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
instance_create_info.ppEnabledExtensionNames = enabled_extensions.data();
instance_create_info.enabledLayerCount = 0;
instance_create_info.ppEnabledLayerNames = nullptr;
// Enable debug layer on debug builds
if (enable_validation_layer)
@@ -224,10 +216,10 @@ bool GSDeviceVK::SelectInstanceExtensions(ExtensionList* extension_list, const W
pxAssert(res == VK_SUCCESS);
auto SupportsExtension = [&available_extension_list, extension_list](const char* name, bool required) {
if (std::find_if(available_extension_list.begin(), available_extension_list.end(),
[name](const VkExtensionProperties& properties) { return !strcmp(name, properties.extensionName); }) !=
available_extension_list.end())
for (const VkExtensionProperties& properties : available_extension_list)
{
if (0 != strcmp(name, properties.extensionName))
continue;
DevCon.WriteLn("VK: Enabling extension: %s", name);
extension_list->push_back(name);
return true;
@@ -319,8 +311,7 @@ GSDeviceVK::GPUList GSDeviceVK::EnumerateGPUs(VkInstance instance)
vkGetPhysicalDeviceProperties(device, &props);
// Skip GPUs which don't support Vulkan 1.1, since we won't be able to create a device with them anyway.
if (VK_API_VERSION_VARIANT(props.apiVersion) == 0 && VK_API_VERSION_MAJOR(props.apiVersion) <= 1 &&
VK_API_VERSION_MINOR(props.apiVersion) < 1)
if (props.apiVersion < VK_API_VERSION_1_1)
{
Console.Warning(fmt::format("VK: Ignoring GPU '{}' because it only claims support for Vulkan {}.{}.{}",
props.deviceName, VK_API_VERSION_MAJOR(props.apiVersion), VK_API_VERSION_MINOR(props.apiVersion),
@@ -365,8 +356,7 @@ GSDeviceVK::GPUList GSDeviceVK::EnumerateGPUs(VkInstance instance)
ai.max_upscale_multiplier = GSGetMaxUpscaleMultiplier(ai.max_texture_size);
// handle duplicate adapter names
if (std::any_of(
gpus.begin(), gpus.end(), [&ai](const auto& other) { return (ai.name == other.second.name); }))
if (std::any_of(gpus.begin(), gpus.end(), [&ai](const auto& other) { return (ai.name == other.second.name); }))
{
std::string original_adapter_name = std::move(ai.name);
@@ -375,8 +365,7 @@ GSDeviceVK::GPUList GSDeviceVK::EnumerateGPUs(VkInstance instance)
{
ai.name = fmt::format("{} ({})", original_adapter_name, current_extra);
current_extra++;
} while (std::any_of(
gpus.begin(), gpus.end(), [&ai](const auto& other) { return (ai.name == other.second.name); }));
} while (std::any_of(gpus.begin(), gpus.end(), [&ai](const auto& other) { return (ai.name == other.second.name); }));
}
gpus.emplace_back(device, std::move(ai));
@@ -438,10 +427,10 @@ bool GSDeviceVK::SelectDeviceExtensions(ExtensionList* extension_list, bool enab
pxAssert(res == VK_SUCCESS);
auto SupportsExtension = [&available_extension_list, extension_list](const char* name, bool required) {
if (std::find_if(available_extension_list.begin(), available_extension_list.end(),
[name](const VkExtensionProperties& properties) { return !strcmp(name, properties.extensionName); }) !=
available_extension_list.end())
for (const VkExtensionProperties& properties : available_extension_list)
{
if (0 != strcmp(name, properties.extensionName))
continue;
if (std::none_of(extension_list->begin(), extension_list->end(),
[name](const char* existing_name) { return (std::strcmp(existing_name, name) == 0); }))
{
@@ -491,7 +480,7 @@ bool GSDeviceVK::SelectDeviceExtensions(ExtensionList* extension_list, bool enab
const bool khr_swapchain_maintenance1 = SupportsExtension(VK_KHR_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, false);
// vk_swapchain_maintenance1_is_khr will be set if we havn't enabled VK_EXT_surface_maintenance1
// This will happen if either the VK_EXT_surface_maintenance1 was unsupported, or we instead found the KHR version.
// As the EXT version depends on the surface maintenance1 extension, we need to check that aswell.
// As the EXT version depends on the surface maintenance1 extension, we need to check that as well.
m_optional_extensions.vk_swapchain_maintenance1 = khr_swapchain_maintenance1 ? khr_swapchain_maintenance1 :
(!m_optional_extensions.vk_swapchain_maintenance1_is_khr && SupportsExtension(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, false));
@@ -610,28 +599,18 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
return false;
}
VkDeviceCreateInfo device_info = {};
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_info.pNext = nullptr;
device_info.flags = 0;
device_info.queueCreateInfoCount = 0;
VkDeviceCreateInfo device_info = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
static constexpr float queue_priorities[] = {1.0f, 0.0f}; // Low priority for the spin queue
std::array<VkDeviceQueueCreateInfo, 3> queue_infos;
VkDeviceQueueCreateInfo& graphics_queue_info = queue_infos[device_info.queueCreateInfoCount++];
graphics_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
graphics_queue_info.pNext = nullptr;
graphics_queue_info.flags = 0;
VkDeviceQueueCreateInfo& graphics_queue_info = queue_infos[device_info.queueCreateInfoCount++] = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
graphics_queue_info.queueFamilyIndex = m_graphics_queue_family_index;
graphics_queue_info.queueCount = 1;
graphics_queue_info.pQueuePriorities = queue_priorities;
if (surface != VK_NULL_HANDLE && m_graphics_queue_family_index != m_present_queue_family_index)
{
VkDeviceQueueCreateInfo& present_queue_info = queue_infos[device_info.queueCreateInfoCount++];
present_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
present_queue_info.pNext = nullptr;
present_queue_info.flags = 0;
VkDeviceQueueCreateInfo& present_queue_info = queue_infos[device_info.queueCreateInfoCount++] = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
present_queue_info.queueFamilyIndex = m_present_queue_family_index;
present_queue_info.queueCount = 1;
present_queue_info.pQueuePriorities = queue_priorities;
@@ -649,10 +628,7 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
}
else if (m_spin_queue_family_index != queue_family_count)
{
VkDeviceQueueCreateInfo& spin_queue_info = queue_infos[device_info.queueCreateInfoCount++];
spin_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
spin_queue_info.pNext = nullptr;
spin_queue_info.flags = 0;
VkDeviceQueueCreateInfo& spin_queue_info = queue_infos[device_info.queueCreateInfoCount++] = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
spin_queue_info.queueFamilyIndex = m_spin_queue_family_index;
spin_queue_info.queueCount = 1;
spin_queue_info.pQueuePriorities = queue_priorities + 1;
@@ -681,22 +657,15 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
device_info.ppEnabledLayerNames = layer_names;
}
VkPhysicalDeviceSynchronization2Features sync2_features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES};
VkPhysicalDeviceSynchronization2Features sync2_features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES};
// provoking vertex
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT attachment_feedback_loop_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT};
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT attachment_feedback_loop_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT};
// VK_EXT_swapchain_maintenance1 types/enums are aliases of VK_KHR_swapchain_maintenance1 types/enums.
VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR};
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT fragment_shader_interlock_ext_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT};
VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR};
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT fragment_shader_interlock_ext_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT};
if (m_optional_extensions.vk_khr_synchronization2)
{
@@ -757,9 +726,9 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
m_spin_queue_is_graphics_queue =
m_spin_queue_family_index == m_graphics_queue_family_index && spin_queue_index == 0;
m_gpu_timing_supported = (m_device_properties.limits.timestampComputeAndGraphics != 0 &&
queue_family_properties[m_graphics_queue_family_index].timestampValidBits > 0 &&
m_device_properties.limits.timestampPeriod > 0);
m_gpu_timing_supported = m_device_properties.limits.timestampComputeAndGraphics != 0 &&
queue_family_properties[m_graphics_queue_family_index].timestampValidBits > 0 &&
m_device_properties.limits.timestampPeriod > 0;
DevCon.WriteLn("GPU timing is %s (TS=%u TS valid bits=%u, TS period=%f)",
m_gpu_timing_supported ? "supported" : "not supported",
static_cast<u32>(m_device_properties.limits.timestampComputeAndGraphics),
@@ -801,21 +770,14 @@ bool GSDeviceVK::ProcessDeviceExtensions()
{
// advanced feature checks
VkPhysicalDeviceFeatures2 features2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
VkPhysicalDeviceSynchronization2Features sync2_features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES};
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
VkPhysicalDeviceSynchronization2Features sync2_features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES};
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
// VK_EXT_swapchain_maintenance1 types/enums are aliases of VK_KHR_swapchain_maintenance1 types/enums.
VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR, nullptr, VK_TRUE};
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT attachment_feedback_loop_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT};
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT fragment_shader_interlock_ext_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT };
VkPhysicalDeviceSwapchainMaintenance1FeaturesKHR swapchain_maintenance1_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_KHR};
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT attachment_feedback_loop_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT};
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT fragment_shader_interlock_ext_feature = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT};
// add in optional feature structs
if (m_optional_extensions.vk_khr_synchronization2)
@@ -837,12 +799,10 @@ bool GSDeviceVK::ProcessDeviceExtensions()
vkGetPhysicalDeviceFeatures2(m_physical_device, &features2);
// confirm we actually support it
m_optional_extensions.vk_khr_synchronization2 &= (sync2_features.synchronization2 == VK_TRUE);
m_optional_extensions.vk_ext_provoking_vertex &= (provoking_vertex_features.provokingVertexLast == VK_TRUE);
m_optional_extensions.vk_ext_rasterization_order_attachment_access &=
(rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
m_optional_extensions.vk_ext_attachment_feedback_loop_layout &=
(attachment_feedback_loop_feature.attachmentFeedbackLoopLayout == VK_TRUE);
m_optional_extensions.vk_khr_synchronization2 &= !!sync2_features.synchronization2;
m_optional_extensions.vk_ext_provoking_vertex &= !!provoking_vertex_features.provokingVertexLast;
m_optional_extensions.vk_ext_rasterization_order_attachment_access &= !!rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess;
m_optional_extensions.vk_ext_attachment_feedback_loop_layout &= !!attachment_feedback_loop_feature.attachmentFeedbackLoopLayout;
VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
@@ -852,8 +812,7 @@ bool GSDeviceVK::ProcessDeviceExtensions()
Vulkan::AddPointerToChain(&properties2, &m_device_driver_properties);
}
VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor_properties = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR};
VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor_properties = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR};
Vulkan::AddPointerToChain(&properties2, &push_descriptor_properties);
// query
@@ -907,11 +866,8 @@ bool GSDeviceVK::ProcessDeviceExtensions()
m_optional_extensions.vk_ext_calibrated_timestamps = false;
}
m_optional_extensions.vk_swapchain_maintenance1 &=
(swapchain_maintenance1_feature.swapchainMaintenance1 == VK_TRUE);
m_optional_extensions.vk_ext_fragment_shader_interlock &=
(fragment_shader_interlock_ext_feature.fragmentShaderPixelInterlock == VK_TRUE);
m_optional_extensions.vk_swapchain_maintenance1 &= !!swapchain_maintenance1_feature.swapchainMaintenance1;
m_optional_extensions.vk_ext_fragment_shader_interlock &= !!fragment_shader_interlock_ext_feature.fragmentShaderPixelInterlock;
Console.WriteLn("VK_%s_swapchain_maintenance1 is %s",
m_optional_extensions.vk_swapchain_maintenance1_is_khr ? "KHR" : "EXT",
@@ -1009,8 +965,8 @@ bool GSDeviceVK::CreateCommandBuffers()
{
resources.needs_fence_wait = false;
VkCommandPoolCreateInfo pool_info = {
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, m_graphics_queue_family_index};
VkCommandPoolCreateInfo pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
pool_info.queueFamilyIndex = m_graphics_queue_family_index;
res = vkCreateCommandPool(m_device, &pool_info, nullptr, &resources.command_pool);
if (res != VK_SUCCESS)
{
@@ -1019,9 +975,10 @@ bool GSDeviceVK::CreateCommandBuffers()
}
Vulkan::SetObjectName(m_device, resources.command_pool, "Frame Command Pool %u", frame_index);
VkCommandBufferAllocateInfo buffer_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr,
resources.command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
static_cast<u32>(resources.command_buffers.size())};
VkCommandBufferAllocateInfo buffer_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
buffer_info.commandPool = resources.command_pool;
buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
buffer_info.commandBufferCount = static_cast<u32>(resources.command_buffers.size());
res = vkAllocateCommandBuffers(m_device, &buffer_info, resources.command_buffers.data());
if (res != VK_SUCCESS)
@@ -1035,7 +992,8 @@ bool GSDeviceVK::CreateCommandBuffers()
(i == 0) ? "Init" : "");
}
VkFenceCreateInfo fence_info = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, VK_FENCE_CREATE_SIGNALED_BIT};
VkFenceCreateInfo fence_info = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
res = vkCreateFence(m_device, &fence_info, nullptr, &resources.fence);
if (res != VK_SUCCESS)
@@ -1058,10 +1016,11 @@ bool GSDeviceVK::CreateGlobalDescriptorPool()
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3},
};
VkDescriptorPoolCreateInfo pool_create_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, nullptr,
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1024, // TODO: tweak this
static_cast<u32>(std::size(pool_sizes)), pool_sizes};
VkDescriptorPoolCreateInfo pool_create_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_create_info.maxSets = 1024; // TODO: tweak this
pool_create_info.poolSizeCount = std::size(pool_sizes);
pool_create_info.pPoolSizes = pool_sizes;
VkResult res = vkCreateDescriptorPool(m_device, &pool_create_info, nullptr, &m_global_descriptor_pool);
if (res != VK_SUCCESS)
@@ -1073,8 +1032,9 @@ bool GSDeviceVK::CreateGlobalDescriptorPool()
if (m_gpu_timing_supported)
{
const VkQueryPoolCreateInfo query_create_info = {
VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, nullptr, 0, VK_QUERY_TYPE_TIMESTAMP, NUM_COMMAND_BUFFERS * 4, 0};
VkQueryPoolCreateInfo query_create_info = {VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO};
query_create_info.queryType = VK_QUERY_TYPE_TIMESTAMP;
query_create_info.queryCount = NUM_COMMAND_BUFFERS * 4;
res = vkCreateQueryPool(m_device, &query_create_info, nullptr, &m_timestamp_query_pool);
if (res != VK_SUCCESS)
{
@@ -1086,9 +1046,11 @@ bool GSDeviceVK::CreateGlobalDescriptorPool()
if (m_gpu_pipeline_statistics_supported)
{
const VkQueryPoolCreateInfo query_create_info = {
VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, nullptr, 0, VK_QUERY_TYPE_PIPELINE_STATISTICS, NUM_COMMAND_BUFFERS,
VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT };
VkQueryPoolCreateInfo query_create_info = {VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO};
query_create_info.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS;
query_create_info.queryCount = NUM_COMMAND_BUFFERS;
query_create_info.pipelineStatistics = VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT
| VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT;
res = vkCreateQueryPool(m_device, &query_create_info, nullptr, &m_pipeline_statistics_query_pool);
if (res != VK_SUCCESS)
{
@@ -1101,10 +1063,11 @@ bool GSDeviceVK::CreateGlobalDescriptorPool()
return true;
}
VkRenderPass GSDeviceVK::GetRenderPass(VkFormat color_format, VkFormat depth_format, VkAttachmentLoadOp color_load_op,
VkAttachmentStoreOp color_store_op, VkAttachmentLoadOp depth_load_op, VkAttachmentStoreOp depth_store_op,
VkAttachmentLoadOp stencil_load_op, VkAttachmentStoreOp stencil_store_op, bool color_feedback_loop,
bool depth_sampling)
VkRenderPass GSDeviceVK::GetRenderPass(VkFormat color_format, VkFormat depth_format,
VkAttachmentLoadOp color_load_op, VkAttachmentStoreOp color_store_op,
VkAttachmentLoadOp depth_load_op, VkAttachmentStoreOp depth_store_op,
VkAttachmentLoadOp stencil_load_op, VkAttachmentStoreOp stencil_store_op,
bool color_feedback_loop, bool depth_sampling)
{
RenderPassCacheKey key = {};
key.color_format = color_format;
@@ -1161,8 +1124,8 @@ VkCommandBuffer GSDeviceVK::GetCurrentInitCommandBuffer()
if (res.init_buffer_used)
return buf;
VkCommandBufferBeginInfo bi{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
VkCommandBufferBeginInfo bi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(buf, &bi);
res.init_buffer_used = true;
return buf;
@@ -1170,8 +1133,10 @@ VkCommandBuffer GSDeviceVK::GetCurrentInitCommandBuffer()
VkDescriptorSet GSDeviceVK::AllocatePersistentDescriptorSet(VkDescriptorSetLayout set_layout)
{
VkDescriptorSetAllocateInfo allocate_info = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr, m_global_descriptor_pool, 1, &set_layout};
VkDescriptorSetAllocateInfo allocate_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO};
allocate_info.descriptorPool = m_global_descriptor_pool;
allocate_info.descriptorSetCount = 1;
allocate_info.pSetLayouts = &set_layout;
VkDescriptorSet descriptor_set;
VkResult res = vkAllocateDescriptorSets(m_device, &allocate_info, &descriptor_set);
@@ -1326,7 +1291,7 @@ void GSDeviceVK::ScanForCommandBufferCompletion()
continue;
if (vkGetFenceStatus(m_device, resources.fence) != VK_SUCCESS)
continue;
SpinCommandCompleted(&resources - &m_spin_resources[0]);
SpinCommandCompleted(static_cast<u32>(&resources - &m_spin_resources[0]));
}
}
@@ -1478,9 +1443,12 @@ void GSDeviceVK::SubmitCommandBuffer(VKSwapChain* present_swap_chain)
if (present_swap_chain)
{
const VkPresentInfoKHR present_info = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, nullptr, 1,
present_swap_chain->GetRenderingFinishedSemaphorePtr(), 1, present_swap_chain->GetSwapChainPtr(),
present_swap_chain->GetCurrentImageIndexPtr(), nullptr};
VkPresentInfoKHR present_info = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR};
present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores = present_swap_chain->GetRenderingFinishedSemaphorePtr();
present_info.swapchainCount = 1;
present_info.pSwapchains = present_swap_chain->GetSwapChainPtr();
present_info.pImageIndices = present_swap_chain->GetCurrentImageIndexPtr();
present_swap_chain->ResetImageAcquireResult();
@@ -1678,13 +1646,14 @@ bool GSDeviceVK::EnableDebugUtils()
return false;
}
VkDebugUtilsMessengerCreateInfoEXT messenger_info = {VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
nullptr, 0,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
DebugMessengerCallback, nullptr};
VkDebugUtilsMessengerCreateInfoEXT messenger_info = {VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
messenger_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
messenger_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
messenger_info.pfnUserCallback = DebugMessengerCallback;
const VkResult res =
vkCreateDebugUtilsMessengerEXT(m_instance, &messenger_info, nullptr, &m_debug_messenger_callback);
@@ -1714,19 +1683,22 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
VkAttachmentReference* depth_reference_ptr = nullptr;
std::array<VkAttachmentReference, 2> input_reference;
u32 num_subpass_inputs = 0;
std::array<VkSubpassDependency, 2> subpass_dependency;
std::array<VkSubpassDependency, 2> subpass_dependencies;
u32 num_subpass_dependencies = 0;
std::array<VkAttachmentDescription, 2> attachments;
u32 num_attachments = 0;
if (key.color_format != VK_FORMAT_UNDEFINED)
{
const VkImageLayout layout =
key.color_feedback_loop ? (UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
VK_IMAGE_LAYOUT_GENERAL) :
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments[num_attachments] = {0, static_cast<VkFormat>(key.color_format), VK_SAMPLE_COUNT_1_BIT,
static_cast<VkAttachmentLoadOp>(key.color_load_op), static_cast<VkAttachmentStoreOp>(key.color_store_op),
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, layout, layout};
const VkImageLayout layout = key.color_feedback_loop ? GetFeedbackLoopLayout() : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentDescription& attachment = attachments[num_attachments] = {};
attachment.format = static_cast<VkFormat>(key.color_format);
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
attachment.loadOp = static_cast<VkAttachmentLoadOp>(key.color_load_op);
attachment.storeOp = static_cast<VkAttachmentStoreOp>(key.color_store_op);
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment.initialLayout = layout;
attachment.finalLayout = layout;
color_reference.attachment = num_attachments;
color_reference.layout = layout;
color_reference_ptr = &color_reference;
@@ -1743,15 +1715,14 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
if (!m_features.framebuffer_fetch)
{
// don't need the framebuffer-local dependency when we have rasterization order attachment access
subpass_dependency[num_subpass_dependencies].srcSubpass = 0;
subpass_dependency[num_subpass_dependencies].dstSubpass = 0;
subpass_dependency[num_subpass_dependencies].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpass_dependency[num_subpass_dependencies].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpass_dependency[num_subpass_dependencies].srcAccessMask =
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpass_dependency[num_subpass_dependencies].dstAccessMask = static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags());
subpass_dependency[num_subpass_dependencies].dependencyFlags = GetFeedbackBarrierDependencyFlags();
num_subpass_dependencies++;
VkSubpassDependency& subpass_dependency = subpass_dependencies[num_subpass_dependencies++];
subpass_dependency.srcSubpass = 0;
subpass_dependency.dstSubpass = 0;
subpass_dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpass_dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpass_dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpass_dependency.dstAccessMask = static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags());
subpass_dependency.dependencyFlags = GetFeedbackBarrierDependencyFlags();
}
}
@@ -1765,10 +1736,15 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
VK_IMAGE_LAYOUT_GENERAL) :
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments[num_attachments] = {0, static_cast<VkFormat>(key.depth_format), VK_SAMPLE_COUNT_1_BIT,
static_cast<VkAttachmentLoadOp>(key.depth_load_op), static_cast<VkAttachmentStoreOp>(key.depth_store_op),
static_cast<VkAttachmentLoadOp>(key.stencil_load_op),
static_cast<VkAttachmentStoreOp>(key.stencil_store_op), layout, layout};
VkAttachmentDescription& attachment = attachments[num_attachments] = {};
attachment.format = static_cast<VkFormat>(key.depth_format);
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
attachment.loadOp = static_cast<VkAttachmentLoadOp>(key.depth_load_op);
attachment.storeOp = static_cast<VkAttachmentStoreOp>(key.depth_store_op);
attachment.stencilLoadOp = static_cast<VkAttachmentLoadOp>(key.stencil_load_op);
attachment.stencilStoreOp = static_cast<VkAttachmentStoreOp>(key.stencil_store_op);
attachment.initialLayout = layout;
attachment.finalLayout = layout;
depth_reference.attachment = num_attachments;
depth_reference.layout = layout;
depth_reference_ptr = &depth_reference;
@@ -1785,31 +1761,37 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
if (!m_features.framebuffer_fetch)
{
// don't need the framebuffer-local dependency when we have rasterization order attachment access
subpass_dependency[num_subpass_dependencies].srcSubpass = 0;
subpass_dependency[num_subpass_dependencies].dstSubpass = 0;
subpass_dependency[num_subpass_dependencies].srcStageMask =
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
subpass_dependency[num_subpass_dependencies].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpass_dependency[num_subpass_dependencies].srcAccessMask =
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
subpass_dependency[num_subpass_dependencies].dstAccessMask = static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags());
subpass_dependency[num_subpass_dependencies].dependencyFlags = GetFeedbackBarrierDependencyFlags();
num_subpass_dependencies++;
VkSubpassDependency& subpass_dependency = subpass_dependencies[num_subpass_dependencies++];
subpass_dependency.srcSubpass = 0;
subpass_dependency.dstSubpass = 0;
subpass_dependency.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
subpass_dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpass_dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
subpass_dependency.dstAccessMask = static_cast<VkAccessFlags>(GetFeedbackLoopInputAccessFlags());
subpass_dependency.dependencyFlags = GetFeedbackBarrierDependencyFlags();
}
}
num_attachments++;
}
const VkSubpassDescriptionFlags subpass_flags =
(key.color_feedback_loop && m_features.framebuffer_fetch) ?
VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT :
0;
const VkSubpassDescription subpass = {subpass_flags, VK_PIPELINE_BIND_POINT_GRAPHICS, num_subpass_inputs,
num_subpass_inputs ? input_reference.data() : nullptr, color_reference_ptr ? 1u : 0u,
color_reference_ptr ? color_reference_ptr : nullptr, nullptr, depth_reference_ptr, 0, nullptr};
const VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0u, num_attachments,
attachments.data(), 1u, &subpass, num_subpass_dependencies, num_subpass_dependencies ? subpass_dependency.data() : nullptr};
VkSubpassDescription subpass = {};
if (key.color_feedback_loop && m_features.framebuffer_fetch)
subpass.flags |= VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.inputAttachmentCount = num_subpass_inputs;
subpass.pInputAttachments = num_subpass_inputs ? input_reference.data() : nullptr;
subpass.colorAttachmentCount = color_reference_ptr ? 1 : 0;
subpass.pColorAttachments = color_reference_ptr;
subpass.pDepthStencilAttachment = depth_reference_ptr;
VkRenderPassCreateInfo pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
pass_info.attachmentCount = num_attachments;
pass_info.pAttachments = attachments.data();
pass_info.subpassCount = 1;
pass_info.pSubpasses = &subpass;
pass_info.dependencyCount = num_subpass_dependencies;
pass_info.pDependencies = num_subpass_dependencies ? subpass_dependencies.data() : nullptr;
VkRenderPass pass;
const VkResult res = vkCreateRenderPass(m_device, &pass_info, nullptr, &pass);
@@ -1903,8 +1885,7 @@ bool GSDeviceVK::InitSpinResources()
VkBufferCreateInfo buf_create = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
buf_create.size = 4;
buf_create.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
if ((res = vmaCreateBuffer(m_allocator, &buf_create, &buf_vma_create, &m_spin_buffer, &m_spin_buffer_allocation,
nullptr)) != VK_SUCCESS)
if ((res = vmaCreateBuffer(m_allocator, &buf_create, &buf_vma_create, &m_spin_buffer, &m_spin_buffer_allocation, nullptr)) != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vmaCreateBuffer failed: ");
return false;
@@ -2104,16 +2085,12 @@ void GSDeviceVK::SubmitSpinCommand(u32 index, u32 cycles)
const u32 timestamp_base = (index + NUM_COMMAND_BUFFERS) * 2;
vkCmdResetQueryPool(resources.command_buffer, m_timestamp_query_pool, timestamp_base, 2);
vkCmdWriteTimestamp(
resources.command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool, timestamp_base);
vkCmdPushConstants(
resources.command_buffer, m_spin_pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(u32), &cycles);
vkCmdWriteTimestamp(resources.command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool, timestamp_base);
vkCmdPushConstants(resources.command_buffer, m_spin_pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(u32), &cycles);
vkCmdBindPipeline(resources.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, m_spin_pipeline);
vkCmdBindDescriptorSets(resources.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, m_spin_pipeline_layout, 0, 1,
&m_spin_descriptor_set, 0, nullptr);
vkCmdBindDescriptorSets(resources.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, m_spin_pipeline_layout, 0, 1, &m_spin_descriptor_set, 0, nullptr);
vkCmdDispatch(resources.command_buffer, 1, 1, 1);
vkCmdWriteTimestamp(
resources.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, m_timestamp_query_pool, timestamp_base + 1);
vkCmdWriteTimestamp(resources.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, m_timestamp_query_pool, timestamp_base + 1);
if ((res = vkEndCommandBuffer(resources.command_buffer)) != VK_SUCCESS)
LOG_VULKAN_ERROR(res, "vkEndCommandBuffer failed: ");
@@ -2191,9 +2168,13 @@ bool GSDeviceVK::AllocatePreinitializedGPUBuffer(u32 size, VkBuffer* gpu_buffer,
// Try to place the fixed index buffer in GPU local memory.
// Use the staging buffer to copy into it.
const VkBufferCreateInfo cpu_bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr, 0, size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_SHARING_MODE_EXCLUSIVE};
const VmaAllocationCreateInfo cpu_aci = {VMA_ALLOCATION_CREATE_MAPPED_BIT, VMA_MEMORY_USAGE_CPU_ONLY, 0, 0};
VkBufferCreateInfo cpu_bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
cpu_bci.size = size;
cpu_bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
cpu_bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo cpu_aci = {};
cpu_aci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
cpu_aci.usage = VMA_MEMORY_USAGE_CPU_ONLY;
VkBuffer cpu_buffer;
VmaAllocation cpu_allocation;
VmaAllocationInfo cpu_ai;
@@ -2204,9 +2185,13 @@ bool GSDeviceVK::AllocatePreinitializedGPUBuffer(u32 size, VkBuffer* gpu_buffer,
return false;
}
const VkBufferCreateInfo gpu_bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr, 0, size,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE};
const VmaAllocationCreateInfo gpu_aci = {0, VMA_MEMORY_USAGE_GPU_ONLY, 0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT};
VkBufferCreateInfo gpu_bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
gpu_bci.size = size;
gpu_bci.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
gpu_bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo gpu_aci = {};
gpu_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
gpu_aci.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VmaAllocationInfo ai;
res = vmaCreateBuffer(m_allocator, &gpu_bci, &gpu_aci, gpu_buffer, gpu_allocation, &ai);
if (res != VK_SUCCESS)
@@ -2423,7 +2408,7 @@ bool GSDeviceVK::UpdateWindow()
VkPresentModeKHR present_mode;
if (!VKSwapChain::SelectPresentMode(surface, &m_vsync_mode, &present_mode) ||
!(m_swap_chain = VKSwapChain::Create(m_window_info, surface, present_mode,
Pcsx2Config::GSOptions::TriStateToOptionalBoolean(GSConfig.ExclusiveFullscreenControl))))
Pcsx2Config::GSOptions::TriStateToOptionalBoolean(GSConfig.ExclusiveFullscreenControl))))
{
Console.Error("VK: Failed to create swap chain");
VKSwapChain::DestroyVulkanSurface(m_instance, &m_window_info, surface);
@@ -2442,7 +2427,7 @@ void GSDeviceVK::ResizeWindow(u32 new_window_width, u32 new_window_height, float
m_resize_requested = false;
if (!m_swap_chain || (m_swap_chain->GetWidth() == new_window_width &&
m_swap_chain->GetHeight() == new_window_height))
m_swap_chain->GetHeight() == new_window_height))
{
// skip unnecessary resizes
m_window_info.surface_scale = new_window_scale;
@@ -2483,16 +2468,17 @@ std::string GSDeviceVK::GetDriverInfo() const
const VkPhysicalDeviceDriverProperties& props = m_device_driver_properties;
ret = StringUtil::StdStringFromFormat(
"Driver %u.%u.%u\nVulkan %u.%u.%u\nConformance Version %u.%u.%u.%u\n%s\n%s\n%s",
VK_VERSION_MAJOR(driver_version), VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version),
VK_VERSION_MAJOR(driver_version), VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version),
VK_API_VERSION_MAJOR(api_version), VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version),
props.conformanceVersion.major, props.conformanceVersion.minor, props.conformanceVersion.subminor,
props.conformanceVersion.patch, props.driverInfo, props.driverName, m_device_properties.deviceName);
}
else
{
ret = StringUtil::StdStringFromFormat("Driver %u.%u.%u\nVulkan %u.%u.%u\n%s", VK_VERSION_MAJOR(driver_version),
VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version), VK_API_VERSION_MAJOR(api_version),
VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version), m_device_properties.deviceName);
ret = StringUtil::StdStringFromFormat("Driver %u.%u.%u\nVulkan %u.%u.%u\n%s",
VK_VERSION_MAJOR(driver_version), VK_VERSION_MINOR(driver_version), VK_VERSION_PATCH(driver_version),
VK_API_VERSION_MAJOR(api_version), VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version),
m_device_properties.deviceName);
}
return ret;
@@ -2608,18 +2594,16 @@ GSDevice::PresentResult GSDeviceVK::BeginPresent(bool frame_skip)
if (fb == VK_NULL_HANDLE)
return GSDevice::PresentResult::FrameSkipped;
const VkRenderPassBeginInfo rp = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr,
GetRenderPass(swap_chain_texture->GetVkFormat(), VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE),
fb,
{{0, 0}, {static_cast<u32>(swap_chain_texture->GetWidth()), static_cast<u32>(swap_chain_texture->GetHeight())}},
1u, &s_present_clear_color};
VkRenderPassBeginInfo rp = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
rp.renderPass = GetRenderPass(swap_chain_texture->GetVkFormat(), VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE);
rp.framebuffer = fb;
rp.renderArea = {{0, 0}, {static_cast<u32>(swap_chain_texture->GetWidth()), static_cast<u32>(swap_chain_texture->GetHeight())}};
rp.clearValueCount = 1;
rp.pClearValues = &s_present_clear_color;
vkCmdBeginRenderPass(GetCurrentCommandBuffer(), &rp, VK_SUBPASS_CONTENTS_INLINE);
const VkViewport vp{0.0f, 0.0f, static_cast<float>(swap_chain_texture->GetWidth()),
static_cast<float>(swap_chain_texture->GetHeight()), 0.0f, 1.0f};
const VkRect2D scissor{
{0, 0}, {static_cast<u32>(swap_chain_texture->GetWidth()), static_cast<u32>(swap_chain_texture->GetHeight())}};
const VkViewport vp{0.0f, 0.0f, static_cast<float>(swap_chain_texture->GetWidth()), static_cast<float>(swap_chain_texture->GetHeight()), 0.0f, 1.0f};
const VkRect2D scissor{{0, 0}, {static_cast<u32>(swap_chain_texture->GetWidth()), static_cast<u32>(swap_chain_texture->GetHeight())}};
vkCmdSetViewport(GetCurrentCommandBuffer(), 0, 1, &vp);
vkCmdSetScissor(GetCurrentCommandBuffer(), 0, 1, &scissor);
m_is_presenting = true;
@@ -2673,12 +2657,11 @@ void GSDeviceVK::PushDebugGroup(const char* fmt, ...)
const std::array<float, 3> color = Palette(
++s_debug_scope_depth, {0.5f, 0.5f, 0.5f}, {0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 0.5f}, {0.8f, 0.90f, 0.30f});
const VkDebugUtilsLabelEXT label = {
VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
nullptr,
buf.c_str(),
{color[0], color[1], color[2], 1.0f},
};
VkDebugUtilsLabelEXT label = {VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT};
label.pLabelName = buf.c_str();
for (uint32_t i = 0; i < 3; i++)
label.color[i] = color[i];
label.color[3] = 1.0f;
vkCmdBeginDebugUtilsLabelEXT(GetCurrentCommandBuffer(), &label);
#endif
}
@@ -2717,9 +2700,11 @@ void GSDeviceVK::InsertDebugMessage(DebugMessageCategory category, const char* f
{0.0f, 0.2f, 0.0f} // Performance
};
const VkDebugUtilsLabelEXT label = {VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, nullptr, buf.c_str(),
{colors[static_cast<int>(category)][0], colors[static_cast<int>(category)][1],
colors[static_cast<int>(category)][2], 1.0f}};
VkDebugUtilsLabelEXT label = {VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT};
label.pLabelName = buf.c_str();
for (uint32_t i = 0; i < 3; i++)
label.color[i] = colors[static_cast<int>(category)][i];
label.color[3] = 1.0f;
vkCmdInsertDebugUtilsLabelEXT(GetCurrentCommandBuffer(), &label);
#endif
}
@@ -2847,7 +2832,7 @@ bool GSDeviceVK::CreateDeviceAndSwapChain()
VkPresentModeKHR present_mode;
if (!VKSwapChain::SelectPresentMode(surface, &m_vsync_mode, &present_mode) ||
!(m_swap_chain = VKSwapChain::Create(m_window_info, surface, present_mode,
Pcsx2Config::GSOptions::TriStateToOptionalBoolean(GSConfig.ExclusiveFullscreenControl))))
Pcsx2Config::GSOptions::TriStateToOptionalBoolean(GSConfig.ExclusiveFullscreenControl))))
{
ERROR_LOG("Failed to create swap chain");
return false;
@@ -2873,8 +2858,7 @@ bool GSDeviceVK::CheckFeatures()
//const bool isAMD = (vendorID == 0x1002 || vendorID == 0x1022);
//const bool isNVIDIA = (vendorID == 0x10DE);
m_features.framebuffer_fetch =
m_optional_extensions.vk_ext_rasterization_order_attachment_access && !GSConfig.DisableFramebufferFetch;
m_features.framebuffer_fetch = m_optional_extensions.vk_ext_rasterization_order_attachment_access && !GSConfig.DisableFramebufferFetch;
m_features.texture_barrier = GSConfig.OverrideTextureBarriers != 0;
m_features.multidraw_fb_copy = false;
m_features.broken_point_sampler = false;
@@ -2910,7 +2894,7 @@ bool GSDeviceVK::CheckFeatures()
// whether we can do point/line expand depends on the range of the device
const float f_upscale = static_cast<float>(GSConfig.UpscaleMultiplier);
m_features.point_expand = (m_device_features.largePoints && limits.pointSizeRange[0] <= f_upscale &&
limits.pointSizeRange[1] >= f_upscale);
limits.pointSizeRange[1] >= f_upscale);
m_features.line_expand =
(m_device_features.wideLines && limits.lineWidthRange[0] <= f_upscale && limits.lineWidthRange[1] >= f_upscale);
@@ -2958,8 +2942,7 @@ bool GSDeviceVK::CheckFeatures()
if (!m_features.texture_barrier && !m_features.stencil_buffer)
{
Host::AddKeyedOSDMessage("GSDeviceVK_NoTextureBarrierOrStencilBuffer",
TRANSLATE_STR("GS",
"Stencil buffers and texture barriers are both unavailable, this will break some graphical effects."),
TRANSLATE_STR("GS", "Stencil buffers and texture barriers are both unavailable, this will break some graphical effects."),
Host::OSD_WARNING_DURATION);
}
@@ -3031,23 +3014,24 @@ void GSDeviceVK::Draw(const GSHWDrawConfig& config)
VkFormat GSDeviceVK::LookupNativeFormat(GSTexture::Format format) const
{
static constexpr std::array<VkFormat, static_cast<int>(GSTexture::Format::Last) + 1> s_format_mapping = {{
VK_FORMAT_UNDEFINED, // Invalid
VK_FORMAT_R8G8B8A8_UNORM, // Color
static constexpr VkFormat s_format_mapping[] = {
VK_FORMAT_UNDEFINED, // Invalid
VK_FORMAT_R8G8B8A8_UNORM, // Color
VK_FORMAT_A2B10G10R10_UNORM_PACK32, // ColorHQ
VK_FORMAT_R16G16B16A16_SFLOAT, // ColorHDR
VK_FORMAT_R16G16B16A16_UNORM, // ColorClip
VK_FORMAT_D32_SFLOAT_S8_UINT, // DepthStencil
VK_FORMAT_R32_SFLOAT, // DepthColor
VK_FORMAT_R8_UNORM, // UNorm8
VK_FORMAT_R16_UINT, // UInt16
VK_FORMAT_R32_UINT, // UInt32
VK_FORMAT_R32_SFLOAT, // PrimID
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1
VK_FORMAT_BC2_UNORM_BLOCK, // BC2
VK_FORMAT_BC3_UNORM_BLOCK, // BC3
VK_FORMAT_BC7_UNORM_BLOCK, // BC7
}};
VK_FORMAT_R16G16B16A16_SFLOAT, // ColorHDR
VK_FORMAT_R16G16B16A16_UNORM, // ColorClip
VK_FORMAT_D32_SFLOAT_S8_UINT, // DepthStencil
VK_FORMAT_R32_SFLOAT, // DepthColor
VK_FORMAT_R8_UNORM, // UNorm8
VK_FORMAT_R16_UINT, // UInt16
VK_FORMAT_R32_UINT, // UInt32
VK_FORMAT_R32_SFLOAT, // PrimID
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1
VK_FORMAT_BC2_UNORM_BLOCK, // BC2
VK_FORMAT_BC3_UNORM_BLOCK, // BC3
VK_FORMAT_BC7_UNORM_BLOCK, // BC7
};
static_assert(std::size(s_format_mapping) == static_cast<u32>(GSTexture::Format::Last) + 1);
return (format != GSTexture::Format::DepthStencil || m_features.stencil_buffer) ?
s_format_mapping[static_cast<int>(format)] :
@@ -3420,8 +3404,13 @@ void GSDeviceVK::BlitRect(GSTexture* sTex, const GSVector4i& sRect, u32 sLevel,
pxAssert(sTexVK->IsDepthStencil() == dTexVK->IsDepthStencil());
const VkImageAspectFlags aspect =
sTexVK->IsDepthStencil() ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
const VkImageBlit ib{{aspect, sLevel, 0u, 1u}, {{sRect.left, sRect.top, 0}, {sRect.right, sRect.bottom, 1}},
{aspect, dLevel, 0u, 1u}, {{dRect.left, dRect.top, 0}, {dRect.right, dRect.bottom, 1}}};
VkImageBlit ib = {};
ib.srcSubresource = {aspect, sLevel, 0u, 1u};
ib.dstSubresource = {aspect, dLevel, 0u, 1u};
ib.srcOffsets[0] = {sRect.left, sRect.top, 0};
ib.dstOffsets[0] = {dRect.left, dRect.top, 0};
ib.srcOffsets[1] = {sRect.right, sRect.bottom, 1};
ib.dstOffsets[1] = {dRect.right, dRect.bottom, 1};
vkCmdBlitImage(GetCurrentCommandBuffer(), sTexVK->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dTexVK->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &ib,
@@ -3904,26 +3893,16 @@ VkSampler GSDeviceVK::GetSampler(GSHWDrawConfig::SamplerSelector ss)
// See https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSamplerCreateInfo.html#_description
// for the reasoning behind 0.25f here.
const VkSamplerCreateInfo ci = {
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, nullptr, 0,
ss.IsMagFilterLinear() ? VK_FILTER_LINEAR : VK_FILTER_NEAREST, // min
ss.IsMinFilterLinear() ? VK_FILTER_LINEAR : VK_FILTER_NEAREST, // mag
ss.IsMipFilterLinear() ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST, // mip
static_cast<VkSamplerAddressMode>(
ss.tau ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE), // u
static_cast<VkSamplerAddressMode>(
ss.tav ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE), // v
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // w
0.0f, // lod bias
VK_FALSE, // anisotropy enable
1.0f, // anisotropy
VK_FALSE, // compare enable
VK_COMPARE_OP_ALWAYS, // compare op
0.0f, // min lod
(ss.lodclamp || !ss.UseMipmapFiltering()) ? 0.25f : VK_LOD_CLAMP_NONE, // max lod
VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // border
VK_FALSE // unnormalized coordinates
};
VkSamplerCreateInfo ci = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO};
ci.magFilter = ss.IsMagFilterLinear() ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
ci.minFilter = ss.IsMinFilterLinear() ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
ci.mipmapMode = ss.IsMipFilterLinear() ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
ci.addressModeU = ss.tau ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
ci.addressModeV = ss.tav ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
ci.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
ci.maxAnisotropy = 1.0f;
ci.compareOp = VK_COMPARE_OP_ALWAYS;
ci.maxLod = (ss.lodclamp || !ss.UseMipmapFiltering()) ? 0.25f : VK_LOD_CLAMP_NONE;
VkSampler sampler = VK_NULL_HANDLE;
VkResult res = vkCreateSampler(m_device, &ci, nullptr, &sampler);
if (res != VK_SUCCESS)
@@ -4136,7 +4115,7 @@ bool GSDeviceVK::CreatePipelineLayouts()
dslb.AddBinding(TFX_TEXTURE_PALETTE, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
dslb.AddBinding(TFX_TEXTURE_RT,
(m_features.texture_barrier && !UseFeedbackLoopLayout()) ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT :
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
1, VK_SHADER_STAGE_FRAGMENT_BIT);
dslb.AddBinding(TFX_TEXTURE_PRIMID, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
dslb.AddBinding(TFX_TEXTURE_DEPTH,
@@ -4165,10 +4144,10 @@ bool GSDeviceVK::CreateRenderPasses()
dest = GetRenderPass( \
(rt), (depth), ((rt) != VK_FORMAT_UNDEFINED) ? (opa) : VK_ATTACHMENT_LOAD_OP_DONT_CARE, /* color load */ \
((rt) != VK_FORMAT_UNDEFINED) ? VK_ATTACHMENT_STORE_OP_STORE : \
VK_ATTACHMENT_STORE_OP_DONT_CARE, /* color store */ \
VK_ATTACHMENT_STORE_OP_DONT_CARE, /* color store */ \
((depth) != VK_FORMAT_UNDEFINED) ? (opb) : VK_ATTACHMENT_LOAD_OP_DONT_CARE, /* depth load */ \
((depth) != VK_FORMAT_UNDEFINED) ? VK_ATTACHMENT_STORE_OP_STORE : \
VK_ATTACHMENT_STORE_OP_DONT_CARE, /* depth store */ \
VK_ATTACHMENT_STORE_OP_DONT_CARE, /* depth store */ \
((depth) != VK_FORMAT_UNDEFINED) ? (opc) : VK_ATTACHMENT_LOAD_OP_DONT_CARE, /* stencil load */ \
VK_ATTACHMENT_STORE_OP_DONT_CARE, /* stencil store */ \
(fbl), /* feedback loop */ \
@@ -4376,8 +4355,7 @@ bool GSDeviceVK::CompileConvertPipelines()
m_primid_image_setup_render_passes[ds][clear] = GetRenderPass(LookupNativeFormat(GSTexture::Format::PrimID),
ds ? LookupNativeFormat(GSTexture::Format::DepthStencil) : VK_FORMAT_UNDEFINED,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
ds ? (clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD) :
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
ds ? (clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD) : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
ds ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE);
}
}
@@ -5224,14 +5202,14 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p)
else if (pbs.enable)
{
// clang-format off
static constexpr std::array<VkBlendFactor, 16> vk_blend_factors = { {
VK_BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_DST_COLOR, VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
VK_BLEND_FACTOR_SRC1_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, VK_BLEND_FACTOR_SRC1_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
static constexpr std::array<VkBlendFactor, 16> vk_blend_factors = {{
VK_BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_DST_COLOR, VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
VK_BLEND_FACTOR_SRC1_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, VK_BLEND_FACTOR_SRC1_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
VK_BLEND_FACTOR_CONSTANT_COLOR, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO
}};
static constexpr std::array<VkBlendOp, 3> vk_blend_ops = {{
VK_BLEND_OP_ADD, VK_BLEND_OP_SUBTRACT, VK_BLEND_OP_REVERSE_SUBTRACT
VK_BLEND_OP_ADD, VK_BLEND_OP_SUBTRACT, VK_BLEND_OP_REVERSE_SUBTRACT
}};
// clang-format on
@@ -6185,16 +6163,16 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
cvs[cv_count++].depthStencil = {draw_ds->GetClearDepth(), 1};
BeginClearRenderPass(GetTFXRenderPass(true, pipe.ds, false, false, pipe.IsRTFeedbackLoop(),
pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_CLEAR,
pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_CLEAR,
pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
draw_rt->GetRect(), cvs, cv_count);
draw_rt->SetState(GSTexture::State::Dirty);
}
else
{
BeginRenderPass(GetTFXRenderPass(true, pipe.ds, false, false, pipe.IsRTFeedbackLoop(),
pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_LOAD,
pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_LOAD,
pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
draw_rt->GetRect());
}
@@ -6453,9 +6431,10 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne)
{
const VkClearAttachment ca = {VK_IMAGE_ASPECT_STENCIL_BIT, 0u, {.depthStencil = {0.0f, 1u}}};
const VkClearRect rc = {{{config.drawarea.left, config.drawarea.top},
{static_cast<u32>(config.drawarea.width()), static_cast<u32>(config.drawarea.height())}},
0u, 1u};
VkClearRect rc = {};
rc.rect.offset = {config.drawarea.left, config.drawarea.top};
rc.rect.extent = {static_cast<u32>(config.drawarea.width()), static_cast<u32>(config.drawarea.height())};
rc.layerCount = 1;
vkCmdClearAttachments(m_current_command_buffer, 1, &ca, 1, &rc);
}
@@ -6553,16 +6532,16 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
cvs[cv_count++].depthStencil = {draw_ds->GetClearDepth(), 1};
BeginClearRenderPass(GetTFXRenderPass(true, pipe.ds, false, false, pipe.IsRTFeedbackLoop(),
pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_CLEAR,
pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_CLEAR,
pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
draw_rt->GetRect(), cvs, cv_count);
draw_rt->SetState(GSTexture::State::Dirty);
}
else
{
BeginRenderPass(GetTFXRenderPass(true, pipe.ds, false, false, pipe.IsRTFeedbackLoop(),
pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_LOAD,
pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_LOAD,
pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
draw_rt->GetRect());
}
+83 -54
View File
@@ -14,10 +14,11 @@
VkFramebuffer GSTextureVK::CreateNullFramebuffer(u32 w, u32 h)
{
const VkRenderPass rp = GSDeviceVK::GetInstance()->GetRenderPass(
VK_FORMAT_UNDEFINED,
VK_FORMAT_UNDEFINED,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, false, false);
VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
false, false);
if (!rp)
return VK_NULL_HANDLE;
@@ -29,29 +30,31 @@ VkFramebuffer GSTextureVK::CreateNullFramebuffer(u32 w, u32 h)
return fbb.Create(GSDeviceVK::GetInstance()->GetDevice());
}
static constexpr const VkComponentMapping s_identity_swizzle{VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
static constexpr const VkComponentMapping s_identity_swizzle {
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
};
static VkImageLayout GetVkImageLayout(GSTextureVK::Layout layout)
{
static constexpr VkImageLayout s_vk_layout_mapping[] = {
VK_IMAGE_LAYOUT_UNDEFINED, // Undefined
VK_IMAGE_LAYOUT_PREINITIALIZED, // Preinitialized
VK_IMAGE_LAYOUT_UNDEFINED, // Undefined
VK_IMAGE_LAYOUT_PREINITIALIZED, // Preinitialized
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // ColorAttachment
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // DepthStencilAttachment
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // ShaderReadOnly
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // ClearDst
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // CopySrc
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // CopyDst
VK_IMAGE_LAYOUT_GENERAL, // CopySelf
VK_IMAGE_LAYOUT_GENERAL, // CopySelf
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // BlitSrc
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // BlitDst
VK_IMAGE_LAYOUT_GENERAL, // BlitSelf
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // PresentSrc
VK_IMAGE_LAYOUT_GENERAL, // FeedbackLoop
VK_IMAGE_LAYOUT_GENERAL, // ReadWriteImage
VK_IMAGE_LAYOUT_GENERAL, // ComputeReadWriteImage
VK_IMAGE_LAYOUT_GENERAL, // General
VK_IMAGE_LAYOUT_GENERAL, // BlitSelf
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // PresentSrc
VK_IMAGE_LAYOUT_GENERAL, // FeedbackLoop
VK_IMAGE_LAYOUT_GENERAL, // ReadWriteImage
VK_IMAGE_LAYOUT_GENERAL, // ComputeReadWriteImage
VK_IMAGE_LAYOUT_GENERAL, // General
};
static_assert(std::size(s_vk_layout_mapping) == static_cast<u32>(GSTextureVK::Layout::Count));
if (layout == GSTextureVK::Layout::FeedbackLoop)
@@ -62,11 +65,13 @@ static VkImageLayout GetVkImageLayout(GSTextureVK::Layout layout)
static VkPipelineStageFlags2 GetPipelineStageFlags(GSTextureVK::Layout layout, bool color)
{
static constexpr VkPipelineStageFlags2 VK_PIPELINE_STAGE_2_FRAGMENT_TESTS_BITS =
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
static constexpr VkPipelineStageFlags2 s_vk_stage_mapping[] = {
VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, // Undefined
VK_PIPELINE_STAGE_2_HOST_BIT, // Preinitialized
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, // ColorAttachment
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, // DepthStencilAttachment
VK_PIPELINE_STAGE_2_FRAGMENT_TESTS_BITS, // DepthStencilAttachment
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, // ShaderReadOnly
VK_PIPELINE_STAGE_2_CLEAR_BIT, // ClearDst
VK_PIPELINE_STAGE_2_COPY_BIT, // CopySrc
@@ -88,7 +93,7 @@ static VkPipelineStageFlags2 GetPipelineStageFlags(GSTextureVK::Layout layout, b
if (color)
flags |= VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
else
flags |= VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
flags |= VK_PIPELINE_STAGE_2_FRAGMENT_TESTS_BITS;
return flags;
}
else
@@ -99,25 +104,27 @@ static VkPipelineStageFlags2 GetPipelineStageFlags(GSTextureVK::Layout layout, b
static VkAccessFlags2 GetAccessFlags(GSTextureVK::Layout layout, bool color)
{
#define VK_ACCESS_2_READ_WRITE_BITS(x) VK_ACCESS_2_##x##_READ_BIT | VK_ACCESS_2_##x##_WRITE_BIT
static constexpr VkPipelineStageFlags2 s_vk_access_mapping[] = {
VK_ACCESS_2_NONE, // Undefined
VK_ACCESS_2_HOST_WRITE_BIT, // Preinitialized
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, // ColorAttachment
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // DepthStencilAttachment
VK_ACCESS_2_READ_WRITE_BITS(COLOR_ATTACHMENT), // ColorAttachment
VK_ACCESS_2_READ_WRITE_BITS(DEPTH_STENCIL_ATTACHMENT), // DepthStencilAttachment
VK_ACCESS_2_SHADER_READ_BIT, // ShaderReadOnly
VK_ACCESS_2_TRANSFER_WRITE_BIT, // ClearDst
VK_ACCESS_2_TRANSFER_READ_BIT, // CopySrc
VK_ACCESS_2_TRANSFER_WRITE_BIT, // CopyDst
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT, // CopySelf
VK_ACCESS_2_READ_WRITE_BITS(TRANSFER), // CopySelf
VK_ACCESS_2_TRANSFER_READ_BIT, // BlitSrc
VK_ACCESS_2_TRANSFER_WRITE_BIT, // BlitDst
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT, // BlitSelf
VK_ACCESS_2_READ_WRITE_BITS(TRANSFER), // BlitSelf
VK_ACCESS_2_NONE, // PresentSrc
VK_ACCESS_2_NONE, // FeedbackLoop (overridden)
VK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, // ReadWriteImage
VK_ACCESS_2_SHADER_STORAGE_READ_BIT | VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT, // ComputeReadWriteImage
VK_ACCESS_2_READ_WRITE_BITS(SHADER_STORAGE), // ReadWriteImage
VK_ACCESS_2_READ_WRITE_BITS(SHADER_STORAGE), // ComputeReadWriteImage
VK_ACCESS_2_NONE, // General
};
#undef VK_ACCESS_2_READ_WRITE_BITS
static_assert(std::size(s_vk_access_mapping) == static_cast<u32>(GSTextureVK::Layout::Count));
if (layout == GSTextureVK::Layout::FeedbackLoop)
@@ -161,18 +168,25 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Usage usage, Format format, int
const VkFormat vk_format = GSDeviceVK::GetInstance()->LookupNativeFormat(format);
VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, nullptr, 0, VK_IMAGE_TYPE_2D, vk_format,
{static_cast<u32>(width), static_cast<u32>(height), 1}, static_cast<u32>(levels), 1, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL};
VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
ici.imageType = VK_IMAGE_TYPE_2D;
ici.format = vk_format;
ici.extent = {static_cast<u32>(width), static_cast<u32>(height), 1};
ici.mipLevels = levels;
ici.arrayLayers = 1;
ici.samples = VK_SAMPLE_COUNT_1_BIT;
ici.tiling = VK_IMAGE_TILING_OPTIMAL;
VmaAllocationCreateInfo aci = {};
aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
aci.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT;
aci.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VkImageViewCreateInfo vci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, nullptr, 0, VK_NULL_HANDLE,
VK_IMAGE_VIEW_TYPE_2D, vk_format, s_identity_swizzle,
{VK_IMAGE_ASPECT_COLOR_BIT, 0, static_cast<u32>(levels), 0, 1}};
VkImageViewCreateInfo vci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
vci.viewType = VK_IMAGE_VIEW_TYPE_2D;
vci.format = vk_format;
vci.components = s_identity_swizzle;
vci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, static_cast<u32>(levels), 0, 1};
ici.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
@@ -250,12 +264,14 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Adopt(
VkImage image, Usage usage, Format format, int width, int height, int levels, VkFormat vk_format)
{
// Only need to create the image view, this is mainly for swap chains.
const VkImageViewCreateInfo view_info = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, nullptr, 0, image,
VK_IMAGE_VIEW_TYPE_2D, vk_format, s_identity_swizzle,
{IsDepthStencil(usage) ?
static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT) :
static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT),
0u, static_cast<u32>(levels), 0u, 1u}};
VkImageViewCreateInfo view_info = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
view_info.image = image;
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
view_info.format = vk_format;
view_info.components = s_identity_swizzle;
view_info.subresourceRange.aspectMask = IsDepthStencil(usage) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
view_info.subresourceRange.levelCount = levels;
view_info.subresourceRange.layerCount = 1;
// Memory is managed by the owner of the image.
VkImageView view = VK_NULL_HANDLE;
@@ -355,8 +371,10 @@ void GSTextureVK::CopyTextureDataForUpload(void* dst, const void* src, u32 pitch
VkBuffer GSTextureVK::AllocateUploadStagingBuffer(const void* data, u32 pitch, u32 upload_pitch, u32 height) const
{
const u32 size = upload_pitch * height;
const VkBufferCreateInfo bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr, 0, static_cast<VkDeviceSize>(size),
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_SHARING_MODE_EXCLUSIVE, 0, nullptr};
VkBufferCreateInfo bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
bci.size = size;
bci.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
// Don't worry about setting the coherent bit for this upload, the main reason we had
// that set in StreamBuffer was for MoltenVK, which would upload the whole buffer on
@@ -393,9 +411,15 @@ void GSTextureVK::UpdateFromBuffer(VkCommandBuffer cmdbuf, int level, u32 x, u32
else if (old_layout != Layout::CopyDst)
TransitionSubresourcesToLayout(cmdbuf, level, 1, old_layout, Layout::CopyDst);
const VkBufferImageCopy bic = {static_cast<VkDeviceSize>(buffer_offset), row_length, buffer_height,
{VK_IMAGE_ASPECT_COLOR_BIT, static_cast<u32>(level), 0u, 1u}, {static_cast<s32>(x), static_cast<s32>(y), 0},
{width, height, 1u}};
VkBufferImageCopy bic = {};
bic.bufferOffset = buffer_offset;
bic.bufferRowLength = row_length;
bic.bufferImageHeight = buffer_height;
bic.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
bic.imageSubresource.mipLevel = level;
bic.imageSubresource.layerCount = 1;
bic.imageOffset = {static_cast<s32>(x), static_cast<s32>(y), 0};
bic.imageExtent = {width, height, 1};
vkCmdCopyBufferToImage(cmdbuf, buffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bic);
@@ -581,12 +605,13 @@ void GSTextureVK::GenerateMipmap()
TransitionSubresourcesToLayout(cmdbuf, src_level, 1, m_layout, Layout::BlitSrc);
TransitionSubresourcesToLayout(cmdbuf, dst_level, 1, m_layout, Layout::BlitDst);
const VkImageBlit blit = {
{VK_IMAGE_ASPECT_COLOR_BIT, static_cast<u32>(src_level), 0u, 1u}, // srcSubresource
{{0, 0, 0}, {src_width, src_height, 1}}, // srcOffsets
{VK_IMAGE_ASPECT_COLOR_BIT, static_cast<u32>(dst_level), 0u, 1u}, // dstSubresource
{{0, 0, 0}, {dst_width, dst_height, 1}} // dstOffsets
};
VkImageBlit blit;
blit.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, static_cast<u32>(src_level), 0u, 1u};
blit.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, static_cast<u32>(dst_level), 0u, 1u};
blit.srcOffsets[0] = {0, 0, 0};
blit.dstOffsets[0] = {0, 0, 0};
blit.srcOffsets[1] = {src_width, src_height, 1};
blit.dstOffsets[1] = {dst_width, dst_height, 1};
vkCmdBlitImage(cmdbuf, m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR);
@@ -700,12 +725,12 @@ void GSTextureVK::TransitionSubresourcesToLayout(
pxAssert(new_layout != Layout::Preinitialized);
VkImageMemoryBarrier2 barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2};
barrier.srcStageMask = GetPipelineStageFlags(old_layout, !IsDepthStencil());
barrier.dstStageMask = GetPipelineStageFlags(new_layout, !IsDepthStencil());
barrier.srcStageMask = GetPipelineStageFlags(old_layout, !IsDepthStencil());
barrier.dstStageMask = GetPipelineStageFlags(new_layout, !IsDepthStencil());
barrier.srcAccessMask = GetAccessFlags(old_layout, !IsDepthStencil());
barrier.dstAccessMask = GetAccessFlags(new_layout, !IsDepthStencil());
barrier.oldLayout = GetVkImageLayout(old_layout);
barrier.newLayout = GetVkImageLayout(new_layout);
barrier.oldLayout = GetVkImageLayout(old_layout);
barrier.newLayout = GetVkImageLayout(new_layout);
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = m_image;
@@ -745,8 +770,10 @@ VkFramebuffer GSTextureVK::GetLinkedFramebuffer(GSTextureVK* depth_texture, bool
const VkRenderPass rp = GSDeviceVK::GetInstance()->GetRenderPass(
!IsDepthStencil() ? m_vk_format : VK_FORMAT_UNDEFINED,
!IsDepthStencil() ? (depth_texture ? depth_texture->m_vk_format : VK_FORMAT_UNDEFINED) : m_vk_format,
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, feedback_loop_color, feedback_loop_depth);
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
feedback_loop_color, feedback_loop_depth);
if (!rp)
return VK_NULL_HANDLE;
@@ -784,8 +811,10 @@ std::unique_ptr<GSDownloadTextureVK> GSDownloadTextureVK::Create(u32 width, u32
const u32 buffer_size =
GetBufferSize(width, height, format, GSDeviceVK::GetInstance()->GetBufferCopyRowPitchAlignment());
const VkBufferCreateInfo bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr, 0u, buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 0u, nullptr};
VkBufferCreateInfo bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
bci.size = buffer_size;
bci.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo aci = {};
aci.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;