mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 15:31:26 +12:00
rsx: Avoid skipping input mask checks due to static flow control
This commit is contained in:
parent
7ca15c60bb
commit
d523f9cc6b
1 changed files with 44 additions and 23 deletions
|
@ -78,6 +78,7 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert
|
||||||
|
|
||||||
const auto instruction = v128::loadu(&data[current_instruction * 4]);
|
const auto instruction = v128::loadu(&data[current_instruction * 4]);
|
||||||
d1.HEX = instruction._u32[1];
|
d1.HEX = instruction._u32[1];
|
||||||
|
d2.HEX = instruction._u32[2];
|
||||||
d3.HEX = instruction._u32[3];
|
d3.HEX = instruction._u32[3];
|
||||||
|
|
||||||
// Touch current instruction
|
// Touch current instruction
|
||||||
|
@ -86,20 +87,52 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert
|
||||||
instruction_range.second = std::max(current_instruction, instruction_range.second);
|
instruction_range.second = std::max(current_instruction, instruction_range.second);
|
||||||
|
|
||||||
// Whether to check if the current instruction references an input stream
|
// Whether to check if the current instruction references an input stream
|
||||||
bool test_input_read = false;
|
auto input_attribute_ref = [&]()
|
||||||
|
{
|
||||||
|
if (!d1.input_src)
|
||||||
|
{
|
||||||
|
// It is possible to reference ATTR0, but this is mandatory anyway. No need to explicitly test for it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto ref_mask = (1u << d1.input_src);
|
||||||
|
if ((result.referenced_inputs_mask & ref_mask) == 0)
|
||||||
|
{
|
||||||
|
// Type is encoded in the first 2 bits of each block
|
||||||
|
const auto src0 = d2.src0l & 0x3;
|
||||||
|
const auto src1 = d2.src1 & 0x3;
|
||||||
|
const auto src2 = d3.src2l & 0x3;
|
||||||
|
|
||||||
|
if ((src0 == RSX_VP_REGISTER_TYPE_INPUT) ||
|
||||||
|
(src1 == RSX_VP_REGISTER_TYPE_INPUT) ||
|
||||||
|
(src2 == RSX_VP_REGISTER_TYPE_INPUT))
|
||||||
|
{
|
||||||
|
result.referenced_inputs_mask |= ref_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto branch_to = [&](const u32 target)
|
||||||
|
{
|
||||||
|
input_attribute_ref();
|
||||||
|
current_instruction = target;
|
||||||
|
};
|
||||||
|
|
||||||
// Basic vec op analysis, must be done before flow analysis
|
// Basic vec op analysis, must be done before flow analysis
|
||||||
switch (d1.vec_opcode)
|
switch (d1.vec_opcode)
|
||||||
{
|
{
|
||||||
|
case RSX_VEC_OPCODE_NOP:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
case RSX_VEC_OPCODE_TXL:
|
case RSX_VEC_OPCODE_TXL:
|
||||||
{
|
{
|
||||||
d2.HEX = instruction._u32[2];
|
|
||||||
result.referenced_textures_mask |= (1 << d2.tex_num);
|
result.referenced_textures_mask |= (1 << d2.tex_num);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
test_input_read = !!d1.input_src;
|
input_attribute_ref();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,6 +142,10 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert
|
||||||
|
|
||||||
switch (d1.sca_opcode)
|
switch (d1.sca_opcode)
|
||||||
{
|
{
|
||||||
|
case RSX_SCA_OPCODE_NOP:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
case RSX_SCA_OPCODE_BRI:
|
case RSX_SCA_OPCODE_BRI:
|
||||||
{
|
{
|
||||||
d0.HEX = instruction._u32[0];
|
d0.HEX = instruction._u32[0];
|
||||||
|
@ -129,19 +166,18 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert
|
||||||
has_branch_instruction = true;
|
has_branch_instruction = true;
|
||||||
|
|
||||||
d0.HEX = instruction._u32[0];
|
d0.HEX = instruction._u32[0];
|
||||||
d2.HEX = instruction._u32[2];
|
|
||||||
const u32 jump_address = (d0.iaddrh2 << 9) | (d2.iaddrh << 3) | d3.iaddrl;
|
const u32 jump_address = (d0.iaddrh2 << 9) | (d2.iaddrh << 3) | d3.iaddrl;
|
||||||
|
|
||||||
if (function_call)
|
if (function_call)
|
||||||
{
|
{
|
||||||
call_stack.push(current_instruction + 1);
|
call_stack.push(current_instruction + 1);
|
||||||
current_instruction = jump_address;
|
branch_to(jump_address);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (static_jump)
|
else if (static_jump)
|
||||||
{
|
{
|
||||||
// NOTE: This will skip potential jump target blocks between current->target
|
// NOTE: This will skip potential jump target blocks between current->target
|
||||||
current_instruction = jump_address;
|
branch_to(jump_address);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -161,7 +197,7 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
current_instruction = call_stack.top();
|
branch_to(call_stack.top());
|
||||||
call_stack.pop();
|
call_stack.pop();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -170,26 +206,11 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
test_input_read = !!d1.input_src;
|
input_attribute_ref();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_input_read)
|
|
||||||
{
|
|
||||||
// Type is encoded in the first 2 bits of each block
|
|
||||||
d2.HEX = instruction._u32[2];
|
|
||||||
|
|
||||||
const auto src0 = d2.src0l;
|
|
||||||
const auto src1 = d2.src1;
|
|
||||||
const auto src2 = d3.src2l;
|
|
||||||
|
|
||||||
if ((src0 | src1 | src2) & RSX_VP_REGISTER_TYPE_INPUT)
|
|
||||||
{
|
|
||||||
result.referenced_inputs_mask |= (1 << d1.input_src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((d3.end && (fast_exit || current_instruction >= instruction_range.second)) ||
|
if ((d3.end && (fast_exit || current_instruction >= instruction_range.second)) ||
|
||||||
(current_instruction + 1) == rsx::max_vertex_program_instructions)
|
(current_instruction + 1) == rsx::max_vertex_program_instructions)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue