GS/Vulkan: Make line width dynamic

This commit is contained in:
Stenzek 2023-06-29 23:04:55 +10:00 committed by refractionpcsx2
parent e9c3807509
commit 987bebffc7
4 changed files with 37 additions and 14 deletions

View File

@ -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;

View File

@ -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<float>(GSConfig.UpscaleMultiplier));
if (p.topology == static_cast<u8>(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<GSTextureVK*>(sr);
@ -3206,6 +3220,9 @@ __ri void GSDeviceVK::ApplyBaseState(u32 flags, VkCommandBuffer cmdbuf)
const GSVector4 col(static_cast<float>(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)

View File

@ -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<const GSTextureVK*, NUM_TFX_TEXTURES> m_tfx_textures{};

View File

@ -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;