diff --git a/rpcs3/Emu/RSX/GL/GLOverlays.h b/rpcs3/Emu/RSX/GL/GLOverlays.h index b24c404956..e1da632fe6 100644 --- a/rpcs3/Emu/RSX/GL/GLOverlays.h +++ b/rpcs3/Emu/RSX/GL/GLOverlays.h @@ -358,7 +358,7 @@ namespace gl std::unordered_map> temp_view_cache; std::unordered_map> font_cache; std::unordered_map> view_cache; - bool is_font_draw = false; + rsx::overlays::primitive_type m_current_primitive_type = rsx::overlays::primitive_type::quad_list; ui_overlay_renderer() { @@ -577,14 +577,32 @@ namespace gl } } + void set_primitive_type(rsx::overlays::primitive_type type) + { + m_current_primitive_type = type; + + switch (type) + { + case rsx::overlays::primitive_type::quad_list: + case rsx::overlays::primitive_type::triangle_strip: + primitives = GL_TRIANGLE_STRIP; + break; + case rsx::overlays::primitive_type::line_list: + primitives = GL_LINES; + break; + case rsx::overlays::primitive_type::line_strip: + primitives = GL_LINE_STRIP; + break; + default: + fmt::throw_exception("Unexpected primitive type %d" HERE, static_cast(type)); + } + } + void emit_geometry() override { - if (!is_font_draw) - { - overlay_pass::emit_geometry(); - } - else + if (m_current_primitive_type == rsx::overlays::primitive_type::quad_list) { + // Emulate quads with disjointed triangle strips int num_quads = num_drawable_elements / 4; std::vector firsts; std::vector counts; @@ -606,6 +624,10 @@ namespace gl glBindVertexArray(old_vao); } + else + { + overlay_pass::emit_geometry(); + } } void run(const areau& viewport, GLuint target, rsx::overlays::overlay& ui) @@ -618,9 +640,9 @@ namespace gl for (auto &cmd : ui.get_compiled().draw_commands) { + set_primitive_type(cmd.config.primitives); upload_vertex_data((f32*)cmd.verts.data(), (u32)cmd.verts.size() * 4u); num_drawable_elements = (u32)cmd.verts.size(); - is_font_draw = false; GLint texture_exists = GL_TRUE; switch (cmd.config.texture_ref) @@ -641,7 +663,6 @@ namespace gl } case rsx::overlays::image_resource_id::font_file: { - is_font_draw = true; glBindTexture(GL_TEXTURE_2D, find_font(cmd.config.font_ref)->id()); break; } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_controls.h b/rpcs3/Emu/RSX/Overlays/overlay_controls.h index 6b38caf67b..b7c39302be 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_controls.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_controls.h @@ -43,6 +43,14 @@ namespace rsx backbuffer = 255 // Use current backbuffer contents }; + enum class primitive_type : u8 + { + quad_list = 0, + triangle_strip = 1, + line_list = 2, + line_strip = 3 + }; + struct vertex { float values[4]; @@ -353,6 +361,8 @@ namespace rsx { struct command_config { + primitive_type primitives = primitive_type::quad_list; + color4f color = { 1.f, 1.f, 1.f, 1.f }; bool pulse_glow = false; diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.h b/rpcs3/Emu/RSX/VK/VKOverlays.h index eb321ba64a..e2131832ea 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.h +++ b/rpcs3/Emu/RSX/VK/VKOverlays.h @@ -26,7 +26,7 @@ namespace vk VkFilter m_sampler_filter = VK_FILTER_LINEAR; u32 m_num_usable_samplers = 1; - std::unordered_map> m_program_cache; + std::unordered_map> m_program_cache; std::unique_ptr m_sampler; std::unique_ptr m_draw_fbo; vk::data_heap m_vao; @@ -37,6 +37,7 @@ namespace vk std::string fs_src; graphics_pipeline_state renderpass_config; + bool multi_primitive = false; bool initialized = false; bool compiled = false; @@ -56,6 +57,25 @@ namespace vk ~overlay_pass() = default; + u64 get_pipeline_key(VkRenderPass pass) + { + if (!multi_primitive) + { + // Default fast path + return reinterpret_cast(pass); + } + else + { + struct + { + u64 pass_value; + u64 config; + } + key{ reinterpret_cast(pass), static_cast(renderpass_config.ia.topology) }; + return rpcs3::hash_struct(key); + } + } + void check_heap() { if (!m_vao.heap) @@ -157,7 +177,7 @@ namespace vk m_vao.unmap(); } - vk::glsl::program* build_pipeline(VkRenderPass render_pass) + vk::glsl::program* build_pipeline(u64 storage_key, VkRenderPass render_pass) { if (!compiled) { @@ -226,7 +246,7 @@ namespace vk auto program = std::make_unique(*m_device, pipeline, get_vertex_inputs(), get_fragment_inputs()); auto result = program.get(); - m_program_cache[render_pass] = std::move(program); + m_program_cache[storage_key] = std::move(program); return result; } @@ -234,11 +254,13 @@ namespace vk void load_program(vk::command_buffer& cmd, VkRenderPass pass, const std::vector& src) { vk::glsl::program *program = nullptr; - auto found = m_program_cache.find(pass); + const auto key = get_pipeline_key(pass); + + auto found = m_program_cache.find(key); if (found != m_program_cache.end()) program = found->second.get(); else - program = build_pipeline(pass); + program = build_pipeline(key, pass); verify(HERE), m_used_descriptors < VK_OVERLAY_MAX_DRAW_CALLS; @@ -457,6 +479,7 @@ namespace vk std::unordered_map> view_cache; std::unordered_map>> temp_image_cache; std::unordered_map> temp_view_cache; + rsx::overlays::primitive_type m_current_primitive_type = rsx::overlays::primitive_type::quad_list; ui_overlay_renderer() { @@ -573,6 +596,9 @@ namespace vk " ocol = sample_image(fs0, tc0, parameters2.x).bgra * diff_color;\n" "}\n"; + // Allow mixed primitive rendering + multi_primitive = true; + renderpass_config.set_attachment_count(1); renderpass_config.set_color_mask(0, true, true, true, true); renderpass_config.set_depth_mask(false); @@ -745,16 +771,44 @@ namespace vk m_ubo.unmap(); } + void set_primitive_type(rsx::overlays::primitive_type type) + { + m_current_primitive_type = type; + + switch (type) + { + case rsx::overlays::primitive_type::quad_list: + case rsx::overlays::primitive_type::triangle_strip: + renderpass_config.set_primitive_type(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); + break; + case rsx::overlays::primitive_type::line_list: + renderpass_config.set_primitive_type(VK_PRIMITIVE_TOPOLOGY_LINE_LIST); + break; + case rsx::overlays::primitive_type::line_strip: + renderpass_config.set_primitive_type(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP); + break; + default: + fmt::throw_exception("Unexpected primitive type %d" HERE, static_cast(type)); + } + } + void emit_geometry(vk::command_buffer &cmd) override { - //Split into groups of 4 - u32 first = 0; - u32 num_quads = num_drawable_elements / 4; - - for (u32 n = 0; n < num_quads; ++n) + if (m_current_primitive_type == rsx::overlays::primitive_type::quad_list) { - vkCmdDraw(cmd, 4, 1, first, 0); - first += 4; + // Emulate quads with disjointed triangle strips + u32 first = 0; + u32 num_quads = num_drawable_elements / 4; + + for (u32 n = 0; n < num_quads; ++n) + { + vkCmdDraw(cmd, 4, 1, first, 0); + first += 4; + } + } + else + { + overlay_pass::emit_geometry(cmd); } } @@ -771,6 +825,7 @@ namespace vk const u32 value_count = num_drawable_elements * 4; upload_vertex_data((f32*)command.verts.data(), value_count); + set_primitive_type(command.config.primitives); m_skip_texture_read = false; m_color = command.config.color;