From 7260af032e0922c86b04cb9ced2acd74bd742b7a Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 7 Dec 2019 19:07:58 +0200 Subject: [PATCH] rsx: Ignore or recover from unknown primitives This also fixes a bug when recovering FIFO or creating such recovery point inside in_begin_end == true scope. --- rpcs3/Emu/RSX/RSXThread.cpp | 6 ++++++ rpcs3/Emu/RSX/gcm_enums.cpp | 23 +++++++++++------------ rpcs3/Emu/RSX/gcm_enums.h | 18 ++++++++++++++++-- rpcs3/Emu/RSX/rsx_methods.cpp | 29 ++++++++++++++++++++++++----- 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 53a49914da..9b05a23b89 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2162,6 +2162,12 @@ namespace rsx fifo_ret_addr = saved_fifo_ret; std::this_thread::sleep_for(1ms); invalid_command_interrupt_raised = false; + + if (std::exchange(in_begin_end, false) && !rsx::method_registers.current_draw_clause.empty()) + { + execute_nop_draw(); + rsx::thread::end(); + } } u32 thread::get_fifo_cmd() diff --git a/rpcs3/Emu/RSX/gcm_enums.cpp b/rpcs3/Emu/RSX/gcm_enums.cpp index ae2bb4b644..e5a224af48 100644 --- a/rpcs3/Emu/RSX/gcm_enums.cpp +++ b/rpcs3/Emu/RSX/gcm_enums.cpp @@ -21,19 +21,18 @@ rsx::primitive_type rsx::to_primitive_type(u8 in) { switch (in) { - case 0: return rsx::primitive_type::invalid; - case 1: return rsx::primitive_type::points; - case 2: return rsx::primitive_type::lines; - case 3: return rsx::primitive_type::line_loop; - case 4: return rsx::primitive_type::line_strip; - case 5: return rsx::primitive_type::triangles; - case 6: return rsx::primitive_type::triangle_strip; - case 7: return rsx::primitive_type::triangle_fan; - case 8: return rsx::primitive_type::quads; - case 9: return rsx::primitive_type::quad_strip; - case 10: return rsx::primitive_type::polygon; + case CELL_GCM_PRIMITIVE_POINTS: return rsx::primitive_type::points; + case CELL_GCM_PRIMITIVE_LINES: return rsx::primitive_type::lines; + case CELL_GCM_PRIMITIVE_LINE_LOOP: return rsx::primitive_type::line_loop; + case CELL_GCM_PRIMITIVE_LINE_STRIP: return rsx::primitive_type::line_strip; + case CELL_GCM_PRIMITIVE_TRIANGLES: return rsx::primitive_type::triangles; + case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP: return rsx::primitive_type::triangle_strip; + case CELL_GCM_PRIMITIVE_TRIANGLE_FAN: return rsx::primitive_type::triangle_fan; + case CELL_GCM_PRIMITIVE_QUADS: return rsx::primitive_type::quads; + case CELL_GCM_PRIMITIVE_QUAD_STRIP: return rsx::primitive_type::quad_strip; + case CELL_GCM_PRIMITIVE_POLYGON: return rsx::primitive_type::polygon; + default: return rsx::primitive_type::invalid; } - fmt::throw_exception("Unknown primitive type %d" HERE, in); } enum diff --git a/rpcs3/Emu/RSX/gcm_enums.h b/rpcs3/Emu/RSX/gcm_enums.h index 9b62c86859..1f3929dea2 100644 --- a/rpcs3/Emu/RSX/gcm_enums.h +++ b/rpcs3/Emu/RSX/gcm_enums.h @@ -449,8 +449,22 @@ enum enum { // Index Array Type - CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 = 0, - CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16 = 1, + CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 = 0, + CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16 = 1, +}; + +enum +{ + CELL_GCM_PRIMITIVE_POINTS = 1, + CELL_GCM_PRIMITIVE_LINES = 2, + CELL_GCM_PRIMITIVE_LINE_LOOP = 3, + CELL_GCM_PRIMITIVE_LINE_STRIP = 4, + CELL_GCM_PRIMITIVE_TRIANGLES = 5, + CELL_GCM_PRIMITIVE_TRIANGLE_STRIP= 6, + CELL_GCM_PRIMITIVE_TRIANGLE_FAN = 7, + CELL_GCM_PRIMITIVE_QUADS = 8, + CELL_GCM_PRIMITIVE_QUAD_STRIP = 9, + CELL_GCM_PRIMITIVE_POLYGON = 10, }; // GCM Texture diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 50567624b3..da3c1162a7 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -70,7 +70,7 @@ namespace rsx void semaphore_acquire(thread* rsx, u32 /*_reg*/, u32 arg) { - rsx->sync_point_request = true; + if (!rsx->in_begin_end) rsx->sync_point_request = true; const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e()); const auto& sema = vm::_ref>(addr); @@ -125,8 +125,8 @@ namespace rsx // By avoiding doing this on flip's semaphore release // We allow last gcm's registers reset to occur in case of a crash - const bool is_flip_sema = (offset == 0x10 && ctxt == CELL_GCM_CONTEXT_DMA_SEMAPHORE_R); - if (!is_flip_sema) + if (const bool is_flip_sema = (offset == 0x10 && ctxt == CELL_GCM_CONTEXT_DMA_SEMAPHORE_R); + !is_flip_sema && !rsx->in_begin_end) { rsx->sync_point_request = true; } @@ -464,9 +464,19 @@ namespace rsx void set_begin_end(thread* rsxthr, u32 _reg, u32 arg) { - if (arg) + // Ignore upper bits + if (const u8 prim = static_cast(arg)) { - rsx::method_registers.current_draw_clause.reset(to_primitive_type(arg)); + rsx::method_registers.current_draw_clause.reset(to_primitive_type(prim)); + + if (rsx::method_registers.current_draw_clause.primitive == rsx::primitive_type::invalid) + { + rsxthr->in_begin_end = true; + + LOG_WARNING(RSX, "Invalid NV4097_SET_BEGIN_END value: 0x%x", arg); + return; + } + rsxthr->begin(); return; } @@ -496,6 +506,15 @@ namespace rsx if (!rsx::method_registers.current_draw_clause.empty()) { + if (rsx::method_registers.current_draw_clause.primitive == rsx::primitive_type::invalid) + { + // Recover from invalid primitive only if draw clause is not empty + rsxthr->invalid_command_interrupt_raised = true; + + LOG_ERROR(RSX, "NV4097_SET_BEGIN_END aborted due to invalid primitive!"); + return; + } + rsx::method_registers.current_draw_clause.compile(); rsxthr->end(); }