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;
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()

View File

@ -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

View File

@ -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

View File

@ -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<atomic_be_t<u32>>(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<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();
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();
}