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

Use memory mapped files for managed textures #2524

Closed
wants to merge 8 commits into from

Conversation

K0bin
Copy link
Collaborator

@K0bin K0bin commented Mar 4, 2022

In order to finally fix some of our address space problems, I took a page out of Gallium Nines book.

Managed textures now use memory mapped files to store the internal data. The data is suballocated from 4MB (totally arbitrary) memory mapped files. This allows us to map and unmap that memory as we see fit. This only impacts managed textures, systemmem textures still use the DXVKBuffer to store their data because they can be used with GetRenderTargetData to read back data from the GPU. I don't think those are a problem anyway. Buffers are also unchanged. It's possible to extend this to buffers but I'd like to get some feedback first.

Unmapping follows a simple heuristic: We track the frame in which a texture was last used with LockRect, AddDirtyRect or when it was actually uploaded. If that was more than 16 frames ago or we've crossed the threshold of 512MB for mapped textures, we unmap. I hope that's good enough for games that keep the pointer around after calling Unlock. If it's not we can either try to tweak the heuristic, come up with something smarter or just disable it using a config option. I'd rather not punish decent D3D9 games that just happen to use too many high res managed textures because some do stupid things that aren't supposed to be allowed.

All of this is disabled in 64 bit builds of course.

The branch is basically a prototype. It works pretty well with Borderlands 2 and Witcher 2, both of which use a ton of managed textures. I'd like to get some feedback on this. Should we also extend this to buffers? Do you have any other ideas for the unmap heuristic?

@K0bin K0bin requested a review from Joshua-Ashton March 4, 2022 22:47
Copy link
Contributor

@DadSchoorse DadSchoorse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the technicalities, I saw the delete this; and got very annoyed about lifetimes 🐸

src/d3d9/d3d9_mem.h Outdated Show resolved Hide resolved
src/d3d9/d3d9_mem.cpp Outdated Show resolved Hide resolved
src/d3d9/d3d9_mem.h Outdated Show resolved Hide resolved
src/d3d9/d3d9_mem.h Outdated Show resolved Hide resolved
src/d3d9/d3d9_mem.h Show resolved Hide resolved
@K0bin
Copy link
Collaborator Author

K0bin commented Mar 5, 2022

Thanks for the review. I guess my lack of C++ experience is really showing here.

@K0bin
Copy link
Collaborator Author

K0bin commented Mar 5, 2022

Addressed the feedback.

@wils0nyan
Copy link

every time I try to merge this in and run Return of Reckoning (warhammer online) with the latest wine and mesa the launcher crashes straight away

wine: Unhandled page fault on read access to 0000000C at address 6244DDDC (thread 0110), starting debugger...

Unhandled exception: page fault on read access to 0x0000000c in 32-bit code (0x6244dddc).
Register dump:
CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b
EIP:6244dddc ESP:079df7b0 EBP:00000000 EFLAGS:00010256( R- -- I Z-A-P- )
EAX:00000003 EBX:079df8b8 ECX:00c77278 EDX:00000000
ESI:00000003 EDI:00000000
Stack dump:
0x079df7b0: 00c6a338 00d0b940 00010000 00000000
0x079df7c0: 00000023 079df8b8 00000000 6a2d961e
0x079df7d0: 0ae20000 e7c18000 00010000 00d059b0
0x079df7e0: 00000000 079df8b8 079df8f8 62462fa2
0x079df7f0: 079df8b8 00000003 00000000 00000000
0x079df800: 626a8ac4 626a92ec 626a8ac4 626a8884
Backtrace:
=>0 0x6244dddc in d3d9 (+0xdddc) (0x00000000)
0x6244dddc d3d9+0xdddc: movl 0xc(%edx),%eax

includes even the frog patch

@K0bin
Copy link
Collaborator Author

K0bin commented Mar 6, 2022

@wils0nyan Can you make an apitrace?

@wils0nyan
Copy link

ror-apitrace.tar.gz

ok here it is I'm not sure if this is useful

this is unrelated but even though the launcher loads without the unmap merge the box is still blacked out/flashes details every now and then

@K0bin K0bin force-pushed the unmap-managed branch 2 times, most recently from 24735cd to fe27aec Compare March 11, 2022 13:11
@K0bin
Copy link
Collaborator Author

K0bin commented Mar 11, 2022

The launcher crash should be fixed.

@K0bin K0bin force-pushed the unmap-managed branch 5 times, most recently from 9aedff8 to fd7cf5e Compare March 16, 2022 14:26
@K0bin K0bin marked this pull request as ready for review March 16, 2022 14:42
@K0bin K0bin changed the title RFC: Use memory mapped files for managed textures Use memory mapped files for managed textures Mar 16, 2022
@K0bin K0bin force-pushed the unmap-managed branch 3 times, most recently from e66062e to 7b78f0c Compare March 16, 2022 16:35
src/d3d9/meson.build Outdated Show resolved Hide resolved
@wils0nyan
Copy link

