rsx/overlays: Add support for other primitive types other than triangle_strips

This commit is contained in:
kd-11 2019-10-30 18:01:30 +03:00 committed by kd-11
parent e3e7051ed3
commit 78aefe5b5e
3 changed files with 106 additions and 20 deletions

View file

@ -358,7 +358,7 @@ namespace gl
std::unordered_map<u64, std::unique_ptr<gl::texture_view>> temp_view_cache; std::unordered_map<u64, std::unique_ptr<gl::texture_view>> temp_view_cache;
std::unordered_map<u64, std::unique_ptr<gl::texture>> font_cache; std::unordered_map<u64, std::unique_ptr<gl::texture>> font_cache;
std::unordered_map<u64, std::unique_ptr<gl::texture_view>> view_cache; std::unordered_map<u64, std::unique_ptr<gl::texture_view>> view_cache;
bool is_font_draw = false; rsx::overlays::primitive_type m_current_primitive_type = rsx::overlays::primitive_type::quad_list;
ui_overlay_renderer() 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<s32>(type));
}
}
void emit_geometry() override void emit_geometry() override
{ {
if (!is_font_draw) if (m_current_primitive_type == rsx::overlays::primitive_type::quad_list)
{
overlay_pass::emit_geometry();
}
else
{ {
// Emulate quads with disjointed triangle strips
int num_quads = num_drawable_elements / 4; int num_quads = num_drawable_elements / 4;
std::vector<GLint> firsts; std::vector<GLint> firsts;
std::vector<GLsizei> counts; std::vector<GLsizei> counts;
@ -606,6 +624,10 @@ namespace gl
glBindVertexArray(old_vao); glBindVertexArray(old_vao);
} }
else
{
overlay_pass::emit_geometry();
}
} }
void run(const areau& viewport, GLuint target, rsx::overlays::overlay& ui) 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) 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); upload_vertex_data((f32*)cmd.verts.data(), (u32)cmd.verts.size() * 4u);
num_drawable_elements = (u32)cmd.verts.size(); num_drawable_elements = (u32)cmd.verts.size();
is_font_draw = false;
GLint texture_exists = GL_TRUE; GLint texture_exists = GL_TRUE;
switch (cmd.config.texture_ref) switch (cmd.config.texture_ref)
@ -641,7 +663,6 @@ namespace gl
} }
case rsx::overlays::image_resource_id::font_file: case rsx::overlays::image_resource_id::font_file:
{ {
is_font_draw = true;
glBindTexture(GL_TEXTURE_2D, find_font(cmd.config.font_ref)->id()); glBindTexture(GL_TEXTURE_2D, find_font(cmd.config.font_ref)->id());
break; break;
} }

View file

