mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 06:21:26 +12:00
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:
parent
d891b83e4b
commit
7b9aaacc4b
2 changed files with 12 additions and 24 deletions
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue