RSX: ProgramStateCache logic cleanup and microoptimizations

- Eliminate some redundant checks in fragment and vertex comparison functions
- Add is_any_src_constant optimization, eliminates 1 instruction per loop
This commit is contained in:
Malcolm Jestadt 2025-02-15 21:39:53 -05:00 committed by Elad
parent d891b83e4b
commit 7b9aaacc4b
2 changed files with 12 additions and 24 deletions

View file

@ -3,7 +3,6 @@
#include "Emu/system_config.h" #include "Emu/system_config.h"
#include <stack> #include <stack>
#include "util/v128.hpp"
#if defined(ARCH_X64) #if defined(ARCH_X64)
#include "emmintrin.h" #include "emmintrin.h"
@ -369,13 +368,7 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R
usz instIndex = 0; usz instIndex = 0;
for (unsigned i = 0; i < binary1.data.size() / 4; i++) for (unsigned i = 0; i < binary1.data.size() / 4; i++)
{ {
const auto active = binary1.instruction_mask[instIndex]; if (binary1.instruction_mask[instIndex])
if (active != binary2.instruction_mask[instIndex])
{
return false;
}
if (active)
{ {
const auto inst1 = v128::loadu(instBuffer1, instIndex); const auto inst1 = v128::loadu(instBuffer1, instIndex);
const auto inst2 = v128::loadu(instBuffer2, instIndex); const auto inst2 = v128::loadu(instBuffer2, instIndex);
@ -391,10 +384,10 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R
return true; return true;
} }
bool fragment_program_utils::is_any_src_constant(v128 sourceOperand)
bool fragment_program_utils::is_constant(u32 sourceOperand)
{ {
return ((sourceOperand >> 8) & 0x3) == 2; const u64 masked = sourceOperand._u64[1] & 0x30000000300;
return (sourceOperand._u32[1] & 0x300) == 0x200 || (static_cast<u32>(masked) == 0x200 || static_cast<u32>(masked >> 32) == 0x200);
} }
usz fragment_program_utils::get_fragment_program_ucode_size(const void* ptr) usz fragment_program_utils::get_fragment_program_ucode_size(const void* ptr)
@ -404,12 +397,9 @@ usz fragment_program_utils::get_fragment_program_ucode_size(const void* ptr)
while (true) while (true)
{ {
const v128 inst = v128::loadu(instBuffer, instIndex); const v128 inst = v128::loadu(instBuffer, instIndex);
bool isSRC0Constant = is_constant(inst._u32[1]);
bool isSRC1Constant = is_constant(inst._u32[2]);
bool isSRC2Constant = is_constant(inst._u32[3]);
bool end = (inst._u32[0] >> 8) & 0x1; bool end = (inst._u32[0] >> 8) & 0x1;
if (isSRC0Constant || isSRC1Constant || isSRC2Constant) if (is_any_src_constant(inst))
{ {
instIndex += 2; instIndex += 2;
if (end) if (end)
@ -483,7 +473,7 @@ fragment_program_utils::fragment_program_metadata fragment_program_utils::analys
} }
} }
if (is_constant(inst._u32[1]) || is_constant(inst._u32[2]) || is_constant(inst._u32[3])) if (is_any_src_constant(inst))
{ {
//Instruction references constant, skip one slot occupied by data //Instruction references constant, skip one slot occupied by data
index++; index++;
@ -531,9 +521,7 @@ usz fragment_program_utils::get_fragment_program_ucode_hash(const RSXFragmentPro
acc1 += tmp1; acc1 += tmp1;
instIndex++; instIndex++;
// Skip constants // Skip constants
if (fragment_program_utils::is_constant(inst._u32[1]) || if (fragment_program_utils::is_any_src_constant(inst))
fragment_program_utils::is_constant(inst._u32[2]) ||
fragment_program_utils::is_constant(inst._u32[3]))
instIndex++; instIndex++;
bool end = (inst._u32[0] >> 8) & 0x1; bool end = (inst._u32[0] >> 8) & 0x1;
@ -588,12 +576,10 @@ bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, con
instIndex++; instIndex++;
// Skip constants // Skip constants
if (fragment_program_utils::is_constant(inst1._u32[1]) || if (fragment_program_utils::is_any_src_constant(inst1))
fragment_program_utils::is_constant(inst1._u32[2]) ||
fragment_program_utils::is_constant(inst1._u32[3]))
instIndex++; instIndex++;
const bool end = ((inst1._u32[0] >> 8) & 0x1) && ((inst2._u32[0] >> 8) & 0x1); const bool end = ((inst1._u32[0] >> 8) & 0x1);
if (end) if (end)
{ {
return true; return true;

View file

@ -6,6 +6,7 @@
#include "Utilities/mutex.h" #include "Utilities/mutex.h"
#include "util/logs.hpp" #include "util/logs.hpp"
#include "util/fnv_hash.hpp" #include "util/fnv_hash.hpp"
#include "util/v128.hpp"
#include <span> #include <span>
#include <unordered_map> #include <unordered_map>
@ -61,7 +62,8 @@ namespace program_hash_util
/** /**
* returns true if the given source Operand is a constant * returns true if the given source Operand is a constant
*/ */
static bool is_constant(u32 sourceOperand);
static bool is_any_src_constant(v128 sourceOperand);
static usz get_fragment_program_ucode_size(const void* ptr); static usz get_fragment_program_ucode_size(const void* ptr);