From 5db45c3699a574be7dbe0ee11ab16560a4c5f9ea Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 17 Oct 2017 13:34:44 +0300 Subject: [PATCH] rsx: More fixes - Workaround for AMD glMultiDrawArrays bug - Disable disjoint command submission when multidraw support is disabled --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 37 +++++++++++++++++++++------------ rpcs3/Emu/RSX/GL/GLHelpers.h | 7 +++++++ rpcs3/Emu/RSX/RSXThread.cpp | 1 + rpcs3/Emu/RSX/VK/VKGSRender.cpp | 8 +++++-- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 27b87b3ca9..4df8a407bc 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -497,7 +497,7 @@ void GLGSRender::end() } const GLenum draw_mode = gl::draw_mode(rsx::method_registers.current_draw_clause.primitive); - bool single_draw = rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive; + bool single_draw = !supports_multidraw || (rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive); if (indexed_draw_info) { @@ -546,21 +546,32 @@ void GLGSRender::end() } else { - std::vector firsts; - std::vector counts; - const auto draw_count = rsx::method_registers.current_draw_clause.first_count_commands.size(); - - firsts.reserve(draw_count); - counts.reserve(draw_count); - u32 base_index = rsx::method_registers.current_draw_clause.first_count_commands.front().first; - for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands) + if (gl::get_driver_caps().vendor_AMD == false) { - firsts.push_back(range.first - base_index); - counts.push_back(range.second); - } + std::vector firsts; + std::vector counts; + const auto draw_count = rsx::method_registers.current_draw_clause.first_count_commands.size(); - glMultiDrawArrays(draw_mode, firsts.data(), counts.data(), (GLsizei)draw_count); + firsts.reserve(draw_count); + counts.reserve(draw_count); + + for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands) + { + firsts.push_back(range.first - base_index); + counts.push_back(range.second); + } + + glMultiDrawArrays(draw_mode, firsts.data(), counts.data(), (GLsizei)draw_count); + } + else + { + //MultiDrawArrays is broken on some primitive types using AMD. One known type is GL_TRIANGLE_STRIP but there could be more + for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands) + { + glDrawArrays(draw_mode, range.first - base_index, range.second); + } + } } } diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index 3bcee945b4..efb27fcfe7 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -84,6 +84,7 @@ namespace gl bool NV_texture_barrier_supported = false; bool initialized = false; bool vendor_INTEL = false; + bool vendor_AMD = false; void initialize() { @@ -192,6 +193,12 @@ namespace gl if (!EXT_dsa_supported && glGetTextureImageEXT && glTextureBufferRangeEXT) EXT_dsa_supported = true; } +#ifdef _WIN32 + else if (vendor_string.find("amd") != std::string::npos) + { + vendor_AMD = true; + } +#endif initialized = true; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b5e94d65a8..66cb5d6062 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -595,6 +595,7 @@ namespace rsx bool execute_method_call = true; + //TODO: Flatten draw calls when multidraw is not supported to simplify checking in the end() methods if (supports_multidraw) { //TODO: Make this cleaner diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 26d9b5a81c..487bbe33cc 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1211,8 +1211,12 @@ void VKGSRender::end() } std::optional > index_info = std::get<4>(upload_info); - const bool is_emulated_restart = (index_info && rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart() && rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed); - const bool single_draw = !is_emulated_restart && (rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive); + + bool primitive_emulated = false; + vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive, primitive_emulated); + + const bool is_emulated_restart = (!primitive_emulated && rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart() && rsx::method_registers.current_draw_clause.command == rsx::draw_command::indexed); + const bool single_draw = !supports_multidraw || (!is_emulated_restart && (rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive)); if (!index_info) {