diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index a008e85a20f1..d8c33ae69377 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -487,6 +487,7 @@ target_sources(rpcs3_emu PRIVATE RSX/Overlays/overlay_animation.cpp RSX/Overlays/overlay_controls.cpp RSX/Overlays/overlay_cursor.cpp + RSX/Overlays/overlay_debug_overlay.cpp RSX/Overlays/overlay_edit_text.cpp RSX/Overlays/overlay_fonts.cpp RSX/Overlays/overlay_list_view.cpp diff --git a/rpcs3/Emu/RSX/Common/TextGlyphs.h b/rpcs3/Emu/RSX/Common/TextGlyphs.h deleted file mode 100644 index 7b7cbc890ce6..000000000000 --- a/rpcs3/Emu/RSX/Common/TextGlyphs.h +++ /dev/null @@ -1,252 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "util/types.hpp" - -/** -* FONT GLYPHS GO HERE -* Any font in hex format should work here. -* For this case, We're using ANSI 128 characters, but more types can be supported -* -* This example is the GNU unifont glyph set -*/ - -constexpr std::array GNU_UNIFONT_GLYPHS = -{ - "0000 : AAAA00018000000180004A51EA505A51C99E0001800000018000000180005555", - "0001 : AAAA00018000000180003993C252325F8A527193800000018000000180005555", - "0002 : AAAA00018000000180003BA5C124311989247125800000018000000180005555", - "0003 : AAAA00018000000180007BA5C1247919C1247925800000018000000180005555", - "0004 : AAAA000180000001800079BFC2487A49C2487989800000018000000180005555", - "0005 : AAAA00018000000180007A4DC2527B53C2D67A4F800000018000000180005555", - "0006 : AAAA000180000001800031A5CA287A31CA2849A5800000018000000180005555", - "0007 : AAAA000180000001800073D1CA1073D1CA1073DF800000018000000180005555", - "0008 : AAAA00018000000180001E3991401E3191081E71800000018000000180005555", - "0009 : AAAA000180000001800022F9A2203E21A2202221800000018000000180005555", - "000A : AAAA000180000001800020F9A08020F9A0803E81800000018000000180005555", - "000B : AAAA000180000001800022F9A220222194200821800000018000000180005555", - "000C : AAAA00018000000180003EF9A0803EF9A0802081800000018000000180005555", - "000D : AAAA00018000000180001EF1A08820F1A0901E89800000018000000180005555", - "000E : AAAA00018000000180001E71A0881C8982883C71800000018000000180005555", - "000F : AAAA00018000000180001EF9A0201C2182203CF9800000018000000180005555", - "0010 : AAAA0001800000018000391DA510251DA51039DD800000018000000180005555", - "0011 : AAAA00018000000180007189CA184A09CA08719D800000018000000180005555", - "0012 : AAAA00018000000180007199CA044A09CA10719D800000018000000180005555", - "0013 : AAAA00018000000180007199CA044A19CA047199800000018000000180005555", - "0014 : AAAA00018000000180007185CA0C4A15CA1C7185800000018000000180005555", - "0015 : AAAA00018000000180004993EA546A59DBD44A53800000018000000180005555", - "0016 : AAAA00018000000180003453C29A311789127113800000018000000180005555", - "0017 : AAAA00018000000180007BB9C1247939C1247939800000018000000180005555", - "0018 : AAAA00018000000180003325C4B447ADC4A434A5800000018000000180005555", - "0019 : AAAA00018000000180003E89A0D83EA9A0883E89800000018000000180005555", - "001A : AAAA00018000000180003A5DC252325D8A52719D800000018000000180005555", - "001B : AAAA000180000001800079CFC2107991C0507B8F800000018000000180005555", - "001C : AAAA00018000000180001E7190801E61901010E1800000018000000180005555", - "001D : AAAA00018000000180000E719080166192100EE1800000018000000180005555", - "001E : AAAA00018000000180001C7192801C61941012E1800000018000000180005555", - "001F : AAAA000180000001800012719280126192100CE1800000018000000180005555", - "0020 : 00000000000000000000000000000000", - "0021 : 00000000080808080808080008080000", - "0022 : 00002222222200000000000000000000", - "0023 : 000000001212127E24247E4848480000", - "0024 : 00000000083E4948380E09493E080000", - "0025 : 00000000314A4A340808162929460000", - "0026 : 000000001C2222141829454246390000", - "0027 : 00000808080800000000000000000000", - "0028 : 00000004080810101010101008080400", - "0029 : 00000020101008080808080810102000", - "002A : 00000000000008492A1C2A4908000000", - "002B : 0000000000000808087F080808000000", - "002C : 00000000000000000000000018080810", - "002D : 0000000000000000003C000000000000", - "002E : 00000000000000000000000018180000", - "002F : 00000000020204080810102040400000", - "0030 : 00000000182442464A52624224180000", - "0031 : 000000000818280808080808083E0000", - "0032 : 000000003C4242020C102040407E0000", - "0033 : 000000003C4242021C020242423C0000", - "0034 : 00000000040C142444447E0404040000", - "0035 : 000000007E4040407C020202423C0000", - "0036 : 000000001C2040407C424242423C0000", - "0037 : 000000007E0202040404080808080000", - "0038 : 000000003C4242423C424242423C0000", - "0039 : 000000003C4242423E02020204380000", - "003A : 00000000000018180000001818000000", - "003B : 00000000000018180000001808081000", - "003C : 00000000000204081020100804020000", - "003D : 000000000000007E0000007E00000000", - "003E : 00000000004020100804081020400000", - "003F : 000000003C4242020408080008080000", - "0040 : 000000001C224A565252524E201E0000", - "0041 : 0000000018242442427E424242420000", - "0042 : 000000007C4242427C424242427C0000", - "0043 : 000000003C42424040404042423C0000", - "0044 : 00000000784442424242424244780000", - "0045 : 000000007E4040407C404040407E0000", - "0046 : 000000007E4040407C40404040400000", - "0047 : 000000003C424240404E4242463A0000", - "0048 : 00000000424242427E42424242420000", - "0049 : 000000003E08080808080808083E0000", - "004A : 000000001F0404040404044444380000", - "004B : 00000000424448506060504844420000", - "004C : 000000004040404040404040407E0000", - "004D : 00000000424266665A5A424242420000", - "004E : 0000000042626252524A4A4646420000", - "004F : 000000003C42424242424242423C0000", - "0050 : 000000007C4242427C40404040400000", - "0051 : 000000003C4242424242425A663C0300", - "0052 : 000000007C4242427C48444442420000", - "0053 : 000000003C424240300C0242423C0000", - "0054 : 000000007F0808080808080808080000", - "0055 : 000000004242424242424242423C0000", - "0056 : 00000000414141222222141408080000", - "0057 : 00000000424242425A5A666642420000", - "0058 : 00000000424224241818242442420000", - "0059 : 00000000414122221408080808080000", - "005A : 000000007E02020408102040407E0000", - "005B : 0000000E080808080808080808080E00", - "005C : 00000000404020101008080402020000", - "005D : 00000070101010101010101010107000", - "005E : 00001824420000000000000000000000", - "005F : 00000000000000000000000000007F00", - "0060 : 00201008000000000000000000000000", - "0061 : 0000000000003C42023E4242463A0000", - "0062 : 0000004040405C6242424242625C0000", - "0063 : 0000000000003C4240404040423C0000", - "0064 : 0000000202023A4642424242463A0000", - "0065 : 0000000000003C42427E4040423C0000", - "0066 : 0000000C1010107C1010101010100000", - "0067 : 0000000000023A44444438203C42423C", - "0068 : 0000004040405C624242424242420000", - "0069 : 000000080800180808080808083E0000", - "006A : 0000000404000C040404040404044830", - "006B : 00000040404044485060504844420000", - "006C : 000000180808080808080808083E0000", - "006D : 00000000000076494949494949490000", - "006E : 0000000000005C624242424242420000", - "006F : 0000000000003C4242424242423C0000", - "0070 : 0000000000005C6242424242625C4040", - "0071 : 0000000000003A4642424242463A0202", - "0072 : 0000000000005C624240404040400000", - "0073 : 0000000000003C4240300C02423C0000", - "0074 : 000000001010107C10101010100C0000", - "0075 : 000000000000424242424242463A0000", - "0076 : 00000000000042424224242418180000", - "0077 : 00000000000041494949494949360000", - "0078 : 00000000000042422418182442420000", - "0079 : 0000000000004242424242261A02023C", - "007A : 0000000000007E0204081020407E0000", - "007B : 0000000C101008081010080810100C00", - "007C : 00000808080808080808080808080808", - "007D : 00000030080810100808101008083000", - "007E : 00000031494600000000000000000000", - "007F : AAAA000180000001800073D1CA104BD1CA1073DF800000018000000180005555" -}; - -class GlyphManager -{ -private: - - struct glyph - { - u8 character; - u32 glyph_point_offset; - u32 points_count; - std::array plot; - }; - - std::vector glyph_map; - - void decode_glyph_map(const std::array& font_glyphs) - { - glyph_map.reserve(font_glyphs.size()); - - for (const auto &font_glyph : font_glyphs) - { - glyph this_glyph{}; - - const auto index = font_glyph.substr(0, 4); - std::from_chars(index.data(), index.data() + index.size(), this_glyph.character, 16); - - const auto glyph_data = font_glyph.substr(7); - if (glyph_data.length() == 32) - { - for (usz n = 0; n < this_glyph.plot.size(); ++n) - { - const auto line = glyph_data.substr(n * 2, 2); - std::from_chars(line.data(), line.data() + line.size(), this_glyph.plot[n], 16); - } - } - else - { - // TODO: Support 16-wide characters - } - - glyph_map.push_back(this_glyph); - } - } - -public: - - struct glyph_point - { - float x; - float y; - - explicit glyph_point(float _x, float _y) : x(_x), y(_y) - {} - }; - - GlyphManager() - { - decode_glyph_map(GNU_UNIFONT_GLYPHS); - } - - std::vector generate_point_map() - { - std::vector result; - - for (auto &entry : glyph_map) - { - entry.glyph_point_offset = ::size32(result); - - for (usz j = 0; j < entry.plot.size(); ++j) - { - const auto &line = entry.plot[j]; - if (line == 0) - continue; - - for (int i = 0; i < 8; ++i) - { - if (line & (1 << i)) - { - // Font is inverted, so we correct it for conventional renderers - const auto x = static_cast(7 - i); - const auto y = static_cast(15 - j); - result.emplace_back(x, y); - } - } - } - - entry.points_count = ::size32(result) - entry.glyph_point_offset; - } - - return result; - } - - std::unordered_map> get_glyph_offsets() const - { - std::unordered_map> result = {}; - - for (const auto &entry : glyph_map) - { - result[entry.character] = std::make_pair(entry.glyph_point_offset, entry.points_count); - } - - return result; - } -}; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 419d3c73bbbc..94439d4f0831 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -505,7 +505,6 @@ void GLGSRender::on_exit() } m_null_textures.clear(); - m_text_printer.close(); m_gl_texture_cache.destroy(); m_ui_renderer.destroy(); m_video_output_pass.destroy(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 740f36f5bbca..29bb6167334c 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -5,7 +5,6 @@ #include "GLTextureCache.h" #include "GLRenderTargets.h" #include "GLProgramBuffer.h" -#include "GLTextOut.h" #include "GLOverlays.h" #include "GLShaderInterpreter.h" @@ -114,7 +113,6 @@ class GLGSRender : public GSRender, public ::rsx::reports::ZCULL_control bool manually_flush_ring_buffers = false; - gl::text_writer m_text_printer; gl::ui_overlay_renderer m_ui_renderer; gl::video_out_calibration_pass m_video_output_pass; diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index 5fdedf5ee845..77cbbea8abe1 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -2,6 +2,7 @@ #include "GLGSRender.h" #include "Emu/Cell/Modules/cellVideoOut.h" #include "Emu/RSX/Overlays/overlay_manager.h" +#include "Emu/RSX/Overlays/overlay_debug_overlay.h" #include "util/video_provider.h" LOG_CHANNEL(screenshot_log, "SCREENSHOT"); @@ -323,36 +324,8 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) } } - if (g_cfg.video.overlay && gl::get_driver_caps().ARB_shader_draw_parameters_supported) + if (g_cfg.video.overlay) { - if (!m_text_printer.is_enabled()) - { - m_text_printer.init(); - m_text_printer.set_enabled(true); - } - - // Disable depth test - gl_state.depth_func(GL_ALWAYS); - - gl::screen.bind(); - glViewport(0, 0, width, height); - - m_text_printer.set_scale(m_frame->client_device_pixel_ratio()); - - int y_loc = 0; - const auto println = [&](const std::string& text) - { - m_text_printer.print_text(cmd, 4, y_loc, width, height, text); - y_loc += 16; - }; - - println(fmt::format("RSX Load: %3d%%", get_load())); - println(fmt::format("draw calls: %16d", info.stats.draw_calls)); - println(fmt::format("draw call setup: %11dus", info.stats.setup_time)); - println(fmt::format("vertex upload time: %8dus", info.stats.vertex_upload_time)); - println(fmt::format("textures upload time: %6dus", info.stats.textures_upload_time)); - println(fmt::format("draw call execution: %7dus", info.stats.draw_exec_time)); - const auto num_dirty_textures = m_gl_texture_cache.get_unreleased_textures_count(); const auto texture_memory_size = m_gl_texture_cache.get_texture_memory_in_use() / (1024 * 1024); const auto num_flushes = m_gl_texture_cache.get_num_flush_requests(); @@ -365,17 +338,29 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) const auto num_texture_upload_miss = m_gl_texture_cache.get_texture_upload_misses_this_frame(); const auto texture_upload_miss_ratio = m_gl_texture_cache.get_texture_upload_miss_percentage(); const auto texture_copies_ellided = m_gl_texture_cache.get_texture_copies_ellided_this_frame(); - - println(fmt::format("Unreleased textures: %7d", num_dirty_textures)); - println(fmt::format("Texture memory: %12dM", texture_memory_size)); - println(fmt::format("Flush requests: %12d = %2d (%3d%%) hard faults, %2d unavoidable, %2d misprediction(s), %2d speculation(s)", num_flushes, num_misses, cache_miss_ratio, num_unavoidable, num_mispredict, num_speculate)); - println(fmt::format("Texture uploads: %11u (%u from CPU - %02u%%, %u copies avoided)", num_texture_upload, num_texture_upload_miss, texture_upload_miss_ratio, texture_copies_ellided)); - const auto vertex_cache_hit_count = (info.stats.vertex_cache_request_count - info.stats.vertex_cache_miss_count); const auto vertex_cache_hit_ratio = info.stats.vertex_cache_request_count ? (vertex_cache_hit_count * 100) / info.stats.vertex_cache_request_count : 0; - println(fmt::format("Vertex cache hits: %9u/%u (%u%%)", vertex_cache_hit_count, info.stats.vertex_cache_request_count, vertex_cache_hit_ratio)); + + rsx::overlays::set_debug_overlay_text(fmt::format( + "RSX Load: %3d%%\n" + "draw calls: %16d\n" + "draw call setup: %11dus\n" + "vertex upload time: %8dus\n" + "textures upload time: %6dus\n" + "draw call execution: %7dus\n" + "Unreleased textures: %7d\n" + "Texture memory: %12dM\n" + "Flush requests: %12d = %2d (%3d%%) hard faults, %2d unavoidable, %2d misprediction(s), %2d speculation(s)\n" + "Texture uploads: %11u (%u from CPU - %02u%%, %u copies avoided)\n" + "Vertex cache hits: %9u/%u (%u%%)", + get_load(), info.stats.draw_calls, info.stats.setup_time, info.stats.vertex_upload_time, + info.stats.textures_upload_time, info.stats.draw_exec_time, num_dirty_textures, texture_memory_size, + num_flushes, num_misses, cache_miss_ratio, num_unavoidable, num_mispredict, num_speculate, + num_texture_upload, num_texture_upload_miss, texture_upload_miss_ratio, texture_copies_ellided, + vertex_cache_hit_count, info.stats.vertex_cache_request_count, vertex_cache_hit_ratio) + ); } if (gl::debug::g_vis_texture) diff --git a/rpcs3/Emu/RSX/GL/GLTextOut.h b/rpcs3/Emu/RSX/GL/GLTextOut.h deleted file mode 100644 index e288f1ff75e1..000000000000 --- a/rpcs3/Emu/RSX/GL/GLTextOut.h +++ /dev/null @@ -1,214 +0,0 @@ -#pragma once - -#include "util/types.hpp" -#include "GLHelpers.h" -#include "glutils/vao.hpp" -#include "../Common/TextGlyphs.h" -#include -#include -#include - -namespace gl -{ - class text_writer - { - private: - - gl::glsl::program m_program; - gl::glsl::shader m_vs; - gl::glsl::shader m_fs; - - gl::vao m_vao; - gl::buffer m_text_buffer; - std::unordered_map> m_offsets; - - bool initialized = false; - bool enabled = false; - - f32 m_scale = 1.0f; - - void init_program() - { - std::string vs = - { - "#version 420\n" - "#extension GL_ARB_shader_draw_parameters: enable\n" - "layout(location=0) in vec2 pos;\n" - "uniform vec2 offsets[255];\n" - "uniform vec2 scale;\n" - "\n" - "void main()\n" - "{\n" - " vec2 offset = offsets[gl_DrawIDARB];\n" - " gl_Position = vec4(pos, 0., 1.);\n" - " gl_Position.xy = gl_Position.xy * scale + offset;\n" - "}\n" - }; - - std::string fs = - { - "#version 420\n" - "layout(location=0) out vec4 col0;\n" - "uniform vec4 draw_color;\n" - "\n" - "void main()\n" - "{\n" - " col0 = draw_color;\n" - "}\n" - }; - - m_fs.create(::glsl::program_domain::glsl_fragment_program, fs); - m_fs.compile(); - - m_vs.create(::glsl::program_domain::glsl_vertex_program, vs); - m_vs.compile(); - - m_program.create(); - m_program.attach(m_vs); - m_program.attach(m_fs); - m_program.link(); - } - - void load_program(gl::command_context& cmd, float scale_x, float scale_y, float *offsets, usz nb_offsets, color4f color) - { - float scale[] = { scale_x, scale_y }; - - cmd->use_program(m_program.id()); - - m_program.uniforms["draw_color"] = color; - glProgramUniform2fv(m_program.id(), m_program.uniforms["offsets"].location(), static_cast(nb_offsets), offsets); - glProgramUniform2fv(m_program.id(), m_program.uniforms["scale"].location(), 1, scale); - } - - public: - - text_writer() = default; - ~text_writer() = default; - - void init() - { - GlyphManager glyph_source; - auto points = glyph_source.generate_point_map(); - - const usz buffer_size = points.size() * sizeof(GlyphManager::glyph_point); - - m_text_buffer.create(gl::buffer::target::array, buffer_size, points.data(), gl::buffer::memory_type::host_visible); - m_offsets = glyph_source.get_glyph_offsets(); - - //Init VAO - int old_vao; - glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_vao); - - m_vao.create(); - m_vao.bind(); - - //This is saved as part of the bound VAO's state - m_vao.array_buffer = m_text_buffer; - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(GlyphManager::glyph_point), 0); - - glBindVertexArray(old_vao); - - init_program(); - initialized = true; - } - - void set_enabled(bool state) - { - enabled = state; - } - - bool is_enabled() - { - return enabled; - } - - void print_text(gl::command_context& cmd, int x, int y, int target_w, int target_h, const std::string &text, color4f color = { 0.3f, 1.f, 0.3f, 1.f }) - { - if (!enabled) return; - - ensure(initialized); - - std::vector offsets; - std::vector counts; - std::vector shader_offsets; - char *s = const_cast(text.c_str()); - - //Y is in raster coordinates: convert to bottom-left origin - y = (static_cast(target_h / m_scale) - y - 16); - - //Compress [0, w] and [0, h] into range [-1, 1] - float scale_x = m_scale * 2.f / target_w; - float scale_y = m_scale * 2.f / target_h; - - float base_offset = 0.f; - shader_offsets.reserve(text.length() * 2); - - while (u8 offset = static_cast(*s)) - { - bool to_draw = false; //Can be false for space or unsupported characters - - auto o = m_offsets.find(offset); - if (o != m_offsets.end()) - { - if (o->second.second > 0) - { - to_draw = true; - offsets.push_back(o->second.first); - counts.push_back(o->second.second); - } - } - - if (to_draw) - { - //Generate a scale_offset pair for this entry - float offset_x = scale_x * (x + base_offset); - offset_x -= 1.f; - - float offset_y = scale_y * y; - offset_y -= 1.f; - - shader_offsets.push_back(offset_x); - shader_offsets.push_back(offset_y); - } - - base_offset += 9.f; - s++; - } - - //TODO: Add drop shadow if deemed necessary for visibility - - int old_vao; - glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_vao); - - load_program(cmd, scale_x, scale_y, shader_offsets.data(), counts.size(), color); - cmd->clip_planes(GL_NONE); - - m_vao.bind(); - - glMultiDrawArrays(GL_POINTS, offsets.data(), counts.data(), static_cast(counts.size())); - glBindVertexArray(old_vao); - } - - void close() - { - if (initialized) - { - m_text_buffer.remove(); - m_vao.remove(); - - m_program.remove(); - m_fs.remove(); - m_vs.remove(); - - initialized = false; - } - } - - void set_scale(double scale) - { - // Restrict scale to 2. The dots are gonna be too sparse otherwise. - m_scale = std::min(static_cast(scale), 2.0f); - } - }; -} diff --git a/rpcs3/Emu/RSX/GSFrameBase.h b/rpcs3/Emu/RSX/GSFrameBase.h index e81aa5525332..2834b44df82e 100644 --- a/rpcs3/Emu/RSX/GSFrameBase.h +++ b/rpcs3/Emu/RSX/GSFrameBase.h @@ -25,7 +25,6 @@ class GSFrameBase virtual void flip(draw_context_t ctx, bool skip_frame = false) = 0; virtual int client_width() = 0; virtual int client_height() = 0; - virtual double client_device_pixel_ratio() const = 0; virtual display_handle_t handle() const = 0; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.cpp b/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.cpp new file mode 100644 index 000000000000..31fde89f2926 --- /dev/null +++ b/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.cpp @@ -0,0 +1,81 @@ +#include "stdafx.h" +#include "overlay_manager.h" +#include "overlay_debug_overlay.h" +#include "Emu/system_config.h" + +namespace rsx +{ + namespace overlays + { + debug_overlay::debug_overlay() + { + text_display.set_size(1260, 40); + text_display.set_pos(10, 10); + text_display.set_font("n023055ms.ttf", 10); + text_display.align_text(overlay_element::text_align::left); + text_display.set_wrap_text(true); + text_display.fore_color = { 0.3f, 1.f, 0.3f, 1.f }; + text_display.back_color.a = 0.f; + } + + compiled_resource debug_overlay::get_compiled() + { + if (!visible) + { + return {}; + } + + if (const auto [dirty, text] = text_guard.get_text(); dirty) + { + text_display.set_text(text); + } + + compiled_resource result; + result.add(text_display.get_compiled()); + return result; + } + + void debug_overlay::set_text(std::string&& text) + { + text_guard.set_text(std::move(text)); + visible = true; + } + + extern void reset_debug_overlay() + { + if (!g_cfg.misc.use_native_interface) + return; + + if (auto manager = g_fxo->try_get()) + { + auto overlay = manager->get(); + + if (g_cfg.video.overlay) + { + if (!overlay) + { + overlay = manager->create(); + } + } + else if (overlay) + { + manager->remove(); + } + } + } + + extern void set_debug_overlay_text(std::string&& text) + { + if (!g_cfg.misc.use_native_interface || !g_cfg.video.overlay) + return; + + if (auto manager = g_fxo->try_get()) + { + if (auto overlay = manager->get()) + { + overlay->set_text(std::move(text)); + } + } + } + } // namespace overlays +} // namespace rsx diff --git a/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.h b/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.h new file mode 100644 index 000000000000..202aeea2c5b6 --- /dev/null +++ b/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.h @@ -0,0 +1,25 @@ +#pragma once + +#include "overlays.h" + +namespace rsx +{ + namespace overlays + { + class debug_overlay : public user_interface + { + label text_display; + text_guard_t text_guard{}; + + public: + debug_overlay(); + + compiled_resource get_compiled() override; + + void set_text(std::string&& text); + }; + + void reset_debug_overlay(); + void set_debug_overlay_text(std::string&& text); + } +} diff --git a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.h b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.h index cfc5d44ebace..301393ee1352 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.h @@ -32,32 +32,6 @@ namespace rsx animation_color_interpolate fade_animation; - struct text_guard_t - { - std::mutex mutex; - std::string text; - bool dirty{false}; - - void set_text(std::string t) - { - std::lock_guard lock(mutex); - text = std::move(t); - dirty = true; - } - - std::pair get_text() - { - if (dirty) - { - std::lock_guard lock(mutex); - dirty = false; - return { true, std::move(text) }; - } - - return { false, {} }; - } - }; - text_guard_t text_guard{}; std::array bar_text_guard{}; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp b/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp index 01a266c73d72..992c4f0fb63d 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_perf_metrics.cpp @@ -878,21 +878,19 @@ namespace rsx if (!g_cfg.misc.use_native_interface) return; - if (auto& manager = g_fxo->get(); g_fxo->is_init()) + if (auto manager = g_fxo->try_get()) { auto& perf_settings = g_cfg.video.perf_overlay; - auto perf_overlay = manager.get(); + auto perf_overlay = manager->get(); if (perf_settings.perf_overlay_enabled) { - const bool existed = !!perf_overlay; - - if (!existed) + if (!perf_overlay) { - perf_overlay = manager.create(); + perf_overlay = manager->create(); } - std::lock_guard lock(manager); + std::lock_guard lock(*manager); perf_overlay->set_detail_level(perf_settings.level); perf_overlay->set_position(perf_settings.position); @@ -912,7 +910,7 @@ namespace rsx } else if (perf_overlay) { - manager.remove(); + manager->remove(); } } } diff --git a/rpcs3/Emu/RSX/Overlays/overlays.h b/rpcs3/Emu/RSX/Overlays/overlays.h index f12d0ed20963..4b93a5421e06 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.h +++ b/rpcs3/Emu/RSX/Overlays/overlays.h @@ -133,5 +133,31 @@ namespace rsx s32 run_input_loop(std::function check_state = nullptr); }; + + struct text_guard_t + { + std::mutex mutex; + std::string text; + bool dirty{false}; + + void set_text(std::string t) + { + std::lock_guard lock(mutex); + text = std::move(t); + dirty = true; + } + + std::pair get_text() + { + if (dirty) + { + std::lock_guard lock(mutex); + dirty = false; + return { true, std::move(text) }; + } + + return { false, {} }; + } + }; } } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 1febc6326084..de304799b86b 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -21,6 +21,7 @@ #include "Emu/Cell/Modules/cellGcmSys.h" #include "util/serialization_ext.hpp" #include "Overlays/overlay_perf_metrics.h" +#include "Overlays/overlay_debug_overlay.h" #include "Overlays/overlay_message.h" #include "Program/GLSLCommon.h" #include "Utilities/date_time.h" @@ -903,6 +904,7 @@ namespace rsx if (!serialized) method_registers.init(); rsx::overlays::reset_performance_overlay(); + rsx::overlays::reset_debug_overlay(); if (!is_initialized) { diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 90e3411680d7..059b46c42120 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -965,9 +965,6 @@ VKGSRender::~VKGSRender() m_stencil_mirror_sampler.reset(); - // Overlay text handler - m_text_writer.reset(); - // Pipeline descriptors m_descriptor_pool.destroy(); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 99fa0827daeb..10731d709de9 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -14,7 +14,6 @@ #include "VKTextureCache.h" #include "VKRenderTargets.h" #include "VKFormats.h" -#include "VKTextOut.h" #include "VKOverlays.h" #include "VKProgramBuffer.h" #include "VKFramebuffer.h" @@ -72,7 +71,6 @@ class VKGSRender : public GSRender, public ::rsx::reports::ZCULL_control std::unique_ptr null_buffer; std::unique_ptr null_buffer_view; - std::unique_ptr m_text_writer; std::unique_ptr m_upscaler; output_scaling_mode m_output_scaling{output_scaling_mode::bilinear}; diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 2f69505b962f..eadc094b7c74 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -3,6 +3,7 @@ #include "vkutils/buffer_object.h" #include "Emu/RSX/Overlays/overlay_manager.h" #include "Emu/RSX/Overlays/overlays.h" +#include "Emu/RSX/Overlays/overlay_debug_overlay.h" #include "Emu/Cell/Modules/cellVideoOut.h" #include "upscalers/bilinear_pass.hpp" @@ -763,32 +764,6 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) if (g_cfg.video.overlay) { - // TODO: Move this to native overlay! It is both faster and easier to manage - if (!m_text_writer) - { - auto key = vk::get_renderpass_key(m_swapchain->get_surface_format()); - m_text_writer = std::make_unique(); - m_text_writer->init(*m_device, vk::get_renderpass(*m_device, key)); - } - - m_text_writer->set_scale(m_frame->client_device_pixel_ratio()); - - int y_loc = 0; - const auto println = [&](const std::string& text) - { - m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 4, y_loc, direct_fbo->width(), direct_fbo->height(), text); - y_loc += 16; - }; - - println(fmt::format("RSX Load: %3d%%", get_load())); - println(fmt::format("draw calls: %17d", info.stats.draw_calls)); - println(fmt::format("submits: %20d", info.stats.submit_count)); - println(fmt::format("draw call setup: %12dus", info.stats.setup_time)); - println(fmt::format("vertex upload time: %9dus", info.stats.vertex_upload_time)); - println(fmt::format("texture upload time: %8dus", info.stats.textures_upload_time)); - println(fmt::format("draw call execution: %8dus", info.stats.draw_exec_time)); - println(fmt::format("submit and flip: %12dus", info.stats.flip_time)); - const auto num_dirty_textures = m_texture_cache.get_unreleased_textures_count(); const auto texture_memory_size = m_texture_cache.get_texture_memory_in_use() / (1024 * 1024); const auto tmp_texture_memory_size = m_texture_cache.get_temporary_memory_in_use() / (1024 * 1024); @@ -802,18 +777,33 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) const auto num_texture_upload_miss = m_texture_cache.get_texture_upload_misses_this_frame(); const auto texture_upload_miss_ratio = m_texture_cache.get_texture_upload_miss_percentage(); const auto texture_copies_ellided = m_texture_cache.get_texture_copies_ellided_this_frame(); - - println(fmt::format("Unreleased textures: %8d", num_dirty_textures)); - println(fmt::format("Texture cache memory: %7dM", texture_memory_size)); - println(fmt::format("Temporary texture memory: %3dM", tmp_texture_memory_size)); - println(fmt::format("Flush requests: %13d = %2d (%3d%%) hard faults, %2d unavoidable, %2d misprediction(s), %2d speculation(s)", num_flushes, num_misses, cache_miss_ratio, num_unavoidable, num_mispredict, num_speculate)); - println(fmt::format("Texture uploads: %12u (%u from CPU - %02u%%, %u copies avoided)", num_texture_upload, num_texture_upload_miss, texture_upload_miss_ratio, texture_copies_ellided)); - const auto vertex_cache_hit_count = (info.stats.vertex_cache_request_count - info.stats.vertex_cache_miss_count); const auto vertex_cache_hit_ratio = info.stats.vertex_cache_request_count ? (vertex_cache_hit_count * 100) / info.stats.vertex_cache_request_count : 0; - println(fmt::format("Vertex cache hits: %10u/%u (%u%%)", vertex_cache_hit_count, info.stats.vertex_cache_request_count, vertex_cache_hit_ratio)); + + rsx::overlays::set_debug_overlay_text(fmt::format( + "RSX Load: %3d%%\n" + "draw calls: %17d\n" + "submits: %20d\n" + "draw call setup: %12dus\n" + "vertex upload time: %9dus\n" + "texture upload time: %8dus\n" + "draw call execution: %8dus\n" + "submit and flip: %12dus\n" + "Unreleased textures: %8d\n" + "Texture cache memory: %7dM\n" + "Temporary texture memory: %3dM\n" + "Flush requests: %13d = %2d (%3d%%) hard faults, %2d unavoidable, %2d misprediction(s), %2d speculation(s)\n" + "Texture uploads: %12u (%u from CPU - %02u%%, %u copies avoided)\n" + "Vertex cache hits: %10u/%u (%u%%)", + get_load(), info.stats.draw_calls, info.stats.submit_count, info.stats.setup_time, info.stats.vertex_upload_time, + info.stats.textures_upload_time, info.stats.draw_exec_time, info.stats.flip_time, + num_dirty_textures, texture_memory_size, tmp_texture_memory_size, + num_flushes, num_misses, cache_miss_ratio, num_unavoidable, num_mispredict, num_speculate, + num_texture_upload, num_texture_upload_miss, texture_upload_miss_ratio, texture_copies_ellided, + vertex_cache_hit_count, info.stats.vertex_cache_request_count, vertex_cache_hit_ratio) + ); } direct_fbo->release(); diff --git a/rpcs3/Emu/RSX/VK/VKTextOut.h b/rpcs3/Emu/RSX/VK/VKTextOut.h deleted file mode 100644 index 1cb45cecd3c4..000000000000 --- a/rpcs3/Emu/RSX/VK/VKTextOut.h +++ /dev/null @@ -1,362 +0,0 @@ -#pragma once -#include "VKVertexProgram.h" -#include "VKFragmentProgram.h" -#include "VKRenderPass.h" -#include "VKPipelineCompiler.h" - -#include "vkutils/framebuffer_object.hpp" - -#include "../Common/TextGlyphs.h" -#include - -namespace vk -{ - class text_writer - { - private: - std::unique_ptr m_vertex_buffer; - std::unique_ptr m_uniforms_buffer; - - std::unique_ptr m_program; - vk::glsl::shader m_vertex_shader; - vk::glsl::shader m_fragment_shader; - - vk::descriptor_pool m_descriptor_pool; - vk::descriptor_set m_descriptor_set; - VkDescriptorSetLayout m_descriptor_layout = nullptr; - VkPipelineLayout m_pipeline_layout = nullptr; - u32 m_used_descriptors = 0; - - VkRenderPass m_render_pass; - VkDevice device = nullptr; - - u32 m_uniform_buffer_offset = 0; - u32 m_uniform_buffer_size = 0; - - f32 m_scale = 1.0f; - - bool initialized = false; - std::unordered_map> m_offsets; - - void init_descriptor_set(vk::render_device &dev) - { - rsx::simple_array descriptor_pools = - { - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 }, - }; - - // Reserve descriptor pools - m_descriptor_pool.create(dev, descriptor_pools); - - // Scale and offset data plus output color - rsx::simple_array bindings = - { - { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .pImmutableSamplers = nullptr - } - }; - m_descriptor_layout = vk::descriptors::create_layout(bindings); - - VkPipelineLayoutCreateInfo layout_info = {}; - layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - layout_info.setLayoutCount = 1; - layout_info.pSetLayouts = &m_descriptor_layout; - - CHECK_RESULT(vkCreatePipelineLayout(dev, &layout_info, nullptr, &m_pipeline_layout)); - } - - void init_program() - { - std::string vs = - { - "#version 450\n" - "#extension GL_ARB_separate_shader_objects : enable\n" - "layout(location=0) in vec2 pos;\n" - "layout(std140, set=0, binding=0) uniform scale_offset_buffer\n" - "{\n" - " vec4 offsets[510];\n" - " vec4 scale;\n" - " vec4 text_color;\n" - "};\n" - "\n" - "layout(location=1) out vec4 draw_color;\n" - "\n" - "void main()\n" - "{\n" - " vec2 offset = offsets[gl_InstanceIndex].xy;\n" - " gl_Position = vec4(pos, 0., 1.);\n" - " gl_Position.xy = gl_Position.xy * scale.xy + offset;\n" - " draw_color = text_color;\n" - "}\n" - }; - - std::string fs = - { - "#version 420\n" - "#extension GL_ARB_separate_shader_objects : enable\n" - "layout(location=1) in vec4 draw_color;\n" - "layout(location=0) out vec4 col0;\n" - "\n" - "void main()\n" - "{\n" - " col0 = draw_color;\n" - "}\n" - }; - - m_vertex_shader.create(::glsl::program_domain::glsl_vertex_program, vs); - m_vertex_shader.compile(); - - m_fragment_shader.create(::glsl::program_domain::glsl_fragment_program, fs); - m_fragment_shader.compile(); - - VkPipelineShaderStageCreateInfo shader_stages[2] = {}; - shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shader_stages[0].module = m_vertex_shader.get_handle(); - shader_stages[0].pName = "main"; - - shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shader_stages[1].module = m_fragment_shader.get_handle(); - shader_stages[1].pName = "main"; - - std::vector dynamic_state_descriptors; - VkPipelineDynamicStateCreateInfo dynamic_state_info = {}; - dynamic_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamic_state_descriptors.push_back(VK_DYNAMIC_STATE_VIEWPORT); - dynamic_state_descriptors.push_back(VK_DYNAMIC_STATE_SCISSOR); - dynamic_state_info.pDynamicStates = dynamic_state_descriptors.data(); - dynamic_state_info.dynamicStateCount = ::size32(dynamic_state_descriptors); - - VkVertexInputAttributeDescription vdesc; - VkVertexInputBindingDescription vbind; - - vdesc.binding = 0; - vdesc.format = VK_FORMAT_R32G32_SFLOAT; - vdesc.location = 0; - vdesc.offset = 0; - - vbind.binding = 0; - vbind.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - vbind.stride = 8; - - VkPipelineVertexInputStateCreateInfo vi = {}; - vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vi.vertexAttributeDescriptionCount = 1; - vi.vertexBindingDescriptionCount = 1; - vi.pVertexAttributeDescriptions = &vdesc; - vi.pVertexBindingDescriptions = &vbind; - - VkPipelineViewportStateCreateInfo vp = {}; - vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vp.scissorCount = 1; - vp.viewportCount = 1; - - VkPipelineMultisampleStateCreateInfo ms = {}; - ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms.pSampleMask = NULL; - ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineInputAssemblyStateCreateInfo ia = {}; - ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; - - VkPipelineRasterizationStateCreateInfo rs = {}; - rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rs.lineWidth = 1.f; - - VkPipelineColorBlendAttachmentState att = {}; - att.colorWriteMask = 0xf; - - VkPipelineColorBlendStateCreateInfo cs = {}; - cs.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - cs.attachmentCount = 1; - cs.pAttachments = &att; - - VkPipelineDepthStencilStateCreateInfo ds = {}; - ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - - VkGraphicsPipelineCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - info.pVertexInputState = &vi; - info.pInputAssemblyState = &ia; - info.pRasterizationState = &rs; - info.pColorBlendState = &cs; - info.pMultisampleState = &ms; - info.pViewportState = &vp; - info.pDepthStencilState = &ds; - info.stageCount = 2; - info.pStages = shader_stages; - info.pDynamicState = &dynamic_state_info; - info.layout = m_pipeline_layout; - info.basePipelineIndex = -1; - info.basePipelineHandle = VK_NULL_HANDLE; - info.renderPass = m_render_pass; - - auto compiler = vk::get_pipe_compiler(); - m_program = compiler->compile(info, m_pipeline_layout, vk::pipe_compiler::COMPILE_INLINE); - } - - void load_program(vk::command_buffer &cmd, float scale_x, float scale_y, const float *offsets, usz nb_offsets, std::array color) - { - ensure(m_used_descriptors < 120); - - m_descriptor_set = m_descriptor_pool.allocate(m_descriptor_layout); - - float scale[] = { scale_x, scale_y }; - float colors[] = { color[0], color[1], color[2], color[3] }; - float* dst = static_cast(m_uniforms_buffer->map(m_uniform_buffer_offset, 8192)); - - //std140 spec demands that arrays be multiples of 16 bytes - for (usz i = 0; i < nb_offsets; ++i) - { - dst[i * 4] = offsets[i * 2]; - dst[i * 4 + 1] = offsets[i * 2 + 1]; - } - - memcpy(&dst[510*4], scale, 8); - memcpy(&dst[511*4], colors, 16); - - m_uniforms_buffer->unmap(); - - m_program->bind_uniform({ m_uniforms_buffer->value, m_uniform_buffer_offset, 8192 }, 0, m_descriptor_set); - m_uniform_buffer_offset = (m_uniform_buffer_offset + 8192) % m_uniform_buffer_size; - - vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_program->pipeline); - m_descriptor_set.bind(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout); - - VkDeviceSize zero = 0; - vkCmdBindVertexBuffers(cmd, 0, 1, &m_vertex_buffer->value, &zero); - } - - public: - - text_writer() = default; - ~text_writer() - { - if (initialized) - { - m_vertex_shader.destroy(); - m_fragment_shader.destroy(); - - vkDestroyDescriptorSetLayout(device, m_descriptor_layout, nullptr); - vkDestroyPipelineLayout(device, m_pipeline_layout, nullptr); - m_descriptor_pool.destroy(); - } - } - - void init(vk::render_device &dev, VkRenderPass render_pass) - { - ensure(render_pass != VK_NULL_HANDLE); - - //At worst case, 1 char = 16*16*8 bytes (average about 24*8), so ~256K for 128 chars. Allocating 512k for verts - //uniform params are 8k in size, allocating for 120 lines (max lines at 4k, one column per row. Can be expanded - m_vertex_buffer = std::make_unique(dev, 524288, dev.get_memory_mapping().host_visible_coherent, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); - m_uniforms_buffer = std::make_unique(dev, 983040, dev.get_memory_mapping().host_visible_coherent, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 0, VMM_ALLOCATION_POOL_UNDEFINED); - - m_render_pass = render_pass; - m_uniform_buffer_size = 983040; - - init_descriptor_set(dev); - init_program(); - - GlyphManager glyph_source; - auto points = glyph_source.generate_point_map(); - const usz buffer_size = points.size() * sizeof(GlyphManager::glyph_point); - - u8* dst = static_cast(m_vertex_buffer->map(0, buffer_size)); - memcpy(dst, points.data(), buffer_size); - m_vertex_buffer->unmap(); - - m_offsets = glyph_source.get_glyph_offsets(); - - device = dev; - initialized = true; - } - - void print_text(vk::command_buffer &cmd, vk::framebuffer &target, int x, int y, int target_w, int target_h, const std::string &text, std::array color = { 0.3f, 1.f, 0.3f, 1.f }) - { - std::vector offsets; - std::vector counts; - std::vector shader_offsets; - char *s = const_cast(text.c_str()); - - //Y is in raster coordinates: convert to bottom-left origin - y = (static_cast(target_h / m_scale) - y - 16); - - //Compress [0, w] and [0, h] into range [-1, 1] - //Flip Y scaling - float scale_x = m_scale * +2.f / target_w; - float scale_y = m_scale * -2.f / target_h; - - float base_offset = 0.f; - shader_offsets.reserve(text.length() * 2); - - while (*s) - { - u8 offset = static_cast(*s); - bool to_draw = false; //Can be false for space or unsupported characters - - auto o = m_offsets.find(offset); - if (o != m_offsets.end()) - { - if (o->second.second > 0) - { - to_draw = true; - offsets.push_back(o->second.first); - counts.push_back(o->second.second); - } - } - - if (to_draw) - { - //Generate a scale_offset pair for this entry - float offset_x = scale_x * (x + base_offset); - offset_x -= 1.f; - - float offset_y = scale_y * y; - offset_y += 1.f; - - shader_offsets.push_back(offset_x); - shader_offsets.push_back(offset_y); - } - - base_offset += 9.f; - s++; - } - - VkViewport vp{}; - vp.width = static_cast(target_w); - vp.height = static_cast(target_h); - vp.minDepth = 0.f; - vp.maxDepth = 1.f; - vkCmdSetViewport(cmd, 0, 1, &vp); - - VkRect2D vs = { {0, 0}, {0u+target_w, 0u+target_h} }; - vkCmdSetScissor(cmd, 0, 1, &vs); - - //TODO: Add drop shadow if deemed necessary for visibility - load_program(cmd, scale_x, scale_y, shader_offsets.data(), counts.size(), color); - - const coordu viewport = { positionu{0u, 0u}, sizeu{target.width(), target.height() } }; - vk::begin_renderpass(cmd, m_render_pass, target.value, viewport); - - for (uint i = 0; i < counts.size(); ++i) - { - vkCmdDraw(cmd, counts[i], 1, offsets[i], i); - } - } - - void set_scale(double scale) - { - // Restrict scale to 2. The dots are gonna be too sparse otherwise. - m_scale = std::min(static_cast(scale), 2.0f); - } - }; -} diff --git a/rpcs3/GLGSRender.vcxproj b/rpcs3/GLGSRender.vcxproj index be8c034d816b..64f197a65b8b 100644 --- a/rpcs3/GLGSRender.vcxproj +++ b/rpcs3/GLGSRender.vcxproj @@ -54,7 +54,6 @@ - diff --git a/rpcs3/GLGSRender.vcxproj.filters b/rpcs3/GLGSRender.vcxproj.filters index f3cc05833dce..52fb34ef4a6c 100644 --- a/rpcs3/GLGSRender.vcxproj.filters +++ b/rpcs3/GLGSRender.vcxproj.filters @@ -58,7 +58,6 @@ - diff --git a/rpcs3/VKGSRender.vcxproj b/rpcs3/VKGSRender.vcxproj index e0080c18d20b..0ed839bb1bb7 100644 --- a/rpcs3/VKGSRender.vcxproj +++ b/rpcs3/VKGSRender.vcxproj @@ -36,7 +36,6 @@ - diff --git a/rpcs3/VKGSRender.vcxproj.filters b/rpcs3/VKGSRender.vcxproj.filters index f0f31f894aa0..ea01969b46dd 100644 --- a/rpcs3/VKGSRender.vcxproj.filters +++ b/rpcs3/VKGSRender.vcxproj.filters @@ -89,7 +89,6 @@ - diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index d95d172d0ac7..d63acdb83c33 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -102,6 +102,7 @@ + @@ -580,6 +581,7 @@ + @@ -832,7 +834,6 @@ - diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 4166ed3b3dc0..e1522df0c73d 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1177,6 +1177,9 @@ Crypto + + Emu\GPU\RSX\Overlays + @@ -1773,9 +1776,6 @@ Emu\GPU\RSX - - Emu\GPU\RSX\Common - Utilities @@ -2398,6 +2398,9 @@ Emu + + Emu\GPU\RSX\Overlays + diff --git a/rpcs3/main_application.cpp b/rpcs3/main_application.cpp index c3d37658ba6b..130f3fdd32eb 100644 --- a/rpcs3/main_application.cpp +++ b/rpcs3/main_application.cpp @@ -50,6 +50,7 @@ namespace audio namespace rsx::overlays { extern void reset_performance_overlay(); + extern void reset_debug_overlay(); } /** Emu.Init() wrapper for user management */ @@ -91,6 +92,7 @@ void main_application::OnEmuSettingsChange() audio::configure_audio(); audio::configure_rsxaudio(); rsx::overlays::reset_performance_overlay(); + rsx::overlays::reset_debug_overlay(); } /** RPCS3 emulator has functions it desires to call from the GUI at times. Initialize them in here. */ diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 4a21bfa1ca18..f89302918037 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -756,11 +756,6 @@ int gs_frame::client_height() return height() * devicePixelRatio(); } -double gs_frame::client_device_pixel_ratio() const -{ - return devicePixelRatio(); -} - void gs_frame::flip(draw_context_t, bool /*skip_frame*/) { static Timer fps_t; diff --git a/rpcs3/rpcs3qt/gs_frame.h b/rpcs3/rpcs3qt/gs_frame.h index a5e69fa958b8..622eaf0d4a53 100644 --- a/rpcs3/rpcs3qt/gs_frame.h +++ b/rpcs3/rpcs3qt/gs_frame.h @@ -89,7 +89,6 @@ class gs_frame : public QWindow, public GSFrameBase void flip(draw_context_t context, bool skip_frame = false) override; int client_width() override; int client_height() override; - double client_device_pixel_ratio() const override; bool event(QEvent* ev) override;