This prevents "error X5765: Dest register for LRP cannot be the same as first or third source register" in WWE RAW2.

A little background information :

When compiling pixel shaders, to facilitate later optimizations, FixOverusedRegisters() inserts MOV opcodes reading from constant, vertex color or texture registers, and writing to a free R register slot.

In this case, this transformed :

````
lrp r0, c0,r2,c1
````

into

````
mov r0, c0
lrp r0, r0,r2,c1
````

Not only introduces this a completely useless additional MOV (to R0, which is overwritten by the next LRP opcode), but it also results in LRP reading from R0, which is the same register it's writing to, which seems to be forbidden.

This fix prevents that from happening, by not-inserting a MOV when this situation would arise.

It's possible there exist more such scenario's, but let's tackle them when they are reported.

As for the other change in this commit : Instead of repeating a nearly identical while-loop three times, this loop is now wrapped in a for-loop, that handles all three versions (for PARAM_C, PARAM_V and PARAM_T type registers).
This commit is contained in:
patrickvl 2018-10-28 16:06:26 +01:00
parent 8fd6253ad1
commit 36569f0d2e
1 changed files with 24 additions and 52 deletions

View File

@ -5613,63 +5613,35 @@ bool PSH_XBOX_SHADER::FixOverusedRegisters()
int InsertPos = i;
int addressCount = 0;
int total = 0;
while (Intermediate[i].ReadsFromRegister(PARAM_C, -1, addressCount, total) && (addressCount > 1 || total > 2))
{
for (int p = 0; p < PSH_OPCODE_DEFS[Intermediate[i].Opcode]._In; ++p)
// Handle PARAM_C, PARAM_V and PARAM_T (in that order) :
for (int t = PARAM_C; t >= PARAM_T; t--) {
enum PSH_ARGUMENT_TYPE param_t = (enum PSH_ARGUMENT_TYPE)t;
int max_total = (t == PARAM_C) ? 2 : (t == PARAM_V) ? 999 : 1;
int addressCount = 0;
int total = 0;
while (Intermediate[i].ReadsFromRegister(param_t, -1, addressCount, total) && (addressCount > 1 || total > max_total))
{
if (Intermediate[i].Parameters[p].Type == PARAM_C)
for (int p = 0; p < PSH_OPCODE_DEFS[Intermediate[i].Opcode]._In; ++p)
{
int output = NextFreeRegisterFromIndexUntil(i, PARAM_R, i);
if (Intermediate[i].Parameters[p].Type == param_t)
{
int output = NextFreeRegisterFromIndexUntil(i, PARAM_R, i);
Ins.Output[0].SetRegister(PARAM_R, output, 0);
Ins.Parameters[0].SetRegister(Intermediate[i].Parameters[p].Type, Intermediate[i].Parameters[p].Address, 0);
InsertIntermediate(&Ins, InsertPos);
++InsertPos;
// This prevents "error X5765: Dest register for LRP cannot be the same as first or third source register" in WWE RAW2
if (Intermediate[i].Opcode == PO_LRP)
if (Intermediate[i].Output[0].IsRegister(PARAM_R, output, 0))
continue; // for
ReplaceInputRegisterFromIndexOnwards(InsertPos, Intermediate[InsertPos].Parameters[p].Type, Intermediate[InsertPos].Parameters[p].Address, PARAM_R, output, InsertPos);
Result = true;
break;
}
}
}
// This inserts a MOV opcode that writes to R, reading from a C, V or T register
Ins.Output[0].SetRegister(PARAM_R, output, 0);
Ins.Parameters[0].SetRegister(Intermediate[i].Parameters[p].Type, Intermediate[i].Parameters[p].Address, 0);
InsertIntermediate(&Ins, InsertPos);
++InsertPos;
while (Intermediate[i].ReadsFromRegister(PARAM_V, -1, addressCount, total) && (addressCount > 1))
{
for (int p = 0; p < PSH_OPCODE_DEFS[Intermediate[i].Opcode]._In; ++p)
{
if (Intermediate[i].Parameters[p].Type == PARAM_V)
{
int output = NextFreeRegisterFromIndexUntil(i, PARAM_R, i);
Ins.Output[0].SetRegister(PARAM_R, output, 0);
Ins.Parameters[0].SetRegister(Intermediate[i].Parameters[p].Type, Intermediate[i].Parameters[p].Address, 0);
InsertIntermediate(&Ins, InsertPos);
++InsertPos;
ReplaceInputRegisterFromIndexOnwards(InsertPos, Intermediate[InsertPos].Parameters[p].Type, Intermediate[InsertPos].Parameters[p].Address, PARAM_R, output, InsertPos);
Result = true;
break;
}
}
}
while (Intermediate[i].ReadsFromRegister(PARAM_T, -1, addressCount, total) && (addressCount > 1 || total > 1))
{
for (int p = 0; p < PSH_OPCODE_DEFS[Intermediate[i].Opcode]._In; ++p)
{
if (Intermediate[i].Parameters[p].Type == PARAM_T)
{
int output = NextFreeRegisterFromIndexUntil(i, PARAM_R, i);
Ins.Output[0].SetRegister(PARAM_R, output, 0);
Ins.Parameters[0].SetRegister(Intermediate[i].Parameters[p].Type, Intermediate[i].Parameters[p].Address, 0);
InsertIntermediate(&Ins, InsertPos);
++InsertPos;
ReplaceInputRegisterFromIndexOnwards(InsertPos, Intermediate[InsertPos].Parameters[p].Type, Intermediate[InsertPos].Parameters[p].Address, PARAM_R, output, InsertPos);
Result = true;
break;
ReplaceInputRegisterFromIndexOnwards(InsertPos, Intermediate[InsertPos].Parameters[p].Type, Intermediate[InsertPos].Parameters[p].Address, PARAM_R, output, InsertPos);
Result = true;
break;
}
}
}
}