mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
d3d12: Fix hash/compare/getSize for fragment program
It didn't properly take constants into account
This commit is contained in:
parent
d1ebc47867
commit
2ac3c66c80
2 changed files with 40 additions and 15 deletions
|
@ -11,6 +11,8 @@
|
||||||
#include "FragmentProgramDecompiler.h"
|
#include "FragmentProgramDecompiler.h"
|
||||||
#include "Utilities/File.h"
|
#include "Utilities/File.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#pragma comment (lib, "d3dcompiler.lib")
|
#pragma comment (lib, "d3dcompiler.lib")
|
||||||
|
|
||||||
namespace ProgramHashUtil
|
namespace ProgramHashUtil
|
||||||
|
@ -23,10 +25,21 @@ namespace ProgramHashUtil
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
const qword& inst = instBuffer[instIndex];
|
const qword& inst = instBuffer[instIndex];
|
||||||
|
bool isSRC0Constant = ((inst.word[1] >> 8) & 0x3) == 2;
|
||||||
|
bool isSRC1Constant = ((inst.word[2] >> 8) & 0x3) == 2;
|
||||||
|
bool isSRC2Constant = ((inst.word[3] >> 8) & 0x3) == 2;
|
||||||
bool end = (inst.word[0] >> 8) & 0x1;
|
bool end = (inst.word[0] >> 8) & 0x1;
|
||||||
if (end)
|
|
||||||
return (instIndex + 1) * 4 * 4;
|
if (isSRC0Constant || isSRC1Constant || isSRC2Constant)
|
||||||
|
{
|
||||||
|
instIndex += 2;
|
||||||
|
if (end)
|
||||||
|
return instIndex * 4 * 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
instIndex++;
|
instIndex++;
|
||||||
|
if (end)
|
||||||
|
return (instIndex) * 4 * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,8 +101,16 @@ namespace ProgramHashUtil
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FragmentHashUtil
|
struct FragmentProgramUtil
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* returns true if the given source Operand is a constant
|
||||||
|
*/
|
||||||
|
static bool isConstant(u32 sourceOperand)
|
||||||
|
{
|
||||||
|
return ((sourceOperand >> 8) & 0x3) == 2;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RSX fragment program constants are inlined inside shader code.
|
* RSX fragment program constants are inlined inside shader code.
|
||||||
* This function takes an instruction from a fragment program and
|
* This function takes an instruction from a fragment program and
|
||||||
|
@ -114,16 +122,11 @@ namespace ProgramHashUtil
|
||||||
static qword fragmentMaskConstant(const qword &initialQword)
|
static qword fragmentMaskConstant(const qword &initialQword)
|
||||||
{
|
{
|
||||||
qword result = initialQword;
|
qword result = initialQword;
|
||||||
u64 dword0Mask = 0, dword1Mask = 0;;
|
if (isConstant(initialQword.word[1]))
|
||||||
// Check if there is a constant and mask word if there is
|
|
||||||
SRC0 s0 = { initialQword.word[1] };
|
|
||||||
SRC1 s1 = { initialQword.word[2] };
|
|
||||||
SRC2 s2 = { initialQword.word[3] };
|
|
||||||
if (s0.reg_type == 2)
|
|
||||||
result.word[1] = 0;
|
result.word[1] = 0;
|
||||||
if (s1.reg_type == 2)
|
if (isConstant(initialQword.word[2]))
|
||||||
result.word[2] = 0;
|
result.word[2] = 0;
|
||||||
if (s2.reg_type == 2)
|
if (isConstant(initialQword.word[3]))
|
||||||
result.word[3] = 0;
|
result.word[3] = 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -143,13 +146,17 @@ namespace ProgramHashUtil
|
||||||
bool end = (inst.word[0] >> 8) & 0x1;
|
bool end = (inst.word[0] >> 8) & 0x1;
|
||||||
if (end)
|
if (end)
|
||||||
return hash;
|
return hash;
|
||||||
const qword& maskedInst = FragmentHashUtil::fragmentMaskConstant(inst);
|
const qword& maskedInst = FragmentProgramUtil::fragmentMaskConstant(inst);
|
||||||
|
|
||||||
hash ^= maskedInst.dword[0];
|
hash ^= maskedInst.dword[0];
|
||||||
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
|
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
|
||||||
hash ^= maskedInst.dword[1];
|
hash ^= maskedInst.dword[1];
|
||||||
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
|
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
|
||||||
instIndex++;
|
instIndex++;
|
||||||
|
// Skip constants
|
||||||
|
if (FragmentProgramUtil::isConstant(inst.word[1]) ||
|
||||||
|
FragmentProgramUtil::isConstant(inst.word[2]) ||
|
||||||
|
FragmentProgramUtil::isConstant(inst.word[3]))
|
||||||
|
instIndex++;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -170,12 +177,17 @@ namespace ProgramHashUtil
|
||||||
if (end)
|
if (end)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const qword& maskedInst1 = FragmentHashUtil::fragmentMaskConstant(inst1);
|
const qword& maskedInst1 = FragmentProgramUtil::fragmentMaskConstant(inst1);
|
||||||
const qword& maskedInst2 = FragmentHashUtil::fragmentMaskConstant(inst2);
|
const qword& maskedInst2 = FragmentProgramUtil::fragmentMaskConstant(inst2);
|
||||||
|
|
||||||
if (maskedInst1.dword[0] != maskedInst2.dword[0] || maskedInst1.dword[1] != maskedInst2.dword[1])
|
if (maskedInst1.dword[0] != maskedInst2.dword[0] || maskedInst1.dword[1] != maskedInst2.dword[1])
|
||||||
return false;
|
return false;
|
||||||
instIndex++;
|
instIndex++;
|
||||||
|
// Skip constants
|
||||||
|
if (FragmentProgramUtil::isConstant(inst1.word[1]) ||
|
||||||
|
FragmentProgramUtil::isConstant(inst1.word[2]) ||
|
||||||
|
FragmentProgramUtil::isConstant(inst1.word[3]))
|
||||||
|
instIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue