narzoul / DDrawCompat

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

Old emulators and DirectDraw hardware blitter (linear interpolation). #104

Closed eugene-s-nesdev closed 1 year ago

eugene-s-nesdev commented 3 years ago

I have a question, maybe you can help for solving this problem: https://github.com/TASVideos/fceux/issues/364

Most of old videogame emulators (FCEUltra, FCEUX, DGen, NNNesterJ, VirtuaNES) does hardware blitter (linear interpolation) via DirectDraw instead of D3D.

Recent Nvidia video drivers doesn't have DirectDraw hardware blitting support since Windows 7, but intel GMA/HD graphics does. Linear interpolation works even on Windows 10 here.

This is an old issue, and Nvidia don't want to fix it yet: https://www.nvidia.com/en-us/geforce/forums/discover/33537/pixalisation-with-directdraw-blt-under-vista-pixel-replication-instead-interpolation/

intel (DirectDraw linear interpolation works correctly): intel

nvidia (DirectDraw linear interpolation doesn't work): nvidia

Can it be fixed via wrapper, or no way?

narzoul commented 3 years ago

If you're sure it's using hardware-accelerated DirectDraw Blt, then yes, in theory it should be fixable via a wrapper. Hardware-accelerated DirectDraw blits use the Direct3D 9 user-mode display driver's Blt routine (https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/d3dumddi/nc-d3dumddi-pfnd3dddi_blt) for blitting. This does have options for choosing either point or linear filtering (see the Flags member of the D3DDDIARG_BLT struct).

This option is not exposed through the DirectDraw API (both flags will always be set to 0), so it's up to the driver to choose whatever it wants. I'm surprised that any modern driver would default to point filtering instead of linear, but I haven't used NVIDIA drivers in a long time, so I don't have much experience with that.

The "equivalent" method in the Direct3D 9 runtime would be IDirect3DDevice9::StretchRect, which does have a parameter to control the filtering. So either a wrapper that wraps Blt calls to that, or which translates them to 3D textured quads could do it. Hooking the user-mode display driver's Blt routine would also be an option, though I'm not aware of any wrapper doing that (besides DDrawCompat). Of course, if the emulator source code can be changed, then the best option would be to stop using DirectDraw for this purpose (or any purpose, for that matter).

If you want to experiment with the driver hook approach, you could try to set data.Flags.Linear = 1; at the start of this function: https://github.com/narzoul/DDrawCompat/blob/v0.3.1/DDrawCompat/D3dDdi/Resource.cpp#L190

eugene-s-nesdev commented 3 years ago

Can you compile it with fix please? It requires MSVS2019 / BuildTools14.2 that i doesn't have. I'm under Win10 LTSC.

Administrator rights are required to install Visual Studio. Windows 10 Enterprise LTSC edition and Windows 10 S are not supported for development. You may use Visual Studio 2019 to build apps that run on Windows 10 LTSC and Windows 10 S.

narzoul commented 3 years ago

Here you go: ddraw.zip (diff.txt compared to v0.3.1)

eugene-s-nesdev commented 3 years ago

OMG it works for FCEUX (topic target problem) and NNNesterJ.

Thank tou very much!!!

works

logs.zip

For some reason it cannot catch VirtuaNES (no log, window decorator still Win10-like as you can see) Can you add setting for toggle ON/OFF force-Win9x window decorators in future releases?

General issues i've found while testing emulators (DDrawCompat 0.3.1 and your fresh ddraw.dll):

Interesting Jnes 1.1.1 behavior: https://youtu.be/flnppQlCf6E (1.1.1 was the last version used DirectDraw. Jnes use D3D9 since 1.2)

narzoul commented 3 years ago

Themes are not supported because I didn't find a way to properly hook them, so GDI interworking makes it a necessity for now. Disabling GDI interworking is similarly difficult, especially if 8/16 bit display mode support is to be kept. I might try again in the future, but I'm not to keen on spending more time on it for now.

I don't have Windows 7 anymore, so please attach debug logs for that using the ReleaseWithDebugLogs build.

eugene-s-nesdev commented 3 years ago

It's here, 0.3.1-release-with-debug-logs: win7-logs.zip Emulators performance and GUI rendering are very slow. Win10 works like a charm. P.S:

For some reason it cannot catch VirtuaNES (no log, window decorator still Win10-like as you can see)

Win7 catched virtuanes. Linear-filter driver hook works too. BTW, I guess i know why Linear-filter driver hook doesn't work with DGen1.21 Dgen force your desktop to 16-bit BPP at start (even windowed).

eugene-s-nesdev commented 3 years ago

ElectrixX guy from emu-land.net tested fresh AMD-drivers behavior. It works like NVIDIA, setting point flag instead of linear unfortunately. Your hack helped it that case too: http://www.emu-land.net/forum/index.php/topic,72761.msg1499360.html#msg1499360

I've just got intelNUC for testing (Win10LTSC-2019+lastest driver):

intel core i3-5005U
Intel HD Graphics 5500 (aida64 report: OpenGL 4.4.0)
graphic driver 20.19.15.5171 (dev 04.11.2020), whql

It does job right "oldstyled" way, setting linear flag.

My request is to add this hack to master branch. Maybe user will can turn OFF/ON it via settings someday.

narzoul commented 3 years ago

For the slowdown on Windows 7, I'm pretty sure it's the same issue related to D3DKMTWaitForVerticalBlankEvent which is reported in comment 46 here: https://bugs.chromium.org/p/chromium/issues/detail?id=467617#c46

It looks like there is no ideal solution for that. I'll have to come up with another (less accurate) way of tracking vertical blanks on Windows Vista and 7. Honestly, I should have dropped support for those OSes already, as they're no longer maintained anyway, and the point of DDrawCompat is to maintain compatibility with modern systems (not to mention I cannot test anything on those OSes). But as long as they can be kept at least minimally supported with little effort, I'll try to maintain at least basic compatibility with them, at least for now.

Just to verify that this is indeed the issue, I removed the call to D3DKMTWaitForVerticalBlankEvent and replaced it with a simple Sleep(16) for testing purposes: ddraw.zip (diff.txt compared to v0.3.1) I've left the linear filter fix in there as well.

eugene-s-nesdev commented 3 years ago

Thank you very much. It works like a charm on win7+aero (still have some minor glitches without aero). Very good and fast results: https://youtu.be/4eIkvk_9GRk

narzoul commented 3 years ago

Disabled desktop composition is not supported, and that's unlikely to change. This is written in the readme under Requirements.

narzoul commented 1 year ago

A BltFilter setting has been added in v0.4.0.