From d6099dd2634fcd560e5afe86ea0086bd11c6c451 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 9 Feb 2023 21:32:31 +1000 Subject: [PATCH] GS/Vulkan: Use Bresenham line rasterization when supported --- common/Vulkan/Builders.cpp | 15 ++++++++++++++- common/Vulkan/Builders.h | 2 ++ common/Vulkan/Context.cpp | 16 ++++++++++++++++ common/Vulkan/Context.h | 2 ++ pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 5 +++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/common/Vulkan/Builders.cpp b/common/Vulkan/Builders.cpp index ec0026dfa3..bf2e8f6882 100644 --- a/common/Vulkan/Builders.cpp +++ b/common/Vulkan/Builders.cpp @@ -153,6 +153,9 @@ namespace Vulkan m_provoking_vertex = {}; m_provoking_vertex.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT; + m_line_rasterization_state = {}; + m_line_rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT; + // set defaults SetNoCullRasterizationState(); SetNoDepthTestState(); @@ -255,7 +258,17 @@ namespace Vulkan m_ci.pRasterizationState = &m_rasterization_state; } - void GraphicsPipelineBuilder::SetLineWidth(float width) { m_rasterization_state.lineWidth = width; } + void GraphicsPipelineBuilder::SetLineWidth(float width) + { + m_rasterization_state.lineWidth = width; + } + + void GraphicsPipelineBuilder::SetLineRasterizationMode(VkLineRasterizationModeEXT mode) + { + Util::AddPointerToChain(&m_rasterization_state, &m_line_rasterization_state); + + m_line_rasterization_state.lineRasterizationMode = mode; + } void GraphicsPipelineBuilder::SetMultisamples(u32 multisamples, bool per_sample_shading) { diff --git a/common/Vulkan/Builders.h b/common/Vulkan/Builders.h index 86a0f884dc..5b4e5b0a08 100644 --- a/common/Vulkan/Builders.h +++ b/common/Vulkan/Builders.h @@ -96,6 +96,7 @@ namespace Vulkan void SetRasterizationState(VkPolygonMode polygon_mode, VkCullModeFlags cull_mode, VkFrontFace front_face); void SetLineWidth(float width); + void SetLineRasterizationMode(VkLineRasterizationModeEXT mode); void SetMultisamples(u32 multisamples, bool per_sample_shading); void SetNoCullRasterizationState(); @@ -157,6 +158,7 @@ namespace Vulkan VkPipelineMultisampleStateCreateInfo m_multisample_state; VkPipelineRasterizationProvokingVertexStateCreateInfoEXT m_provoking_vertex; + VkPipelineRasterizationLineStateCreateInfoEXT m_line_rasterization_state; }; class ComputePipelineBuilder diff --git a/common/Vulkan/Context.cpp b/common/Vulkan/Context.cpp index 49c2706a28..1f9af54021 100644 --- a/common/Vulkan/Context.cpp +++ b/common/Vulkan/Context.cpp @@ -458,6 +458,8 @@ namespace Vulkan SupportsExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, false); m_optional_extensions.vk_ext_calibrated_timestamps = SupportsExtension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, false); + m_optional_extensions.vk_ext_line_rasterization = + SupportsExtension(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, false); m_optional_extensions.vk_khr_driver_properties = SupportsExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, false); m_optional_extensions.vk_arm_rasterization_order_attachment_access = @@ -654,12 +656,19 @@ namespace Vulkan VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT}; VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM rasterization_order_access_feature = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM}; + VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT}; if (m_optional_extensions.vk_ext_provoking_vertex) { provoking_vertex_feature.provokingVertexLast = VK_TRUE; Util::AddPointerToChain(&device_info, &provoking_vertex_feature); } + if (m_optional_extensions.vk_ext_line_rasterization) + { + line_rasterization_feature.bresenhamLines = VK_TRUE; + Util::AddPointerToChain(&device_info, &line_rasterization_feature); + } if (m_optional_extensions.vk_arm_rasterization_order_attachment_access) { rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess = VK_TRUE; @@ -724,12 +733,16 @@ namespace Vulkan VkPhysicalDeviceFeatures2 features2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; 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}; VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM rasterization_order_access_feature = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM}; // add in optional feature structs if (m_optional_extensions.vk_ext_provoking_vertex) Util::AddPointerToChain(&features2, &provoking_vertex_features); + if (m_optional_extensions.vk_ext_line_rasterization) + Util::AddPointerToChain(&features2, &line_rasterization_feature); if (m_optional_extensions.vk_arm_rasterization_order_attachment_access) Util::AddPointerToChain(&features2, &rasterization_order_access_feature); @@ -739,6 +752,7 @@ namespace Vulkan // confirm we actually support it m_optional_extensions.vk_ext_provoking_vertex &= (provoking_vertex_features.provokingVertexLast == VK_TRUE); m_optional_extensions.vk_arm_rasterization_order_attachment_access &= (rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE); + m_optional_extensions.vk_ext_line_rasterization &= (line_rasterization_feature.bresenhamLines == VK_TRUE); VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2}; void** pNext = &properties2.pNext; @@ -789,6 +803,8 @@ namespace Vulkan Console.WriteLn("VK_EXT_provoking_vertex is %s", m_optional_extensions.vk_ext_provoking_vertex ? "supported" : "NOT supported"); + Console.WriteLn("VK_EXT_line_rasterization is %s", + m_optional_extensions.vk_ext_line_rasterization ? "supported" : "NOT supported"); Console.WriteLn("VK_EXT_calibrated_timestamps is %s", m_optional_extensions.vk_ext_calibrated_timestamps ? "supported" : "NOT supported"); Console.WriteLn("VK_ARM_rasterization_order_attachment_access is %s", diff --git a/common/Vulkan/Context.h b/common/Vulkan/Context.h index 10d9ffb2c6..450f12e8a5 100644 --- a/common/Vulkan/Context.h +++ b/common/Vulkan/Context.h @@ -52,6 +52,7 @@ namespace Vulkan bool vk_ext_provoking_vertex : 1; bool vk_ext_memory_budget : 1; bool vk_ext_calibrated_timestamps : 1; + bool vk_ext_line_rasterization : 1; bool vk_khr_driver_properties : 1; bool vk_arm_rasterization_order_attachment_access : 1; bool vk_khr_fragment_shader_barycentric : 1; @@ -398,6 +399,7 @@ namespace Vulkan VkPhysicalDeviceProperties m_device_properties = {}; VkPhysicalDeviceMemoryProperties m_device_memory_properties = {}; VkPhysicalDeviceDriverPropertiesKHR m_device_driver_properties = {}; + VkPhysicalDeviceLineRasterizationFeaturesEXT m_line_rasterization_features = {}; OptionalExtensions m_optional_extensions = {}; }; diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 0e4bf4f6a5..4b3c620cb7 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -251,6 +251,9 @@ bool GSDeviceVK::CheckFeatures() if (!m_features.texture_barrier) Console.Warning("Texture buffers are disabled. This may break some graphical effects."); + if (!g_vulkan_context->GetOptionalExtensions().vk_ext_line_rasterization) + Console.WriteLn("VK_EXT_line_rasterization or the BRESENHAM mode is not supported, this may cause rendering inaccuracies."); + // Test for D32S8 support. { VkFormatProperties props = {}; @@ -2047,6 +2050,8 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p) gpb.SetRasterizationState(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE); if (p.line_width) gpb.SetLineWidth(static_cast(GSConfig.UpscaleMultiplier)); + if (p.topology == static_cast(GSHWDrawConfig::Topology::Line) && g_vulkan_context->GetOptionalExtensions().vk_ext_line_rasterization) + gpb.SetLineRasterizationMode(VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT); gpb.SetDynamicViewportAndScissorState(); gpb.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS);