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 <stack>
#include "util/v128.hpp"
#if defined(ARCH_X64)
#include "emmintrin.h"
@ -369,13 +368,7 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R
usz instIndex = 0;
for (unsigned i = 0; i < binary1.data.size() / 4; i++)
{
const auto active = binary1.instruction_mask[instIndex];
if (active != binary2.instruction_mask[instIndex])
{
return false;
}
if (active)
if (binary1.instruction_mask[instIndex])
{
const auto inst1 = v128::loadu(instBuffer1, instIndex);
const auto inst2 = v128::loadu(instBuffer2, instIndex);
@ -391,10 +384,10 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R
return true;
}
bool fragment_program_utils::is_constant(u32 sourceOperand)
bool fragment_program_utils::is_any_src_constant(v128 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)
@ -404,12 +397,9 @@ usz fragment_program_utils::get_fragment_program_ucode_size(const void* ptr)
while (true)
{
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;
if (isSRC0Constant || isSRC1Constant || isSRC2Constant)
if (is_any_src_constant(inst))
{
instIndex += 2;
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
index++;
@ -531,9 +521,7 @@ usz fragment_program_utils::get_fragment_program_ucode_hash(const RSXFragmentPro
acc1 += tmp1;
instIndex++;
// Skip constants
if (fragment_program_utils::is_constant(inst._u32[1]) ||
fragment_program_utils::is_constant(inst._u32[2]) ||
fragment_program_utils::is_constant(inst._u32[3]))
if (fragment_program_utils::is_any_src_constant(inst))
instIndex++;
bool end = (inst._u32[0] >> 8) & 0x1;
@ -588,12 +576,10 @@ bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, con
instIndex++;
// Skip constants
if (fragment_program_utils::is_constant(inst1._u32[1]) ||
fragment_program_utils::is_constant(inst1._u32[2]) ||
fragment_program_utils::is_constant(inst1._u32[3]))
if (fragment_program_utils::is_any_src_constant(inst1))
instIndex++;
const bool end = ((inst1._u32[0] >> 8) & 0x1) && ((inst2._u32[0] >> 8) & 0x1);
const bool end = ((inst1._u32[0] >> 8) & 0x1);
if (end)
{
return true;

View file

@ -6,6 +6,7 @@
#include "Utilities/mutex.h"
#include "util/logs.hpp"
#include "util/fnv_hash.hpp"
#include "util/v128.hpp"
#include <span>
#include <unordered_map>
@ -61,7 +62,8 @@ namespace program_hash_util
/**
* 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);