rsx: Program cache fixes

- Reorganize storage hash vs ucode hash
- Scan for actual fragment program start in case leading NOPed code precedes the actual instructions
-- e.g FEAR2 Demo has over 32k of padding before actual program code that messes up hashes
This commit is contained in:
kd-11 2017-12-02 18:20:52 +03:00
parent f5145943b2
commit 90c2324e47
5 changed files with 66 additions and 12 deletions

View file

@ -3,7 +3,7 @@
using namespace program_hash_util;
size_t vertex_program_hash::operator()(const RSXVertexProgram &program) const
size_t vertex_program_utils::get_vertex_program_ucode_hash(const RSXVertexProgram &program)
{
// 64-bit Fowler/Noll/Vo FNV-1a hash code
size_t hash = 0xCBF29CE484222325ULL;
@ -22,6 +22,13 @@ size_t vertex_program_hash::operator()(const RSXVertexProgram &program) const
return hash;
}
size_t vertex_program_storage_hash::operator()(const RSXVertexProgram &program) const
{
size_t hash = vertex_program_utils::get_vertex_program_ucode_hash(program);
hash ^= program.output_mask;
return hash;
}
bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const
{
if (binary1.output_mask != binary2.output_mask)
@ -77,7 +84,24 @@ size_t fragment_program_utils::get_fragment_program_ucode_size(void *ptr)
}
}
size_t fragment_program_hash::operator()(const RSXFragmentProgram& program) const
u32 fragment_program_utils::get_fragment_program_start(void *ptr)
{
const qword *instBuffer = (const qword*)ptr;
size_t instIndex = 0;
while (true)
{
const qword& inst = instBuffer[instIndex];
u32 opcode = inst.word[0] >> 16 & 0x3F;
if (opcode)
break;
instIndex++;
}
return instIndex * 16;
}
size_t fragment_program_utils::get_fragment_program_ucode_hash(const RSXFragmentProgram& program)
{
// 64-bit Fowler/Noll/Vo FNV-1a hash code
size_t hash = 0xCBF29CE484222325ULL;
@ -104,6 +128,21 @@ size_t fragment_program_hash::operator()(const RSXFragmentProgram& program) cons
return 0;
}
size_t fragment_program_storage_hash::operator()(const RSXFragmentProgram& program) const
{
size_t hash = fragment_program_utils::get_fragment_program_ucode_hash(program);
hash ^= program.ctrl;
hash ^= program.texture_dimensions;
hash ^= program.unnormalized_coords;
hash ^= program.back_color_diffuse_output;
hash ^= program.back_color_specular_output;
hash ^= program.front_back_color_enabled;
hash ^= program.shadow_textures;
hash ^= program.redirected_textures;
return hash;
}
bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const
{
if (binary1.ctrl != binary2.ctrl || binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords ||