diff --git a/rpcs3/Emu/RSX/GL/GLOverlays.cpp b/rpcs3/Emu/RSX/GL/GLOverlays.cpp index 193339370a..571adc9b97 100644 --- a/rpcs3/Emu/RSX/GL/GLOverlays.cpp +++ b/rpcs3/Emu/RSX/GL/GLOverlays.cpp @@ -395,7 +395,7 @@ namespace gl } } - void ui_overlay_renderer::run(gl::command_context& cmd_, const areau& viewport, GLuint target, rsx::overlays::overlay& ui) + void ui_overlay_renderer::run(gl::command_context& cmd_, const areau& viewport, GLuint target, rsx::overlays::overlay& ui, bool flip_vertically) { program_handle.uniforms["viewport"] = color4f(static_cast(viewport.width()), static_cast(viewport.height()), static_cast(viewport.x1), static_cast(viewport.y1)); program_handle.uniforms["ui_scale"] = color4f(static_cast(ui.virtual_width), static_cast(ui.virtual_height), 1.f, 1.f); @@ -445,12 +445,13 @@ namespace gl } } - rsx::overlays::vertex_options vert_opts; + rsx::overlays::vertex_options vert_opts {}; program_handle.uniforms["vertex_config"] = vert_opts .disable_vertex_snap(cmd.config.disable_vertex_snap) + .enable_vertical_flip(flip_vertically) .get(); - rsx::overlays::fragment_options draw_opts; + rsx::overlays::fragment_options draw_opts {}; program_handle.uniforms["fragment_config"] = draw_opts .texture_mode(texture_mode) .clip_fragments(cmd.config.clip_region) diff --git a/rpcs3/Emu/RSX/GL/GLOverlays.h b/rpcs3/Emu/RSX/GL/GLOverlays.h index 4399993cc7..96478a161e 100644 --- a/rpcs3/Emu/RSX/GL/GLOverlays.h +++ b/rpcs3/Emu/RSX/GL/GLOverlays.h @@ -90,7 +90,7 @@ namespace gl void emit_geometry(gl::command_context& cmd) override; - void run(gl::command_context& cmd, const areau& viewport, GLuint target, rsx::overlays::overlay& ui); + void run(gl::command_context& cmd, const areau& viewport, GLuint target, rsx::overlays::overlay& ui, bool flip_vertically); }; struct video_out_calibration_pass final : public overlay_pass diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index dcadb68700..e8e92a04dc 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -294,7 +294,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) m_overlay_manager->dispose(uids_to_dispose); } - const auto render_overlays = [this, &cmd](gl::texture* dst, const areau& aspect_ratio) + const auto render_overlays = [this, &cmd](gl::texture* dst, const areau& aspect_ratio, bool flip_vertically = false) { if (m_overlay_manager && m_overlay_manager->has_visible()) { @@ -316,7 +316,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) for (const auto& view : m_overlay_manager->get_views()) { - m_ui_renderer.run(cmd, aspect_ratio, target, *view.get()); + m_ui_renderer.run(cmd, aspect_ratio, target, *view.get(), flip_vertically); } } }; @@ -359,7 +359,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) static const position3u offset{}; gl::g_hw_blitter->copy_image(cmd, image_to_flip, tex, 0, 0, offset, offset, { tex->width(), tex->height(), 1 }); - render_overlays(tex, areau(0, 0, image_to_flip->width(), image_to_flip->height())); + render_overlays(tex, areau(0, 0, image_to_flip->width(), image_to_flip->height()), true); m_sshot_fbo.remove(); } diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/OverlayRenderVS.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/OverlayRenderVS.glsl index f0c4844aa0..c583627251 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/OverlayRenderVS.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/OverlayRenderVS.glsl @@ -33,12 +33,14 @@ layout(%push_block) uniform Configuration struct config_t { bool no_vertex_snap; + bool flip_vertically; }; config_t unpack_vertex_options() { config_t result; result.no_vertex_snap = bitfieldExtract(vertex_config, 0, 1) != 0; + result.flip_vertically = bitfieldExtract(vertex_config, 1, 1) != 0; return result; } @@ -47,12 +49,14 @@ vec2 snap_to_grid(const in vec2 normalized) return floor(fma(normalized, viewport.xy, vec2(0.5))) / viewport.xy; } -vec4 clip_to_ndc(const in vec4 coord) +vec4 clip_to_ndc(const in vec4 coord, const in bool flip_vertically) { vec4 ret = (coord * ui_scale.zwzw) / ui_scale.xyxy; #ifndef VULKAN // Flip Y for OpenGL - ret.yw = 1. - ret.yw; + if (!flip_vertically) ret.yw = 1. - ret.yw; +#else + if (flip_vertically) ret.yw = 1. - ret.yw; #endif return ret; } @@ -64,12 +68,13 @@ vec4 ndc_to_window(const in vec4 coord) void main() { + config_t config = unpack_vertex_options(); + tc0.xy = in_pos.zw; color = albedo; - clip_rect = ndc_to_window(clip_to_ndc(clip_bounds)); + clip_rect = ndc_to_window(clip_to_ndc(clip_bounds, config.flip_vertically)); - vec4 pos = vec4(clip_to_ndc(in_pos).xy, 0.5, 1.); - config_t config = unpack_vertex_options(); + vec4 pos = vec4(clip_to_ndc(in_pos, config.flip_vertically).xy, 0.5, 1.); if (!config.no_vertex_snap) { diff --git a/rpcs3/Emu/RSX/Program/RSXOverlay.h b/rpcs3/Emu/RSX/Program/RSXOverlay.h index 99c51a5e92..ebb2071a8b 100644 --- a/rpcs3/Emu/RSX/Program/RSXOverlay.h +++ b/rpcs3/Emu/RSX/Program/RSXOverlay.h @@ -59,12 +59,31 @@ namespace rsx class vertex_options { + private: u32 value = 0; + void set_bit(u32 bit, bool enable) + { + if (enable) + { + value |= (1u << bit); + } + else + { + value &= ~(1u << bit); + } + } + public: vertex_options& disable_vertex_snap(bool enable) { - value = enable ? 1 : 0; + set_bit(0, enable); + return *this; + } + + vertex_options& enable_vertical_flip(bool enable) + { + set_bit(1, enable); return *this; } diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.cpp b/rpcs3/Emu/RSX/VK/VKOverlays.cpp index 3307dc3a48..c7d971a6a1 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.cpp +++ b/rpcs3/Emu/RSX/VK/VKOverlays.cpp @@ -543,7 +543,7 @@ namespace vk push_buf[14] = m_clip_region.x2; push_buf[15] = m_clip_region.y2; - rsx::overlays::vertex_options vert_opts; + rsx::overlays::vertex_options vert_opts {}; const auto vert_config = vert_opts .disable_vertex_snap(m_disable_vertex_snap) .get(); @@ -552,7 +552,7 @@ namespace vk vkCmdPushConstants(cmd, program->layout(), VK_SHADER_STAGE_VERTEX_BIT, 0, 68, push_buf); // 2. Fragment stuff - rsx::overlays::fragment_options frag_opts; + rsx::overlays::fragment_options frag_opts {}; const auto frag_config = frag_opts .texture_mode(m_texture_type) .clip_fragments(m_clip_enabled)