Skip to content

Commit

Permalink
Merge pull request microsoft#80 from microsoft/user/tvandewalle/rcp_f…
Browse files Browse the repository at this point in the history
…ixes

[Translate_RCP] Handle modifiers on src0 before performing movc

The rcp instruction is allowed to have modifiers on src0, such as _abs. When we perform the translation, src0 gets passed as the comparison param for movc, which is not allowed to have modifiers. When we detect that src0 has modifiers present, we need to handle that by doign a mov into a temp register. This was actually done in microsoft#51 , but when CSGO was found to have rendering issues after the changes the movc fix got reverted too (microsoft#55 ).

This PR brings back the movc fixes from those earlier PRs, but doesn't pick up the change to use FLT_MAX.

This is technically not to spec, as we should be using FLT_MAX here.
However, since CSGO (d3d9 version) was found to expect non-FLT_MAX
values when doing an rcp of 0, we're going to keep the out of spec
approach in case other apps have the same expectation.
  • Loading branch information
vdwtanner authored Feb 14, 2024
2 parents f060ab0 + 4d093aa commit 423115b
Showing 1 changed file with 33 additions and 7 deletions.
40 changes: 33 additions & 7 deletions ShaderConverter/ShaderConv/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1506,23 +1506,49 @@ void
CContext::Translate_RCP( const CInstr& instr )
{
// div dest, vec4( 1.0f ), src0
// movc dest, src0, dest, src0

const COperandBase dest = instr.CreateDstOperand();
const COperandBase src0 = this->EmitSrcOperand( instr, 0 );
const DWORD dwToken = instr.GetSrcToken( 0 );
const DWORD dwModifier = ( dwToken & D3DSP_SRCMOD_MASK );

this->EmitDstInstruction( instr.GetModifiers(),
D3D10_SB_OPCODE_DIV,
dest,
COperand( 1.0f ),
src0 );

this->EmitDstInstruction(instr.GetModifiers(),
D3D10_SB_OPCODE_MOVC,
dest,
src0,
dest,
src0 );
// movc doesn't allow modifiers on the comparison param, so if src0 has modifiers we need to apply those and mov into a temp register
// note that according to spec, rcp can only act on scalar values, so we just mov into r0.z
if ( dwModifier != D3DSPSM_NONE )
{
// mov r0.z, src0
// movc dest, r0.z, dest, src0


m_pShaderAsm->EmitInstruction(
CInstruction( D3D10_SB_OPCODE_MOV,
CTempOperandDst( SREG_TMP0, D3D10_SB_OPERAND_4_COMPONENT_MASK_Z ),
src0 ) );

this->EmitDstInstruction( instr.GetModifiers(),
D3D10_SB_OPCODE_MOVC,
dest,
CTempOperand4( SREG_TMP0, __SWIZZLE_Z ),
dest,
src0 );
}
else
{
// movc dest, src0, dest, src0

this->EmitDstInstruction( instr.GetModifiers(),
D3D10_SB_OPCODE_MOVC,
dest,
src0,
dest,
src0 );
}
}

///---------------------------------------------------------------------------
Expand Down

0 comments on commit 423115b

Please sign in to comment.