@ -43,6 +43,14 @@ namespace rsx
backbuffer = 255 // Use current backbuffer contents 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 struct vertex
{ {
float values[4]; float values[4];
@ -353,6 +361,8 @@ namespace rsx
{ {
struct command_config struct command_config
{ {
primitive_type primitives = primitive_type::quad_list;
color4f color = { 1.f, 1.f, 1.f, 1.f }; color4f color = { 1.f, 1.f, 1.f, 1.f };
bool pulse_glow = false; bool pulse_glow = false;

View file

@ -26,7 +26,7 @@ namespace vk
VkFilter m_sampler_filter = VK_FILTER_LINEAR; VkFilter m_sampler_filter = VK_FILTER_LINEAR;
u32 m_num_usable_samplers = 1; u32 m_num_usable_samplers = 1;
std::unordered_map<VkRenderPass, std::unique_ptr<vk::glsl::program>> m_program_cache; std::unordered_map<u64, std::unique_ptr<vk::glsl::program>> m_program_cache;
std::unique_ptr<vk::sampler> m_sampler; std::unique_ptr<vk::sampler> m_sampler;
std::unique_ptr<vk::framebuffer> m_draw_fbo; std::unique_ptr<vk::framebuffer> m_draw_fbo;
vk::data_heap m_vao; vk::data_heap m_vao;
@ -37,6 +37,7 @@ namespace vk
std::string fs_src; std::string fs_src;
graphics_pipeline_state renderpass_config; graphics_pipeline_state renderpass_config;
bool multi_primitive = false;
bool initialized = false; bool initialized = false;
bool compiled = false; bool compiled = false;
@ -56,6 +57,25 @@ namespace vk
~overlay_pass() = default; ~overlay_pass() = default;
u64 get_pipeline_key(VkRenderPass pass)
{
if (!multi_primitive)
{
// Default fast path
return reinterpret_cast<u64>(pass);
}
else
{
struct
{
u64 pass_value;
u64 config;
}
key{ reinterpret_cast<uintptr_t>(pass), static_cast<u64>(renderpass_config.ia.topology) };
return rpcs3::hash_struct(key);
}
}
void check_heap() void check_heap()
{ {
if (!m_vao.heap) if (!m_vao.heap)
@ -157,7 +177,7 @@ namespace vk
m_vao.unmap(); m_vao.unmap();
} }
vk::glsl::program* build_pipeline(VkRenderPass render_pass) vk::glsl::program* build_pipeline(u64 storage_key, VkRenderPass render_pass)
{ {
if (!compiled) if (!compiled)
{ {
@ -226,7 +246,7 @@ namespace vk
auto program = std::make_unique<vk::glsl::program>(*m_device, pipeline, get_vertex_inputs(), get_fragment_inputs()); auto program = std::make_unique<vk::glsl::program>(*m_device, pipeline, get_vertex_inputs(), get_fragment_inputs());
auto result = program.get(); auto result = program.get();
m_program_cache[render_pass] = std::move(program); m_program_cache[storage_key] = std::move(program);
return result; return result;
} }
@ -234,11 +254,13 @@ namespace vk
void load_program(vk::command_buffer& cmd, VkRenderPass pass, const std::vector<vk::image_view*>& src) void load_program(vk::command_buffer& cmd, VkRenderPass pass, const std::vector<vk::image_view*>& src)
{ {
vk::glsl::program *program = nullptr; 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()) if (found != m_program_cache.end())
program = found->second.get(); program = found->second.get();
else else
program = build_pipeline(pass); program = build_pipeline(key, pass);
verify(HERE), m_used_descriptors < VK_OVERLAY_MAX_DRAW_CALLS; verify(HERE), m_used_descriptors < VK_OVERLAY_MAX_DRAW_CALLS;
@ -457,6 +479,7 @@ namespace vk
std::unordered_map<u64, std::unique_ptr<vk::image_view>> view_cache; std::unordered_map<u64, std::unique_ptr<vk::image_view>> view_cache;
std::unordered_map<u64, std::pair<u32, std::unique_ptr<vk::image>>> temp_image_cache; std::unordered_map<u64, std::pair<u32, std::unique_ptr<vk::image>>> temp_image_cache;
std::unordered_map<u64, std::unique_ptr<vk::image_view>> temp_view_cache; std::unordered_map<u64, std::unique_ptr<vk::image_view>> temp_view_cache;
rsx::overlays::primitive_type m_current_primitive_type = rsx::overlays::primitive_type::quad_list;
ui_overlay_renderer() ui_overlay_renderer()
{ {
@ -573,6 +596,9 @@ namespace vk
" ocol = sample_image(fs0, tc0, parameters2.x).bgra * diff_color;\n" " ocol = sample_image(fs0, tc0, parameters2.x).bgra * diff_color;\n"
"}\n"; "}\n";
// Allow mixed primitive rendering
multi_primitive = true;
renderpass_config.set_attachment_count(1); renderpass_config.set_attachment_count(1);
renderpass_config.set_color_mask(0, true, true, true, true); renderpass_config.set_color_mask(0, true, true, true, true);
renderpass_config.set_depth_mask(false); renderpass_config.set_depth_mask(false);
@ -745,16 +771,44 @@ namespace vk
m_ubo.unmap(); 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<s32>(type));
}
}
void emit_geometry(vk::command_buffer &cmd) override void emit_geometry(vk::command_buffer &cmd) override
{ {
//Split into groups of 4 if (m_current_primitive_type == rsx::overlays::primitive_type::quad_list)
u32 first = 0;
u32 num_quads = num_drawable_elements / 4;
for (u32 n = 0; n < num_quads; ++n)
{ {
vkCmdDraw(cmd, 4, 1, first, 0); // Emulate quads with disjointed triangle strips
first += 4; 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; const u32 value_count = num_drawable_elements * 4;
upload_vertex_data((f32*)command.verts.data(), value_count); upload_vertex_data((f32*)command.verts.data(), value_count);
set_primitive_type(command.config.primitives);
m_skip_texture_read = false; m_skip_texture_read = false;
m_color = command.config.color; m_color = command.config.color;