From 2330d3a0565dea97b689d9ef8698737f3bd61e00 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 30 Dec 2021 15:25:12 +1000 Subject: [PATCH] GS: Use hardware point/line expansion where supported in GL --- bin/resources/shaders/opengl/tfx_vgs.glsl | 4 +++ pcsx2/GS/Renderers/Common/GSDevice.h | 6 ++++- pcsx2/GS/Renderers/DX11/GSDevice11.cpp | 2 ++ pcsx2/GS/Renderers/HW/GSRendererNew.cpp | 25 ++++++++++++++---- pcsx2/GS/Renderers/OpenGL/GLState.cpp | 3 +++ pcsx2/GS/Renderers/OpenGL/GLState.h | 3 +++ pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp | 32 ++++++++++++++++++++++- pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h | 3 ++- 8 files changed, 70 insertions(+), 8 deletions(-) diff --git a/bin/resources/shaders/opengl/tfx_vgs.glsl b/bin/resources/shaders/opengl/tfx_vgs.glsl index c5f6e2c012..c3dcd7489b 100644 --- a/bin/resources/shaders/opengl/tfx_vgs.glsl +++ b/bin/resources/shaders/opengl/tfx_vgs.glsl @@ -67,6 +67,10 @@ void vs_main() VSout.c = i_c; VSout.t_float.z = i_f.x; // pack for with texture + + #if VS_POINT_SIZE + gl_PointSize = float(VS_POINT_SIZE_VALUE); + #endif } #endif diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index c2e749c6bb..c04adf9187 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -165,6 +165,7 @@ struct alignas(16) GSHWDrawConfig u8 fst : 1; u8 tme : 1; u8 iip : 1; + u8 point_size : 1; ///< Set when points need to be expanded without geometry shader. u8 _free : 1; }; u8 key; @@ -471,7 +472,8 @@ struct alignas(16) GSHWDrawConfig bool require_full_barrier; ///< Require texture barrier between all prims DestinationAlphaMode destination_alpha; - bool datm; + bool datm : 1; + bool line_expand : 1; struct AlphaSecondPass { @@ -496,6 +498,8 @@ public: bool image_load_store : 1; ///< Supports atomic min and max on images (for use with prim tracking destination alpha algorithm) bool texture_barrier : 1; ///< Supports sampling rt and hopefully texture barrier bool provoking_vertex_last: 1; ///< Supports using the last vertex in a primitive as the value for flat shading. + bool point_expand : 1; ///< Supports point expansion in hardware without using geometry shaders. + bool line_expand : 1; ///< Supports line expansion in hardware without using geometry shaders. FeatureSupport() { memset(this, 0, sizeof(*this)); diff --git a/pcsx2/GS/Renderers/DX11/GSDevice11.cpp b/pcsx2/GS/Renderers/DX11/GSDevice11.cpp index 81bae29849..74d1fb69a3 100644 --- a/pcsx2/GS/Renderers/DX11/GSDevice11.cpp +++ b/pcsx2/GS/Renderers/DX11/GSDevice11.cpp @@ -40,6 +40,8 @@ GSDevice11::GSDevice11() m_features.image_load_store = false; m_features.texture_barrier = false; m_features.provoking_vertex_last = false; + m_features.point_expand = false; + m_features.line_expand = false; } bool GSDevice11::SetFeatureLevel(D3D_FEATURE_LEVEL level, bool compat_mode) diff --git a/pcsx2/GS/Renderers/HW/GSRendererNew.cpp b/pcsx2/GS/Renderers/HW/GSRendererNew.cpp index e4b824cba4..6abd590655 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererNew.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererNew.cpp @@ -55,15 +55,23 @@ void GSRendererNew::SetupIA(const float& sx, const float& sy) for (unsigned int i = 0; i < m_vertex.next; i++) m_vertex.buff[i].UV &= 0x3FEF3FEF; } - const bool unscale_pt_ln = m_userHacks_enabled_unscale_ptln && (GetUpscaleMultiplier() != 1) && m_dev->Features().geometry_shader; + const bool unscale_pt_ln = m_userHacks_enabled_unscale_ptln && (GetUpscaleMultiplier() != 1); + const GSDevice::FeatureSupport features = m_dev->Features(); switch (m_vt.m_primclass) { case GS_POINT_CLASS: if (unscale_pt_ln) { - m_conf.gs.expand = true; - m_conf.cb_vs.point_size = GSVector2(16.0f * sx, 16.0f * sy); + if (features.point_expand) + { + m_conf.vs.point_size = true; + } + else if (features.geometry_shader) + { + m_conf.gs.expand = true; + m_conf.cb_vs.point_size = GSVector2(16.0f * sx, 16.0f * sy); + } } m_conf.gs.topology = GSHWDrawConfig::GSTopology::Point; @@ -74,8 +82,15 @@ void GSRendererNew::SetupIA(const float& sx, const float& sy) case GS_LINE_CLASS: if (unscale_pt_ln) { - m_conf.gs.expand = true; - m_conf.cb_vs.point_size = GSVector2(16.0f * sx, 16.0f * sy); + if (features.line_expand) + { + m_conf.line_expand = true; + } + else if (features.geometry_shader) + { + m_conf.gs.expand = true; + m_conf.cb_vs.point_size = GSVector2(16.0f * sx, 16.0f * sy); + } } m_conf.gs.topology = GSHWDrawConfig::GSTopology::Line; diff --git a/pcsx2/GS/Renderers/OpenGL/GLState.cpp b/pcsx2/GS/Renderers/OpenGL/GLState.cpp index 119cd8e840..2e6659590e 100644 --- a/pcsx2/GS/Renderers/OpenGL/GLState.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GLState.cpp @@ -22,6 +22,9 @@ namespace GLState GSVector2i viewport; GSVector4i scissor; + bool point_size = false; + float line_width = 1.0f; + bool blend; u16 eq_RGB; u16 f_sRGB; diff --git a/pcsx2/GS/Renderers/OpenGL/GLState.h b/pcsx2/GS/Renderers/OpenGL/GLState.h index 25e7350179..e8a63606f9 100644 --- a/pcsx2/GS/Renderers/OpenGL/GLState.h +++ b/pcsx2/GS/Renderers/OpenGL/GLState.h @@ -24,6 +24,9 @@ namespace GLState extern GSVector2i viewport; extern GSVector4i scissor; + extern bool point_size; + extern float line_width; + extern bool blend; extern u16 eq_RGB; extern u16 f_sRGB; diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp index b28eb40a71..a624f7ff31 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp @@ -256,6 +256,15 @@ bool GSDeviceOGL::Create(const WindowInfo& wi) m_features.texture_barrier = true; m_features.provoking_vertex_last = true; + GLint point_range[2] = {}; + GLint line_range[2] = {}; + glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, point_range); + glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, line_range); + m_features.point_expand = (point_range[0] <= m_upscale_multiplier && point_range[1] >= m_upscale_multiplier); + m_features.line_expand = (line_range[0] <= m_upscale_multiplier && line_range[1] >= m_upscale_multiplier); + Console.WriteLn("Using %s for point expansion and %s for line expansion.", + m_features.point_expand ? "hardware" : "geometry shaders", m_features.line_expand ? "hardware" : "geometry shaders"); + { auto shader = Host::ReadResourceFileToString("shaders/opengl/common_header.glsl"); if (!shader.has_value()) @@ -991,7 +1000,10 @@ std::string GSDeviceOGL::GetVSSource(VSSelector sel) #endif std::string macro = format("#define VS_INT_FST %d\n", sel.int_fst) - + format("#define VS_IIP %d\n", sel.iip); + + format("#define VS_IIP %d\n", sel.iip) + + format("#define VS_POINT_SIZE %d\n", sel.point_size); + if (sel.point_size) + macro += format("#define VS_POINT_SIZE_VALUE %d\n", m_upscale_multiplier); std::string src = GenGlslHeader("vs_main", GL_VERTEX_SHADER, macro); src += m_shader_common_header; @@ -1784,6 +1796,7 @@ static GSDeviceOGL::VSSelector convertSel(const GSHWDrawConfig::VSSelector sel) GSDeviceOGL::VSSelector out; out.int_fst = !sel.fst; out.iip = sel.iip; + out.point_size = sel.point_size; return out; } @@ -1892,6 +1905,23 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config) SetupPipeline(psel); + // additional non-pipeline config stuff + const bool point_size_enabled = config.vs.point_size; + if (GLState::point_size != point_size_enabled) + { + if (point_size_enabled) + glEnable(GL_PROGRAM_POINT_SIZE); + else + glDisable(GL_PROGRAM_POINT_SIZE); + GLState::point_size = point_size_enabled; + } + const float line_width = config.line_expand ? static_cast(m_upscale_multiplier) : 1.0f; + if (GLState::line_width != line_width) + { + GLState::line_width = line_width; + glLineWidth(line_width); + } + if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking) { GL_PUSH("Date GL42"); diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h index cd04b3fe6f..8e844797d2 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h @@ -133,7 +133,8 @@ public: { u32 int_fst : 1; u32 iip : 1; - u32 _free : 30; + u32 point_size : 1; + u32 _free : 29; }; u32 key;