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

CustomTexture: prefetch all available textures #2162

Merged
merged 2 commits into from May 26, 2015

Conversation

degasus
Copy link
Member

@degasus degasus commented Mar 1, 2015

This PR tries to prefetch and to decode all available custom textures if possible. This behavior can be enabled with a GUI option.
The goal is to reduce the stuttering on png decoding while playing, but it will require lots of memoy. eg the biggest texture pack I've found is the xenoblade one which requires additional 4GB. As this may crash smaller systems, the prefetcher will abort if more than half of the physical RAM is used.

@degasus
Copy link
Member Author

degasus commented Mar 1, 2015

@BigheadSMZ Do you want to try the new option? It shall load all custom textures non-blocking (at least a bit) on startup.

@magumagu
Copy link
Contributor

magumagu commented Mar 1, 2015

Why is the prefetcher on a separate thread? Does it really take so long that we can't block startup on it? Would parallelizing it help?

Could we maybe consider adding support for some format that loads faster instead (like .dds)?

Also, how much memory are we talking about? Gigabytes?

@degasus
Copy link
Member Author

degasus commented Mar 1, 2015

Here, it's about 35 seconds. So it is worth in my opinion.

Parallelizing would help, but soil isn't thread safe as written somewhere as comment...

.dds is supported by soil already.

The current xenoblade pack + environment are 3.6 GB, so it should never ever be enabled by default.

@magumagu
Copy link
Contributor

magumagu commented Mar 1, 2015

Oh, another alternative: maybe we could track textures which are used together, so when one texture is used, we prefetch the others which are expected to be used soon.

@magumagu
Copy link
Contributor

magumagu commented Mar 1, 2015

.dds might technically be supported, but it would be a heck of a lot faster if we could just memmap() the file and pass the pointer directly to the backend.

@mimimi085181
Copy link
Contributor

How fast do the textures load if they are the in the cache of the OS? I mean like, copy the textures from Dolphin's folder to anywhere, and then start Dolphin and let it load the textures?

