Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
eugene-s-nesdev opened this issue Jun 6, 2021 · 11 comments
Closed

Comments

@eugene-s-nesdev
Copy link

I have a question, maybe you can help for solving this problem: TASEmulators/fceux#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
Copy link
Owner

narzoul commented Jun 6, 2021

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
Copy link
Author

eugene-s-nesdev commented Jun 7, 2021

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
Copy link
Owner

narzoul commented Jun 7, 2021

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

@eugene-s-nesdev
Copy link
Author

eugene-s-nesdev commented Jun 7, 2021

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
Copy link
Owner

narzoul commented Jun 8, 2021

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
Copy link
Author

eugene-s-nesdev commented Jun 8, 2021

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
Copy link
Author

eugene-s-nesdev commented Jun 20, 2021

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
Copy link
Owner

narzoul commented Jun 27, 2021

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
Copy link
Author

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
Copy link
Owner

narzoul commented Jun 27, 2021

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

@narzoul
Copy link
Owner

narzoul commented Sep 27, 2022

A BltFilter setting has been added in v0.4.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants