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
IOS: Emulate FS timings for ES content IPC commands #9511
Conversation
|
@leoetlino - anything in particular to test or anything to watch out for when testing? |
|
The Wii System Menu is crashing when I try to access my Channel List in the Data Management screen. This does not happen in master. Nevermind, it can happen on Master too, it depends on me accessing menus in a certain order. |
|
@iwubcode just making sure the system menu and NAND (including WiiWare) titles still work, nothing too specific JMC said most games don't care about the timing changes, it's just VC games that take longer to load now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code seems good, nothing that sticks out - but untested.
|
We solved the crash. Netplay corrupted my NAND at some point. |
|
yep, turned out there was a missing TMD for Dokapon Kingdom. It's why we enforce the requirement that games must be launched at least once before its save can be imported, but I guess this doesn't happen with netplay. |
|
After thinking about this a bit more, I'm not entirely satisfied with the way ticks are kept track of in the ES code -- I think that ideally ES shouldn't have to increment the number of ticks manually after each call to FS. I'll try to find a way to make that cleaner... |
91f30f5
to
ed2a712
Compare
|
Still WIP, but I changed the way ticks were accumulated. For the new version of the third and fourth commits, I recommend reviewing with "Hide whitespace changes" enabled to make the diff less noisy. I plan to address @Pokechu22's comment tomorrow. |
766f0c1
to
fdd1fc3
Compare
| class Ticks | ||
| { | ||
| public: | ||
| Ticks(u64* ticks = nullptr) : m_ticks(ticks) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explicit ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, we actually want implicit conversions to Ticks as this class is for all intents and purposes just a wrapper around a u64* and having to write Ticks{...} every time would be very verbose.
| auto backend_fd = m_ios.GetFS()->OpenFile(request.uid, request.gid, request.path, | ||
| static_cast<Mode>(request.flags & 3)); | ||
| LogResult(backend_fd, "OpenFile({})", request.path); | ||
| auto backend_fd = m_ios.GetFS()->OpenFile(uid, gid, path, mode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ticks doesn't seem to be used. Did you mean to pass it into OpenFile here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I see this quite a bit. What is the point of updating the ticks when they are passed in as a copy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number of ticks is estimated and ticks is updated two lines above -- the underlying backend doesn't know anything about timings.
ticks isn't an integer, it's a small wrapper around a u64*, which is why it is passed by value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @leoetlino for your explanation. I believe in my second comment I was confused ^^. In my first comment, I was aware of the u64* but thought the ticks were used in an underlying call somewhere.
Re-reading, I missed an important part. The ticks are ultimately passed in to the IPCReply structure via the MakeIPCReply function which I think helps determine the delay call for the command? Either the delay time is built up from 0 or it is built up from IPCOverheadTicks depending on the call.
Sorry for all the dumb comments!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's correct. MakeIPCReply is used to help construct an IPCReply with timing information and without having to duplicate the IPCReply{..., ticks} for every return.
| { | ||
| u64 title_id = 0; | ||
| if (!file.Read(&title_id, 1)) | ||
| if (fs.Read(fd, &title_id, 1, ticks) != sizeof(title_id)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't a constant be used to indicate an invalid read or an invalid title_id rather than relying on sizeof?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sizeof(title_id) is that constant. I could hardcode 8 but I think that's worse than using sizeof.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, I just find odd that the Read function can have an error state and it's not being used to handle the error. I understand the reasoning behind this use of sizeof in the case of partially read. Maybe that's just me but I find it strange to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there is an error, Read() returns a negative value so the comparison will be false in that case. Or am I misunderstanding your comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just saying that having if (Read(..., &var, ...) != READ_SIZE) rather than if (Read(..., &var, ...) < 0)/if (Read(..., &var, ...) == ERROR seems a bit odd to read to me.
Feel free to disregard that comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see what you mean. But if we do if (Read(..., &var, ...) < 0) we still also need to check for partial reads, so we'd have to do something like
const int ret = Read(...);
if (ret < 0 || ret != READ_SIZE)
...which seems redundant to me, since READ_SIZE is positive.
| return {}; | ||
|
|
||
| u32 uid = 0; | ||
| if (!file.Read(&uid, 1)) | ||
| if (fs.Read(fd, &uid, 1, ticks) != sizeof(uid)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto for sizeof and uid.
fdd1fc3
to
477c847
Compare
The content ID/index is what actually matters..
We log FS reads already, might as well log ES content reads.
This makes it more convenient to emulate timings for IPC commands that perform internal IOS <-> IOS IPC, for example ES relying on FS for filesystem access.
Filesystem accesses aren't magically faster when they are done by ES, so this commit changes our content wrapper IPC commands to take FS access times and read operations into account. This should make content read timings a lot more accurate and closer to console. Note that the accuracy of the timings are limited to the accuracy of the emulated FS timings, and currently performance differences between IOS9-IOS28 and newer IOS versions are not emulated. Part 1 of fixing https://bugs.dolphin-emu.org/issues/11346 (part 2 will involve emulating those differences)
477c847
to
f750208
Compare
93127f2
to
e3bf5fc
Compare
Filesystem accesses aren't magically faster when they are done by ES,
so this commit changes our content wrapper IPC commands to take FS
access times and read operations into account.
This should make content read timings a lot more accurate and closer
to console. Note that the accuracy of the timings are limited to the
accuracy of the emulated FS timings, and currently performance
differences between IOS9-IOS28 and newer IOS versions are not emulated.
Part 1 of fixing https://bugs.dolphin-emu.org/issues/11346
(part 2 will involve emulating those differences)