Merge pull request #9009 from unknownbrackets/savestates

Compress rewind snapshots off thread
This commit is contained in:
Henrik Rydgård 2016-09-24 21:17:25 +02:00 committed by GitHub
commit 9ea1c25667
3 changed files with 37 additions and 1 deletions

View File

@ -194,6 +194,7 @@ void __KernelShutdown()
CoreTiming::ClearPendingEvents();
CoreTiming::UnregisterAllEvents();
Reporting::Shutdown();
SaveState::Shutdown();
kernelRunning = false;
}

View File

@ -21,6 +21,8 @@
#include "base/mutex.h"
#include "base/timeutil.h"
#include "i18n/i18n.h"
#include "thread/thread.h"
#include "thread/threadutil.h"
#include "Common/FileUtil.h"
#include "Common/ChunkFile.h"
@ -96,6 +98,8 @@ namespace SaveState
CChunkFileReader::Error Save()
{
lock_guard guard(lock_);
int n = next_++ % size_;
if ((next_ % size_) == first_)
++first_;
@ -116,7 +120,7 @@ namespace SaveState
err = SaveToRam(buffer);
if (err == CChunkFileReader::ERROR_NONE)
Compress(states_[n], *compressBuffer, bases_[base_]);
ScheduleCompress(&states_[n], compressBuffer, &bases_[base_]);
else
states_[n].clear();
baseMapping_[n] = base_;
@ -125,6 +129,8 @@ namespace SaveState
CChunkFileReader::Error Restore()
{
lock_guard guard(lock_);
// No valid states left.
if (Empty())
return CChunkFileReader::ERROR_BAD_FILE;
@ -138,8 +144,22 @@ namespace SaveState
return LoadFromRam(buffer);
}
void ScheduleCompress(std::vector<u8> *result, const std::vector<u8> *state, const std::vector<u8> *base)
{
auto th = new std::thread([=]{
setCurrentThreadName("SaveStateCompress");
Compress(*result, *state, *base);
});
th->detach();
}
void Compress(std::vector<u8> &result, const std::vector<u8> &state, const std::vector<u8> &base)
{
lock_guard guard(lock_);
// Bail if we were cleared before locking.
if (first_ == 0 && next_ == 0)
return;
result.clear();
for (size_t i = 0; i < state.size(); i += BLOCK_SIZE)
{
@ -156,6 +176,7 @@ namespace SaveState
void Decompress(std::vector<u8> &result, const std::vector<u8> &compressed, const std::vector<u8> &base)
{
lock_guard guard(lock_);
result.clear();
result.reserve(base.size());
auto basePos = base.begin();
@ -181,6 +202,8 @@ namespace SaveState
void Clear()
{
// This lock is mainly for shutdown.
lock_guard guard(lock_);
first_ = 0;
next_ = 0;
}
@ -193,13 +216,18 @@ namespace SaveState
static const int BLOCK_SIZE;
// TODO: Instead, based on size of compressed state?
static const int BASE_USAGE_INTERVAL;
typedef std::vector<u8> StateBuffer;
int first_;
int next_;
int size_;
std::vector<StateBuffer> states_;
StateBuffer bases_[2];
std::vector<int> baseMapping_;
recursive_mutex lock_;
int base_;
int baseUsage_;
};
@ -674,4 +702,10 @@ namespace SaveState
hasLoadedState = false;
}
void Shutdown()
{
lock_guard guard(mutex);
rewindStates.Clear();
}
}

View File

@ -30,6 +30,7 @@ namespace SaveState
static const char *SCREENSHOT_EXTENSION = "jpg";
void Init();
void Shutdown();
// Cycle through the 5 savestate slots
void NextSlot();