mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-10-12 02:08:45 +00:00
GS:VK: Formatting
This commit is contained in:
committed by
lightningterror
parent
c53b0c9c92
commit
b18c0007a4
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user