narzoul / DDrawCompat

DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11
BSD Zero Clause License
893 stars 67 forks source link

NFS High Stakes bad performance (vanilla game) #166

Closed BEENNath58 closed 8 months ago

BEENNath58 commented 1 year ago

I have tested this game with both DDC and DxWnd native, both have very bad performance. The game setting: Z-Buffer, if disabled, makes the game run slower than "Crysis on Pentium 2". Only dgV2 has acceptable performance.

Can you have a look at the game? It might happen that the game for you, just like mine, crashes with a faulty module "d3da.dll" that belongs to the game, so I use DxWnd to fix everything but not touch the DirectX Graphics part, with the profile: nfshsddc.zip

narzoul commented 1 year ago

Game runs fine on my end, both with software and hardware rendering, on maxed in-game settings. I used the "Special Installer" from myabandonware, no idea where they got it from. Didn't need DxWnd either. Why would you disable Z-Buffer? Of course, that could decrease performance, I didn't even try turning it off.

BEENNath58 commented 1 year ago

I used the "Special Installer" from myabandonware

When I meant "vanilla game", I meant to say not to use that installer. If you read the new installer details, it mentions the replacement of "d3da.dll" with a new DX7 renderer.

Here's the problem, the DX7 renderer, as I have seen, is copied from the next game Porsche Unleashed. PU is itself problematic, on my Intel HD Graphics it causes major artifacting, and copying the same d3da.dll file to High Stakes on the same machine crashes the game with the exception being in d3da.dll.

So that's why I am asking for the vanilla game. The PC where I am writing from, has all the renderers (DX6.1, DX7, DX9) working correctly, but not all machines and drivers are same.

DxWnd manages the exception with the DX6.1 d3da.dll wonderfully, at least on both of my systems, but regardless of putting DDC or not, the performance is awful.

Note: If you don't have the CD, what I did was download a B6I/B6T combination (don't remember from where, old games ru or myabandonware?) and just install the official v4.5 patch. This prevents the need of having a no-CD, but you'll need DAEMON Tools to mount.

narzoul commented 1 year ago

I just continued using the special installer and only replaced the d3da.dll with the older one from the v4.5 patch, which seems to be enough to reproduce the performance issues. I used single race mode with the default "Celtic Ruins" track and maxed in-game graphics settings at 640x480 (resolution scaled to 1920x1080).

With the DX7 renderer, FPS is already maxed at 64 throughout the whole track, but with DX6 it rarely gets maxed and drops to as low as 20 in some parts of the track. The issue is that the game uses video memory vertex buffers, locked after pretty much every single draw call, and with not very GPU-friendly flags either (e.g. no DISCARDCONTENTS or NOOVERWRITE flags). This causes a flush and synchronization after each draw call. The simplest solution is to force the game to use system memory vertex buffers instead.

The crash is caused by too many enumerated texture formats. The game only seems to support a maximum of 14. The 15th one overwrites some other data, replacing (amongst other things) a null pointer with some garbage value (0x4 in my case), which the game tries to read from later.

For now, I just removed all the FOURCC texture formats from enumeration, which reduces the number of texture formats to 12 in my case, so DxWnd is not required. Hopefully, it's enough for your GPU also. I also forced all vertex buffers into system memory. Here's a modified version with these changes: ddraw.zip (diff.txt compared to v0.4.0)

Let me know if this fixes the performance issues for you too. I was getting a steady 64 FPS throughout the whole track with this. I will add some kind of configuration for both fixes in the next official release.

BEENNath58 commented 1 year ago

The issue is that the game uses video memory vertex buffers, locked after pretty much every single draw call, and with not very GPU-friendly flags either (e.g. no DISCARDCONTENTS or NOOVERWRITE flags). This causes a flush and synchronization after each draw call. The simplest solution is to force the game to use system memory vertex buffers instead. Let me know if this fixes the performance issues for you too. I was getting a steady 64 FPS throughout the whole track with this. I will add some kind of configuration for both fixes in the next official release.

Yes that did it, the problem seems fixed :)

The crash is caused by too many enumerated texture formats. The game only seems to support a maximum of 14. The 15th one overwrites some other data, replacing (amongst other things) a null pointer with some garbage value (0x4 in my case), which the game tries to read from later. For now, I just removed all the FOURCC texture formats from enumeration, which reduces the number of texture formats to 12 in my case, so DxWnd is not required.

Great discovery. DxWnd setting, Clear Texture FourCC does the same thing, i.e. trims the FourCC list. And yes, it now works without DxWnd as well.

Does the game use FourCC formats? And if you trim all of them, what does the game use? And how will you implement it in the main release as not all games require this trimming (and some may fail with the trim)?

narzoul commented 1 year ago

The game doesn't use any FourCCs, at least on my system. Somehow I doubt any DX7 and older games made use of FourCC texture formats other than maybe the DXTn formats, which have native decompression support in DX7. But I don't even know of any games that use even those.

The main release will have an option to set a specific list of texture formats to be enumerated, including any FourCCs you want. The default will still be to enumerate everything natively supported.

elishacloud commented 1 year ago

I know of at least two games that use DX7 FourCCs other than DXTn formats.

I believe have seen another DX7 game attempt to use MAKEFOURCC('Y', 'U', 'Y', '2'), but I don't remember what game it was.

Fortunately, in at least the first two cases you can just fail the creation attempt and the game will continue running as normal. But it does show that at least some DX7 games used FourCCs.

elishacloud commented 1 year ago

I don't even know of any games that use even those.

I know of at least three games that use DXTn FourCC formats in DX7:

Keep in mind that both of the Port Royale games use a mix of DX7 and DX8 for different parts of the game. I believe the intro menu and videos are in DX7 and the rest of the game is in DX8. But they use DXTn on DX7.

narzoul commented 1 year ago

Yes, I know about some YUV formats used by videos. But the question is if any non-DXTn FourCCs are used as textures, since the specific issue in NFS was with texture format enumeration, not FourCC enumeration (though I now realize DirectDraw has a separate method for the latter too). Do you know of any FourCC texture formats used by DX7 games, other than DXTn?

elishacloud commented 1 year ago

No, other than the ones I mentioned above, I am not aware of any other usage of FourCCs with DX7. I doubt many DX7 games used non-DXTn FourCC formats as textures. Mainly just for videos, I think.

narzoul commented 8 months ago

Added the SupportedTextureFormats and VertexBufferMemoryType settings to fix these issues. The latter is set to sysmem by default, I figured it won't cause problems in most cases, but we'll see.