Ensure correct swizzle is used for instructions that only allow for a single swizzle component
- Updated commented out DXBX method to work with current code structure - Default swizzle to .x component per direct3d documentation (needs further verification) - Updated logic to only apply RSQ swizzle when not already referencing a single component
This commit is contained in:
parent
5c801b2a05
commit
aebfde5df5
|
@ -1128,62 +1128,10 @@ static boolean VshAddInstructionMAC_ARL(VSH_SHADER_INSTRUCTION *pInstruction,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Dxbx addition : Scalar instructions reading from W should read from X instead
|
// Dxbx addition : Scalar instructions reading from W should read from X instead
|
||||||
boolean DxbxFixupScalarParameter(VSH_SHADER_INSTRUCTION *pInstruction,
|
static boolean DxbxFixupScalarParameter(VSH_SHADER_INSTRUCTION *pInstruction,
|
||||||
VSH_XBOX_SHADER *pShader,
|
VSH_XBOX_SHADER *pShader,
|
||||||
VSH_PARAMETER *pParameter)
|
VSH_PARAMETER *pParameter);
|
||||||
{
|
|
||||||
boolean Result;
|
|
||||||
int i;
|
|
||||||
boolean WIsWritten;
|
|
||||||
|
|
||||||
// The DirectX vertex shader language specifies that the exp, log, rcc, rcp, and rsq instructions
|
|
||||||
// all operate on the "w" component of the input. But the microcode versions of these instructions
|
|
||||||
// actually operate on the "x" component of the input.
|
|
||||||
Result = false;
|
|
||||||
|
|
||||||
// Test if this is a scalar instruction :
|
|
||||||
if (pInstruction->ILU in [ILU_RCP, ILU_RCC, ILU_RSQ, ILU_EXP, ILU_LOG])
|
|
||||||
{
|
|
||||||
// Test if this parameter reads all components, including W (TODO : Or should we fixup any W reading swizzle?) :
|
|
||||||
if ((pParameter->Swizzle[0] = SWIZZLE_X)
|
|
||||||
&& (pParameter->Swizzle[1] = SWIZZLE_Y)
|
|
||||||
&& (pParameter->Swizzle[2] = SWIZZLE_Z)
|
|
||||||
&& (pParameter->Swizzle[3] = SWIZZLE_W))
|
|
||||||
{
|
|
||||||
// Also test that the .W component is never written to before:
|
|
||||||
WIsWritten = false;
|
|
||||||
for (i = 0; i < pShader->IntermediateCount; i++)
|
|
||||||
{
|
|
||||||
// Stop when we reached this instruction :
|
|
||||||
if (&(pShader->Intermediate[i]) == pInstruction)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Check if this instruction writes to the .W component of the same input parameter :
|
|
||||||
if (((pShader->Intermediate[i].Output.Type == IMD_OUTPUT_C) && (pParameter->ParameterType == PARAM_C))
|
|
||||||
|| ((pShader->Intermediate[i].Output.Type == IMD_OUTPUT_R) && (pParameter->ParameterType == PARAM_R)))
|
|
||||||
{
|
|
||||||
WIsWritten = (pShader->Intermediate[i].Output.Address == pParameter->Address)
|
|
||||||
&& ((pShader->Intermediate[i].Output.Mask && MASK_W) > 0);
|
|
||||||
if (WIsWritten)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!WIsWritten)
|
|
||||||
{
|
|
||||||
// Change the read from W into a read from X (this fixes the XDK VolumeLight sample) :
|
|
||||||
VshSetSwizzle(pParameter, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
|
|
||||||
DbgVshPrintf("Dxbx fixup on scalar instruction applied; Changed read of uninitialized W into a read of X!\n");
|
|
||||||
Result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static boolean VshAddInstructionILU_R(VSH_SHADER_INSTRUCTION *pInstruction,
|
static boolean VshAddInstructionILU_R(VSH_SHADER_INSTRUCTION *pInstruction,
|
||||||
VSH_XBOX_SHADER *pShader,
|
VSH_XBOX_SHADER *pShader,
|
||||||
|
@ -1195,10 +1143,9 @@ static boolean VshAddInstructionILU_R(VSH_SHADER_INSTRUCTION *pInstruction,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO
|
|
||||||
// Dxbx note : Scalar instructions read from C, but use X instead of W, fix that :
|
// Dxbx note : Scalar instructions read from C, but use X instead of W, fix that :
|
||||||
DxbxFixupScalarParameter(pInstruction, pShader, &pInstruction.C);
|
DxbxFixupScalarParameter(pInstruction, pShader, &pInstruction->C);
|
||||||
*/
|
|
||||||
pIntermediate = VshNewIntermediate(pShader);
|
pIntermediate = VshNewIntermediate(pShader);
|
||||||
pIntermediate->IsCombined = IsCombined;
|
pIntermediate->IsCombined = IsCombined;
|
||||||
|
|
||||||
|
@ -1302,16 +1249,25 @@ static void VshConvertToIntermediate(VSH_SHADER_INSTRUCTION *pInstruction,
|
||||||
(void)VshAddInstructionILU_O(pInstruction, pShader, IsCombined);
|
(void)VshAddInstructionILU_O(pInstruction, pShader, IsCombined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void VshSetSwizzle(VSH_PARAMETER *pParameter,
|
||||||
|
VSH_SWIZZLE x,
|
||||||
|
VSH_SWIZZLE y,
|
||||||
|
VSH_SWIZZLE z,
|
||||||
|
VSH_SWIZZLE w)
|
||||||
|
{
|
||||||
|
pParameter->Swizzle[0] = x;
|
||||||
|
pParameter->Swizzle[1] = y;
|
||||||
|
pParameter->Swizzle[2] = z;
|
||||||
|
pParameter->Swizzle[3] = w;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void VshSetSwizzle(VSH_IMD_PARAMETER *pParameter,
|
static inline void VshSetSwizzle(VSH_IMD_PARAMETER *pParameter,
|
||||||
VSH_SWIZZLE x,
|
VSH_SWIZZLE x,
|
||||||
VSH_SWIZZLE y,
|
VSH_SWIZZLE y,
|
||||||
VSH_SWIZZLE z,
|
VSH_SWIZZLE z,
|
||||||
VSH_SWIZZLE w)
|
VSH_SWIZZLE w)
|
||||||
{
|
{
|
||||||
pParameter->Parameter.Swizzle[0] = x;
|
VshSetSwizzle(&pParameter->Parameter, x, y, z, w);
|
||||||
pParameter->Parameter.Swizzle[1] = y;
|
|
||||||
pParameter->Parameter.Swizzle[2] = z;
|
|
||||||
pParameter->Parameter.Swizzle[3] = w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void VshSetOutputMask(VSH_IMD_OUTPUT* pOutput,
|
static inline void VshSetOutputMask(VSH_IMD_OUTPUT* pOutput,
|
||||||
|
@ -1325,6 +1281,45 @@ static inline void VshSetOutputMask(VSH_IMD_OUTPUT* pOutput,
|
||||||
pOutput->Mask[2] = MaskZ;
|
pOutput->Mask[2] = MaskZ;
|
||||||
pOutput->Mask[3] = MaskW;
|
pOutput->Mask[3] = MaskW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dxbx addition : Scalar instructions reading from W should read from X instead
|
||||||
|
static boolean DxbxFixupScalarParameter(VSH_SHADER_INSTRUCTION *pInstruction,
|
||||||
|
VSH_XBOX_SHADER *pShader,
|
||||||
|
VSH_PARAMETER *pParameter)
|
||||||
|
{
|
||||||
|
boolean Result;
|
||||||
|
int i;
|
||||||
|
boolean WIsWritten;
|
||||||
|
boolean XIsWritten;
|
||||||
|
|
||||||
|
// The DirectX vertex shader language specifies that the exp, log, rcc, rcp, and rsq instructions
|
||||||
|
// all operate on the "w" component of the input. But the microcode versions of these instructions
|
||||||
|
// actually operate on the "x" component of the input.
|
||||||
|
Result = false;
|
||||||
|
|
||||||
|
// Test if this is a scalar instruction :
|
||||||
|
if (pInstruction->ILU == ILU_RCP ||
|
||||||
|
pInstruction->ILU == ILU_RCC ||
|
||||||
|
pInstruction->ILU == ILU_RSQ ||
|
||||||
|
pInstruction->ILU == ILU_EXP ||
|
||||||
|
pInstruction->ILU == ILU_LOG)
|
||||||
|
{
|
||||||
|
// Test if this parameter reads all components, including W (TODO : Or should we fixup any W reading swizzle?) :
|
||||||
|
if ((pParameter->Swizzle[0] == SWIZZLE_X)
|
||||||
|
&& (pParameter->Swizzle[1] == SWIZZLE_Y)
|
||||||
|
&& (pParameter->Swizzle[2] == SWIZZLE_Z)
|
||||||
|
&& (pParameter->Swizzle[3] == SWIZZLE_W))
|
||||||
|
{
|
||||||
|
// Change the read from W into a read from X (this fixes the XDK VolumeLight sample) :
|
||||||
|
VshSetSwizzle(pParameter, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
|
||||||
|
DbgVshPrintf("Dxbx fixup on scalar instruction applied; Changed read of uninitialized W into a read of X!\n");
|
||||||
|
Result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
mul oPos.xyz, r12, c-38
|
mul oPos.xyz, r12, c-38
|
||||||
+rcc r1.x, r12.w
|
+rcc r1.x, r12.w
|
||||||
|
@ -1510,30 +1505,35 @@ static boolean VshConvertShader(VSH_XBOX_SHADER *pShader,
|
||||||
pIntermediate->ILU = ILU_RCP;
|
pIntermediate->ILU = ILU_RCP;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix when RSQ reads from unitialized components
|
auto sw = pIntermediate->Parameters[0].Parameter.Swizzle;
|
||||||
if (pIntermediate->InstructionType == IMD_ILU && pIntermediate->ILU == ILU_RSQ) {
|
bool singleSwizzle = sw[0] == sw[1] && sw[1] == sw[2] && sw[2] == sw[3];
|
||||||
int swizzle = (pIntermediate->Output.Mask[0]) | (pIntermediate->Output.Mask[1] << 1) | (pIntermediate->Output.Mask[2] << 2) | (pIntermediate->Output.Mask[3] << 3);
|
|
||||||
switch (swizzle)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
VshSetSwizzle(&pIntermediate->Parameters[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
VshSetSwizzle(&pIntermediate->Parameters[0], SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
VshSetSwizzle(&pIntermediate->Parameters[0], SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
VshSetSwizzle(&pIntermediate->Parameters[0], SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W);
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
default:
|
|
||||||
LOG_TEST_CASE("rsq instruction with invalid swizzle");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!singleSwizzle)
|
||||||
|
{
|
||||||
|
// Fix when RSQ reads from unitialized components
|
||||||
|
if (pIntermediate->InstructionType == IMD_ILU && pIntermediate->ILU == ILU_RSQ) {
|
||||||
|
int swizzle = (pIntermediate->Output.Mask[0]) | (pIntermediate->Output.Mask[1] << 1) | (pIntermediate->Output.Mask[2] << 2) | (pIntermediate->Output.Mask[3] << 3);
|
||||||
|
switch (swizzle)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
VshSetSwizzle(&pIntermediate->Parameters[0], SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
VshSetSwizzle(&pIntermediate->Parameters[0], SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
VshSetSwizzle(&pIntermediate->Parameters[0], SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
VshSetSwizzle(&pIntermediate->Parameters[0], SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W);
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
default:
|
||||||
|
LOG_TEST_CASE("rsq instruction with invalid swizzle");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (pIntermediate->InstructionType == IMD_ILU && pIntermediate->ILU == ILU_EXP)
|
if (pIntermediate->InstructionType == IMD_ILU && pIntermediate->ILU == ILU_EXP)
|
||||||
{
|
{
|
||||||
// EXP on DX8 requires that exactly one swizzle is specified on the output
|
// EXP on DX8 requires that exactly one swizzle is specified on the output
|
||||||
|
|
Loading…
Reference in New Issue