{
const std::string& base_filename = entry.first;

if (!strstr(base_filename.c_str(), "_mip"))

This comment was marked as off-topic.

@degasus
Copy link
Member Author

degasus commented Mar 1, 2015

mimimi: It's more about png decoding than disk loading, at least here for me on my hard drive.

@@ -40,6 +42,9 @@ class HiresTexture
std::vector<Level> m_levels;

private:
static HiresTexture* Load(std::string base_filename, u32 width, u32 height);

This comment was marked as off-topic.

@BigheadSMZ
Copy link

Sorry for the delay, didn't notice this until now. Gave it run and it seems to work as intended! This route turned out to be a lot better than I thought it would, my impression was the game would need to be paused or no textures would show up until after preloaded. At first I wasn't sure if it was working because I immediately seen custom textures, then a little message popped up "Custom Textures loaded, 3338.2 MB in 22.5 s". Ran around the known trouble spots and to my surprise not a single hiccup.

@Linktothepast
Copy link
Contributor

It is working pretty well, but i did notice a couple of slowdowns here and there. Unfortunately it is also a ram killer, it makes pngs about 10 times bigger in memory than what they are. Tried two packs i have and 50 mb pngs became about 500 mb in memory and 70 mb about 800 mb. Big packs like the rogue squadron one which is 500mb will probably bring even a 8gb system to it's limits.
Generally though i like it and it works pretty much as intended providing you have a lot of spare ram at your disposal.

@degasus
Copy link
Member Author

degasus commented Mar 2, 2015

@lioncash fixed

@BigheadSMZ
Copy link

I can see that being a concern. What would happen if the limit is breached, as in it tries to preload 8GB of textures and only 4GB is available? And would dds files be smaller in RAM than png and be worth using? Or how about even jpg if it could be added (if it isn't already)?

@degasus
Copy link
Member Author

degasus commented Mar 3, 2015

@BigheadSMZ dds can be smaller, but in the current implementation, they aren't. And if you're out of ram, dolphin may just crash if you're lucky, else the system will freeze.

@degasus
Copy link
Member Author

degasus commented Mar 3, 2015

So any opinions about merging?

@BigheadSMZ
Copy link

While I think this is an awesome feature especially since I can probably take full advantage of it without worry, I don't know if it is safe in the hands of the masses if it has a chance to freeze their system. I imagine it will create panic when someone's 2006 laptop with 2GB RAM deadlocks using Dolphin and texture packs and they don't know why. I'm fine either way. But if there is no way to prevent a random meltdown then maybe it should have a "may cause system instability" warning.

@JMC47
Copy link
Contributor

JMC47 commented Mar 3, 2015

This seems like an awesome feature, but can't we at least warn users with less than 8GB of ram not to use it? Or disable it altogether?

@neobrain
Copy link
Member

neobrain commented Mar 3, 2015

This patch needs a proper host memory manager to be sensibly merged. Enabling options should not make it possible to destroy a stable emulation experience.

@EgoBizarro
Copy link

This should only be an issue for big texture packs. Most packs aren't that big.
I, personally, like this solution much better than the 'cache loaded textures' one. With the latter there would still be stuttering every time you play (though, obviously, it's still better than the current state); you'd never be able to have a smooth play. So I hope this one makes it into master sooner or later.

@@ -138,6 +138,7 @@ static wxString xfb_virtual_desc = wxTRANSLATE("Emulate XFBs using GPU texture o
static wxString xfb_real_desc = wxTRANSLATE("Emulate XFBs accurately.\nSlows down emulation a lot and prohibits high-resolution rendering but is necessary to emulate a number of games properly.\n\nIf unsure, check virtual XFB emulation instead.");
static wxString dump_textures_desc = wxTRANSLATE("Dump decoded game textures to User/Dump/Textures/<game_id>/.\n\nIf unsure, leave this unchecked.");
static wxString load_hires_textures_desc = wxTRANSLATE("Load custom textures from User/Load/Textures/<game_id>/.\n\nIf unsure, leave this unchecked.");
static wxString cache_hires_textures_desc = wxTRANSLATE("Load custom textures on startup.\nThis may require much of RAM but fixes some stutter.\n\nIf unsure, leave this unchecked.");

This comment was marked as off-topic.

This comment was marked as off-topic.

@neobrain
Copy link
Member

neobrain commented Mar 3, 2015

@StripTheSoulwhostolemydamnname "What does it matter, it only happens when using X anyway" is a terrible way to make decisions affecting software quality.

@JMC47
Copy link
Contributor

JMC47 commented Mar 4, 2015

Maybe disable this option on configurations without much ram for now? or just make sure it doesn't max out ram and tell it to stop/abort/notload any more textures?

@BigheadSMZ
Copy link

Some texture packs are not very big, 50-100 small textures will not take much RAM so disabling the option based on a set value wouldn't really be fair to those who could technically use one pack but not another. Maybe a dynamic limit could be imposed like....

  • check amount of RAM in system
  • calculate size of pack in RAM before actually loading into RAM
  • if calculated size greater than available RAM (+ some min overhead?) then do not preload
  • show an OSD message "preload failed because not enough RAM" so its known why

I imagine this would also have a problem if the limit is nearly reached, loading Firefox, WinAMP, etc, could deliver a final blow that Dolphin wouldn't have reached on its own if only like 3MB was free after preloading. So maybe leave some overhead, fail to preload if at least (example random number: 512MB) is not calculated to be free. Such as...

8GB RAM in system
Calculated pack size is 6GB in RAM
1.5GB consumed by OS + other processes
If 7.5GB- total consumed, 512MB still free, preload
If 7.6GB+ was consumed, 512MB exceeded, fail preload

This way the OS still has at least 512MB free (or whatever value works best) to manage so hopefully the limit won't be breached. I don't know many details of how things work on the software level, so I don't know if this could be an actual approach or if I'm just spouting nonsense. Maybe other options could be to remove some textures from RAM or not load some on start, but that kind of defeats the purpose.

@degasus
Copy link
Member Author

degasus commented Mar 6, 2015

Checking for the size of all textures without loading them still takes quite a long time. So I suggest to just try to load them and when you hit the ram limitation, stop it.

atm I'm thinking to just use 50% or the global system memory. Free memory isn't good as it may change while playing. So we still can get slowdown because of out-of-ram, but no system freezes any more.

@degasus degasus force-pushed the prefetch_tex branch 2 times, most recently from e499ea3 to d1190c4 Compare March 14, 2015 09:35
@degasus
Copy link
Member Author

degasus commented Mar 14, 2015

Updated to fix the remaining GUI issues and when to restart the prefetcher thread.
Now it's only missing when (or if) to interrupt the prefetcher on out-of-memory issues. But tbh, I have no clue how to do this on all plattforms :/

@degasus degasus force-pushed the prefetch_tex branch 2 times, most recently from 8eb8adc to 82ff988 Compare April 7, 2015 09:56
@degasus degasus force-pushed the prefetch_tex branch 6 times, most recently from 6e94ccc to 562b9d4 Compare May 16, 2015 13:38
There is no nice way to correctly "detect" the "used" memory, so we just say
we're fine to use 50% of the physical memory for custom textures.

This will fix out-of-memory crashes, but we still might run into swapping issues.
@degasus
Copy link
Member Author

degasus commented May 16, 2015

The last commit now aborts the loading if not enough memory is available. It's only tested on linux, so may anyone please check it on osx and windows?

It shall abort if the physical memory is smaller than 2 times the decoded texture pack.

@Linktothepast
Copy link
Contributor

Here in windows it loaded textures up to half the physical memory in RAM (2 gbytes were used by dolphin). It didn't abort loading them altogether though.

@degasus
Copy link
Member Author

degasus commented May 20, 2015

In my opinion, this PR is ready. Are there still any suggestions or questions?

@Linktothepast
Copy link
Contributor

Testing wise no problems here.

@JMC47
Copy link
Contributor

JMC47 commented May 20, 2015

No issues here using the Rogue Squadron tex pack.

degasus added a commit that referenced this pull request May 26, 2015
CustomTexture: prefetch all available textures
@degasus degasus merged commit a6412fb into dolphin-emu:master May 26, 2015
@degasus degasus deleted the prefetch_tex branch August 9, 2015 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
10 participants