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.
This commit is contained in:
Eladash 2019-12-07 19:07:58 +02:00 committed by Ivan
parent 6a4ba9d562
commit 7260af032e
4 changed files with 57 additions and 19 deletions

View file

@ -2162,6 +2162,12 @@ namespace rsx
fifo_ret_addr = saved_fifo_ret; fifo_ret_addr = saved_fifo_ret;
std::this_thread::sleep_for(1ms); std::this_thread::sleep_for(1ms);
invalid_command_interrupt_raised = false; 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() u32 thread::get_fifo_cmd()

View file

@ -21,19 +21,18 @@ rsx::primitive_type rsx::to_primitive_type(u8 in)
{ {
switch (in) switch (in)
{ {
case 0: return rsx::primitive_type::invalid; case CELL_GCM_PRIMITIVE_POINTS: return rsx::primitive_type::points;
case 1: return rsx::primitive_type::points; case CELL_GCM_PRIMITIVE_LINES: return rsx::primitive_type::lines;
case 2: return rsx::primitive_type::lines; case CELL_GCM_PRIMITIVE_LINE_LOOP: return rsx::primitive_type::line_loop;
case 3: return rsx::primitive_type::line_loop; case CELL_GCM_PRIMITIVE_LINE_STRIP: return rsx::primitive_type::line_strip;
case 4: return rsx::primitive_type::line_strip; case CELL_GCM_PRIMITIVE_TRIANGLES: return rsx::primitive_type::triangles;
case 5: return rsx::primitive_type::triangles; case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP: return rsx::primitive_type::triangle_strip;
case 6: return rsx::primitive_type::triangle_strip; case CELL_GCM_PRIMITIVE_TRIANGLE_FAN: return rsx::primitive_type::triangle_fan;
case 7: return rsx::primitive_type::triangle_fan; case CELL_GCM_PRIMITIVE_QUADS: return rsx::primitive_type::quads;
case 8: return rsx::primitive_type::quads; case CELL_GCM_PRIMITIVE_QUAD_STRIP: return rsx::primitive_type::quad_strip;
case 9: return rsx::primitive_type::quad_strip; case CELL_GCM_PRIMITIVE_POLYGON: return rsx::primitive_type::polygon;
case 10: return rsx::primitive_type::polygon; default: return rsx::primitive_type::invalid;
} }
fmt::throw_exception("Unknown primitive type %d" HERE, in);
} }
enum enum

View file

@ -449,8 +449,22 @@ enum
enum enum
{ {
// Index Array Type // Index Array Type
CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 = 0, CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 = 0,
CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16 = 1, 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 // GCM Texture

View file

@ -70,7 +70,7 @@ namespace rsx
void semaphore_acquire(thread* rsx, u32 /*_reg*/, u32 arg) 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 u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e());
const auto& sema = vm::_ref<atomic_be_t<u32>>(addr); const auto& sema = vm::_ref<atomic_be_t<u32>>(addr);
@ -125,8 +125,8 @@ namespace rsx
// By avoiding doing this on flip's semaphore release // By avoiding doing this on flip's semaphore release
// We allow last gcm's registers reset to occur in case of a crash // 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 (const bool is_flip_sema = (offset == 0x10 && ctxt == CELL_GCM_CONTEXT_DMA_SEMAPHORE_R);
if (!is_flip_sema) !is_flip_sema && !rsx->in_begin_end)
{ {
rsx->sync_point_request = true; rsx->sync_point_request = true;
} }
@ -464,9 +464,19 @@ namespace rsx
void set_begin_end(thread* rsxthr, u32 _reg, u32 arg) void set_begin_end(thread* rsxthr, u32 _reg, u32 arg)
{ {
if (arg) // Ignore upper bits
if (const u8 prim = static_cast<u8>(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(); rsxthr->begin();
return; return;
} }
@ -496,6 +506,15 @@ namespace rsx
if (!rsx::method_registers.current_draw_clause.empty()) 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(); rsx::method_registers.current_draw_clause.compile();
rsxthr->end(); rsxthr->end();
} }