From 987bebffc7208387e3ac1c903207288a6ab921fa Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 29 Jun 2023 23:04:55 +1000 Subject: [PATCH] GS/Vulkan: Make line width dynamic --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 2 +- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 26 +++++++++++++++++++++--- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h | 21 +++++++++++-------- pcsx2/ShaderCacheVersion.h | 2 +- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index f0de09e58b..3f6dc160af 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -4414,7 +4414,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta const float scale_factor = rt ? rt->GetScale() : ds->GetScale(); m_conf.cb_vs.texture_offset = {}; - m_conf.cb_ps.ScaleFactor = GSVector4(scale_factor * (1.0f / 16.0f), 1.0f / scale_factor, 0.0f, 0.0f); + m_conf.cb_ps.ScaleFactor = GSVector4(scale_factor * (1.0f / 16.0f), 1.0f / scale_factor, scale_factor, 0.0f); m_conf.ps.scanmsk = env.SCANMSK.MSK; m_conf.rt = rt ? rt->m_texture : nullptr; m_conf.ds = ds ? ds->m_texture : nullptr; diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 4178062b2e..fd7071520b 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -1857,6 +1857,7 @@ bool GSDeviceVK::CompileConvertPipelines() gpb.SetPipelineLayout(m_utility_pipeline_layout); gpb.SetDynamicViewportAndScissorState(); gpb.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS); + gpb.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH); gpb.SetNoCullRasterizationState(); gpb.SetNoBlendingState(); gpb.SetVertexShader(vs); @@ -2048,6 +2049,7 @@ bool GSDeviceVK::CompilePresentPipelines() gpb.SetPipelineLayout(m_utility_pipeline_layout); gpb.SetDynamicViewportAndScissorState(); gpb.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS); + gpb.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH); gpb.SetNoCullRasterizationState(); gpb.SetNoBlendingState(); gpb.SetVertexShader(vs); @@ -2104,6 +2106,7 @@ bool GSDeviceVK::CompileInterlacePipelines() gpb.SetPipelineLayout(m_utility_pipeline_layout); gpb.SetDynamicViewportAndScissorState(); gpb.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS); + gpb.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH); gpb.SetNoCullRasterizationState(); gpb.SetNoDepthTestState(); gpb.SetNoBlendingState(); @@ -2155,6 +2158,7 @@ bool GSDeviceVK::CompileMergePipelines() gpb.SetPipelineLayout(m_utility_pipeline_layout); gpb.SetDynamicViewportAndScissorState(); gpb.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS); + gpb.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH); gpb.SetNoCullRasterizationState(); gpb.SetNoDepthTestState(); gpb.SetRenderPass(rp, 0); @@ -2194,6 +2198,7 @@ bool GSDeviceVK::CompilePostProcessingPipelines() gpb.SetPipelineLayout(m_utility_pipeline_layout); gpb.SetDynamicViewportAndScissorState(); gpb.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS); + gpb.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH); gpb.SetNoCullRasterizationState(); gpb.SetNoDepthTestState(); gpb.SetNoBlendingState(); @@ -2350,6 +2355,7 @@ bool GSDeviceVK::CompileImGuiPipeline() VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD); gpb.SetDynamicViewportAndScissorState(); gpb.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS); + gpb.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH); m_imgui_pipeline = gpb.Create(g_vulkan_context->GetDevice(), g_vulkan_shader_cache->GetPipelineCache(), false); if (!m_imgui_pipeline) @@ -2722,12 +2728,11 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p) } gpb.SetPrimitiveTopology(topology_lookup[p.topology]); 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); + gpb.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH); // Shaders gpb.SetVertexShader(vs); @@ -2949,7 +2954,7 @@ void GSDeviceVK::ExecuteCommandBufferForReadback() void GSDeviceVK::InvalidateCachedState() { m_dirty_flags |= DIRTY_FLAG_TFX_SAMPLERS_DS | DIRTY_FLAG_TFX_RT_TEXTURE_DS | DIRTY_FLAG_TFX_DYNAMIC_OFFSETS | - DIRTY_FLAG_UTILITY_TEXTURE | DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_VERTEX_BUFFER | + DIRTY_FLAG_UTILITY_TEXTURE | DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_LINE_WIDTH | DIRTY_FLAG_VERTEX_BUFFER | DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR | DIRTY_FLAG_PIPELINE | DIRTY_FLAG_VS_CONSTANT_BUFFER | DIRTY_FLAG_PS_CONSTANT_BUFFER; if (m_vertex_buffer != VK_NULL_HANDLE) @@ -3001,6 +3006,15 @@ void GSDeviceVK::SetBlendConstants(u8 color) m_dirty_flags |= DIRTY_FLAG_BLEND_CONSTANTS; } +void GSDeviceVK::SetLineWidth(float width) +{ + if (m_current_line_width == width) + return; + + m_current_line_width = width; + m_dirty_flags |= DIRTY_FLAG_LINE_WIDTH; +} + void GSDeviceVK::PSSetShaderResource(int i, GSTexture* sr, bool check_state) { GSTextureVK* vkTex = static_cast(sr); @@ -3206,6 +3220,9 @@ __ri void GSDeviceVK::ApplyBaseState(u32 flags, VkCommandBuffer cmdbuf) const GSVector4 col(static_cast(m_blend_constant_color) / 128.0f); vkCmdSetBlendConstants(cmdbuf, col.v); } + + if (flags & DIRTY_FLAG_LINE_WIDTH) + vkCmdSetLineWidth(cmdbuf, m_current_line_width); } bool GSDeviceVK::ApplyTFXState(bool already_execed) @@ -3600,6 +3617,9 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) if (config.blend.constant_enable) SetBlendConstants(config.blend.constant); + if (config.line_expand) + SetLineWidth(config.cb_ps.ScaleFactor.z); + // Primitive ID tracking DATE setup. GSTextureVK* date_image = nullptr; if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking) diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h index a466f14331..e90a3a77d8 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h @@ -340,6 +340,7 @@ public: void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset); void SetIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType type); void SetBlendConstants(u8 color); + void SetLineWidth(float width); void SetUtilityTexture(GSTexture* tex, VkSampler sampler); void SetUtilityPushConstants(const void* data, u32 size); @@ -367,16 +368,17 @@ private: DIRTY_FLAG_TFX_DYNAMIC_OFFSETS = (1 << 2), DIRTY_FLAG_UTILITY_TEXTURE = (1 << 3), DIRTY_FLAG_BLEND_CONSTANTS = (1 << 4), - DIRTY_FLAG_VERTEX_BUFFER = (1 << 5), - DIRTY_FLAG_INDEX_BUFFER = (1 << 6), - DIRTY_FLAG_VIEWPORT = (1 << 7), - DIRTY_FLAG_SCISSOR = (1 << 8), - DIRTY_FLAG_PIPELINE = (1 << 9), - DIRTY_FLAG_VS_CONSTANT_BUFFER = (1 << 10), - DIRTY_FLAG_PS_CONSTANT_BUFFER = (1 << 11), + DIRTY_FLAG_LINE_WIDTH = (1 << 5), + DIRTY_FLAG_VERTEX_BUFFER = (1 << 6), + DIRTY_FLAG_INDEX_BUFFER = (1 << 7), + DIRTY_FLAG_VIEWPORT = (1 << 8), + DIRTY_FLAG_SCISSOR = (1 << 9), + DIRTY_FLAG_PIPELINE = (1 << 10), + DIRTY_FLAG_VS_CONSTANT_BUFFER = (1 << 11), + DIRTY_FLAG_PS_CONSTANT_BUFFER = (1 << 12), DIRTY_BASE_STATE = DIRTY_FLAG_VERTEX_BUFFER | DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PIPELINE | - DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR | DIRTY_FLAG_BLEND_CONSTANTS, + DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR | DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_LINE_WIDTH, DIRTY_TFX_STATE = DIRTY_BASE_STATE | DIRTY_FLAG_TFX_SAMPLERS_DS | DIRTY_FLAG_TFX_RT_TEXTURE_DS, DIRTY_UTILITY_STATE = DIRTY_BASE_STATE | DIRTY_FLAG_UTILITY_TEXTURE, DIRTY_CONSTANT_BUFFER_STATE = DIRTY_FLAG_VS_CONSTANT_BUFFER | DIRTY_FLAG_PS_CONSTANT_BUFFER, @@ -412,8 +414,9 @@ private: VkRenderPass m_current_render_pass = VK_NULL_HANDLE; GSVector4i m_current_render_pass_area = GSVector4i::zero(); - VkViewport m_viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; GSVector4i m_scissor = GSVector4i::zero(); + VkViewport m_viewport = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; + float m_current_line_width = -1.0f; u8 m_blend_constant_color = 0; std::array m_tfx_textures{}; diff --git a/pcsx2/ShaderCacheVersion.h b/pcsx2/ShaderCacheVersion.h index 1ee0e7eac4..09e5593f8f 100644 --- a/pcsx2/ShaderCacheVersion.h +++ b/pcsx2/ShaderCacheVersion.h @@ -15,4 +15,4 @@ /// Version number for GS and other shaders. Increment whenever any of the contents of the /// shaders change, to invalidate the cache. -static constexpr u32 SHADER_CACHE_VERSION = 25; +static constexpr u32 SHADER_CACHE_VERSION = 26;