wils0nyan commented Mar 21, 2022

can confirm that the crash is gone but also have the following going:
git revert 4e6db51
git revert 14df2f7
(because they supposedly fixed that pretty quickly in radv)

and merged:
shader_replacement
dogma-fix
unmap-managed

no crash all good so far

mesa did break hevc 10 bit encoding on my ryzen 5700g recently with that efc stuff otherwise the additions to dxvk and the underlying drivers have been awesome over the last 6 months, it's improved a great deal thanks for the work you guys do

@Blisto91
Copy link
Contributor

Blisto91 commented Apr 4, 2022

Great work.
If you have any specific games that needs testing just say so

@K0bin
Copy link
Collaborator Author

K0bin commented Apr 4, 2022

Basically anything that's 32bit and currently crashes.

@Blisto91
Copy link
Contributor

Blisto91 commented Apr 4, 2022

Ich will dig through the issues

@TheIronWolfModding
Copy link

TheIronWolfModding commented Apr 6, 2022

Hi,
If I understand correctly, this approach saves process' address space when MANAGED pool is used?

Is it possible to extend this approach to optionally do this for D3DPOOL_SYSTEMMEM? There's a family of games that mirrors SYSTEMMEM texture for each DEFAULT one, perhaps because it does some CPU processing on them, sometimes. If those textures could be pushed out of process' address space it would be a huge win there.

Right now, I am trying to change the game itself via reverse engineering. My naive idea was to push everything to GPU memory (DEFAULT), but looks like it is more tricky than that. In any case, such a change looks to be way too invasive and complex... if memory pressure could be reduced via DXVK that would be gold.

I will gladly provide apitrace and test such fix. Thanks!

@Blisto91 Blisto91 mentioned this pull request Apr 6, 2022
@K0bin
Copy link
Collaborator Author

K0bin commented Apr 6, 2022

Is it possible to extend this approach to optionally do this for D3DPOOL_SYSTEMMEM? There's a family of games that mirrors SYSTEMMEM texture for each DEFAULT one, perhaps because it does some CPU processing on them, sometimes. If those textures could be pushed out of process' address space it would be a huge win there.

It's definitely possible but a bit more annoying because you can write to SYSTEMMEM textures on the GPU. Can you open an issue for that and attach an apitrace? I can look into extending this for SYSTEMMEM after landing the initial version.

Which games are we talking about anyway?

@TheIronWolfModding
Copy link

TheIronWolfModding commented Apr 6, 2022

I am messing with a 32bit game called GTR2. However, same or similar game engine is used by rFactor, Automobilista and dozen of other games, so I am guessing they might benefit as well.

One important detail about those games is that they are semi-open. They are not opensource, but they are by design made in such a way, that people can create their own cars/tracks, and customize nearly any aspect of the simulation. There are plenty of tools and a lot of stuff is adjustable via text configuration files.

The stock GTR2 won't run out of memory. But if you use some modern community content with highly detailed meshes and high resolution textures that's where the problem surfaces. It is not possible to simulate real events running, say 67 cars, because game runs out of memory at 30 cars.

I am in a middle of debugging, but it seems that game creates sysmem texture, and it keeps them around (creating the address space pressure), and dynamically manages matching default textures. I see some calls to LockRect/AddDirtyRect/UpdateTexture etc. I do not yet understand why that is done that way, but I think at least some of the processing is on the CPU side. Buffers contribute to memory pressure too, because even though they seem to go to default pool, they are DYNAMIC usage, so they seem to eat up process' address space as well, but not sure how big of a problem that is.

All that said, would issue with an apitrace still help?

EDIT: I think I'll spend more time debugging here as I am still not sure I diagnosed the problem correctly, don't want to waste your time before I am 100% sure.

@K0bin
Copy link
Collaborator Author

K0bin commented Apr 19, 2022

Renamed some symbols from _MANAGED to something a bit more generic in case we ever decide to extend this to other pool types.

@qinlili23333
Copy link

Some games really work better now with this version, but cannot solve #2417
Saints Row 2 now stuck at loading screen (while master branch build will directly crash)
I tested it on Windows 11 Preview (22621.1). Spec:i7-11800H, RTX3060 6G, 64G DDR4, 1440P internal display with another 2160P monitor plugged in

@K0bin
Copy link
Collaborator Author

K0bin commented Jun 2, 2022

Superseded by #2663

@K0bin K0bin closed this Jun 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants