protonscr

Native resolution not listed in DX9-based Call of Duty games

dxvkclosed d3d9can't reproducewindows
doitsujin/dxvk#3214 · opened 2023-01-26 by simonlfc · updated 2024-02-03 · 8 comments · github
Ssimonlfc 2023-01-26 github

Hi, I've tested all D3D9 based Call of Duty games and they all share a common issue of my native resolution (2560x1440) not being listed. All other resolutions are listed correctly except 2560x1440. I have 3 identical monitors all running the same resolution and orientation, none of which are able to display the proper resolution using DXVK.

Software information

Call of Duty 4: Modern Warfare
Call of Duty: Modern Warfare 2 (2009)
Call of Duty: Modern Warfare 3
Call of Duty: Black Ops
Call of Duty: World at War

System information

  • GPU: NVIDIA RTX 3060Ti
  • Driver: 528.02 Game Ready
  • Wine version: N/A
  • DXVK version: 2.1

Apitrace file(s)

Log files

RRareMv 2023-01-28 github

But that's not all DX9 CoDs OP. There CoD2 and Black Ops 2 also.

JJTAG7371 2023-01-28 github

Black Ops 2 is D3D11 so semantics aside, I too have experienced this issue on a 1440p monitor but does not occur on ultrawide 1440p.

OOmarock92 2024-01-19 github

Got the same issue on cod4, 1080p monitor. Can't select native res.

Xxoxor4d 2024-01-19 github

I've just wanted to file exactly that issue myself. The main issue is that D3D9Adapter::CacheModes adds duplicate modes to m_modes. I'm currently not able to properly debug the solution (visual studio issues) but GetMonitorDisplayMode can return the same size+height+width+refreshrate+format multiple times (I've seen the same mode up to 3 times in m_modes).

Example of the first 2 modes being duplicates already:
dxvk_enummodes_bug

As to why thats an issue in call of duty games:
cod4-enumadapter

They use a D3DDISPLAYMODE array with a capacity of 256. Now depending on the max resolution and the refresh rate of the monitor, it can quickly run out of space. I'm on a 5120x1440 resolution with a max refresh rate of 120hz. That results in just close under 200 modes if m_modes does not contain any duplicates.

Since EnumAdapterModes returns duplicates, the max resolution the game offers (for me) is 1080p because the game simply stops calling it after 256 iterations. (I would an array with a capacity of around 360 or so to fit all the modes with duplicates)

I've fixed that on my end (nvidia rtx-remix compatibility mod for cod4) by hooking the EnumAdapterModes call to add returned modes to an unordered_set with hash checks to not add any duplicates. I've set the max iterations check to 1024 and write the non-duplicates list back to the games array after the loop.

https://github.com/xoxor4d/iw3xo-dev/blob/3f14546e1fd489f751e5815004b8872f1b541fe0/src/components/modules/rtx.cpp#L397

Game array without dxvk: https://drive.google.com/file/d/16Tg9YiExKBCJMJXhBQzlmt2U1AY8oSoK/view?usp=sharing
Game array with dxvk: https://drive.google.com/file/d/1KjJqpPSaosYClf83AY2_blH5uz9nEkyP/view?usp=sharing

Mmisyltoad 2024-01-19 github
Mmisyltoad 2024-01-19 github

It would be interesting to know what modes you are seeing also, perhaps there are some garbage ones we should filter out.

MMarkEHenderson 2024-01-19 github

I did some digging into this yesterday (on rtx-remix, but the relevant code is unmodified from dxvk).

I believe the primary cause of the problem is that m_modes is shared by EnumAdapterModes and EnumAdapterModesEx. Modes that are distinct as D3DDISPLAYMODEEX may be identical as D3DDISPLAYMODE. Deduping the D3DDISPLAYMODEEX entries in m_modes may help, but to actually dedupe the results from EnumAdapterModes DXVK will probably need to maintain a separate list of D3DDISPLAYMODE.

The way the filtering is done also means that EnumAdapterModes will return 'D3DERR_INVALIDCALL' for many indices, though from skimming the CoD code it seems that's already handled.

Xxoxor4d 2024-01-19 github

That indeed fixes the issue 🙌
Here is a list dumped from the game (after fix / before the fix) : https://gist.github.com/xoxor4d/233a223fce08e66e3b1ad1fee0976930

Nothing extracted yet.