crosire / d3d8to9

A D3D8 pseudo-driver which converts API calls and bytecode shaders to equivalent D3D9 ones.
BSD 2-Clause "Simplified" License
911 stars 83 forks source link

Translation error when moving _bx2 to separate register #70

Closed PatrickvL closed 6 years ago

PatrickvL commented 6 years ago

Pixel shader input :

dp3 r0.rgb, c0_bx2, t0_bx2

d3d8to9 output :

mov r0.xyz, c0 /* added line */
dp3 r0.xyz, r0.xyz_bx2 /* changed c0 to r0.xyz */, t0_bx2

This fails with :

> Failed to reassemble shader :

error X2004 : invalid swizzle 'xyz_bx2'
error X5027 : Invalid src swizzle for first source param.
elishacloud commented 6 years ago

The issue is with this line and this line. I purposely kept the swizzle to try and preserve the original pixel shader functionality. Removing the swizzle has a possibility of changing the final register value, which could cause an issue.

It is pretty easy to remove the swizzle here, but I would need to test many games to ensure that it does not cause any issues. It might be better if I remove the swizzle only in the case where there is a rear modifier, like _bx2 or _bias. However that would require duplicating those lines, which I really don't want to do.

Note: you cannot have both a rear modifier and a swizzle.

elishacloud commented 6 years ago

As I thought, simply removing the swizzle caused issues with True Crime New York City. However I forgot that you can use a rear modifier with a swizzle as long as the swizzle comes last. So it should look like this:

d3d8to9 output :

mov r0.xyz, c0 /* added line */
dp3 r0.xyz, r0_bx2.xyz /* changed c0 to r0.xyz */, t0_bx2

Try with this file and see if it works.

BTW: here is the check-in if you want to test with the source code instead.

PatrickvL commented 6 years ago

This still fails to compile - I had to change the input shader to use an intermediate register to avoid the swizzle;

This problematic input :

dp3 r0.rgb, c0_bx2, t0_bx2

Gets converted to this, which doesn't work :

mov r0.xyz, c0 /* added line */
dp3 r0.xyz, r0_bx2.xyz /* changed c0 to r0.xyz */, t0_bx2

The error is still:

> Failed to reassemble shader :

error X5027 : Invalid src swizzle for first source param.

But when I use this (manually altered) input :

mov r0.rgb, c0
dp3 r0.rgb, r0_bx2, t0_bx2

... d3d8to9 doesn't even need to replace anything for this, as, the result is :

mov r0.xyz, c0
dp3 r0.xyz, r0_bx2, t0_bx2

... which works as intended.

PS: The DirectX 8 doc states that source register modifiers shouldn't be used on constants (because it will cause undefined results), which can be interpreted as : "it may be done, but it's just not advised". So, it's just bad luck I've encountered such a shader here.