crosire / d3d8to9

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

A Lighting Delay On Silent Hill 2 #56

Closed CHNSK closed 6 years ago

CHNSK commented 6 years ago

Hey guys, When activate d3d8to9 my flashlight gets lazy casting light on objects, I get a huge delay on lighting things.

sh2

sh21

sh23

elishacloud commented 6 years ago

I am pretty sure the issue here is with the PixelShader. We are removing a modifier from a constant because modifiers are not allowed in constants in d3d9 (unlike d3d8).

There are several PixelShaders with this issue but in Silent Hill 2 they are all almost identical. Here is an example of one:

Redirecting 'IDirect3DDevice8::CreatePixelShader(09956B50, 008A41E0, 01F802C4)' ...
> Disassembling shader and translating assembly to Direct3D 9 compatible code ...
> Dumping translated shader assembly:

    ps_1_1
    tex t0
    tex t1
    tex t2
    dp3_sat r0, t2_bx2, c1 /* removed modifier _bx2 */
    dp3 r1.xyz, t2_bx2, v1_bx2
  + sub r0.w, r0, c2.w /* changed 'add' to 'sub' removed modifier - */
    mul_sat r1.xyz, r1, t0.w
    mul_sat r0.xyz, r0.w, r1
    mul r1.xyz, t1, t0.w
    mad_sat r0.xyz, r0, c2, v0
    mul r0.xyz, r0, t0
  + mov r0.w, t0.w
    mad r0.xyz, r1, c3, r0

// approximately 11 instruction slots used (3 texture, 8 arithmetic)

Notice that the _bx2 modifier is removed. I believe this is what is causing the issue.

Normally the simple solution is to add a new line and use a temporary register in place of the constant so that the modifier can remain. However adding a new line causes the arithmetic instructions to exceed 8, which is the maximum allowed for PixelShader 1.x (except 1.4).

The only other fix I know of would be to convert the shader into ps_1_4 (version 1.4), which is what the ENBSeries DX8 to DX9 Convertor does to solve this type of issue.

Can you check with the ENBSeries convertor to see if the same issue happens?

CHNSK commented 6 years ago

Thanks for the explanation. ENB converter has really solved the issue. Since using ASI Loader's d3d8to9 function I completely forgot ENB. Thanks you Elisha.

elishacloud commented 6 years ago

@Markeron, I am having some trouble reproducing this issue. It seems to be related to 4 specific PixelShaders in the game. All of them are virtually identical to the one I shown above, with only minor differences in the instruction modifier (_sat).

However, I think I have found a generic solution. Below is a quick and dirty patch with the PixelShaders hard coded so we can test it to see if it works. Can you try with this one to see if it fixes the issue?

d3d8.zip

CHNSK commented 6 years ago

It works Eli, the dirty patch fixes the issue.

sh25

The issue comes back if return to 1.6.0.0, with or without sweetfx 1.4

elishacloud commented 6 years ago

@Markeron, I was able to build a fairly simple PixelShader v1.1 to v1.4 translator. I tested with a few games and seems to work. Can you test with this updated one?

d3d8.zip

CHNSK commented 6 years ago

It loads the shader but objects get 'rainbow' colours when they are exposed to flashlight.

insta

elishacloud commented 6 years ago

I believe this one should solve the issue. Can you try it once more?

d3d8.zip

CHNSK commented 6 years ago

It did it. It's working perfectly. Now, also I can run the game in the first attempt! It used to always hang on the black screen and take four or five times to start. Thank you.

elishacloud commented 6 years ago

Very good! This was a pretty big change. I added ~250 lines of code so I want to do an in-depth review of the code and full testing before I create a pull request.

elishacloud commented 6 years ago

This should be fixed with the latest release v1.7.0.