GraphicsSystem Save/Restore

This commit is contained in:
Dr. Chat 2015-12-07 10:55:30 -06:00 committed by Ben Vanik
parent 9ed81b6876
commit 6997970d52
5 changed files with 113 additions and 1 deletions

View File

@ -292,12 +292,15 @@ X_STATUS Emulator::LaunchStfsContainer(std::wstring path) {
}
void Emulator::Pause() {
auto lock = global_critical_region::AcquireDirect();
if (paused_) {
return;
}
paused_ = true;
// Don't hold the lock on this (so any waits follow through)
graphics_system_->Pause();
auto lock = global_critical_region::AcquireDirect();
auto threads =
kernel_state()->object_table()->GetObjectsByType<kernel::XThread>(
kernel::XObject::kTypeThread);
@ -320,6 +323,8 @@ void Emulator::Resume() {
paused_ = false;
XELOGD("! EMULATOR RESUMED !");
graphics_system_->Resume();
auto threads =
kernel_state()->object_table()->GetObjectsByType<kernel::XThread>(
kernel::XObject::kTypeThread);
@ -349,6 +354,7 @@ bool Emulator::SaveToFile(const std::wstring& path) {
// It's important we don't hold the global lock here! XThreads need to step
// forward (possibly through guarded regions) without worry!
graphics_system_->Save(&stream);
kernel_state_->Save(&stream);
memory_->Save(&stream);
map->Close(stream.offset());
@ -376,6 +382,9 @@ bool Emulator::RestoreFromFile(const std::wstring& path) {
return false;
}
if (!graphics_system_->Restore(&stream)) {
return false;
}
if (!kernel_state_->Restore(&stream)) {
return false;
}

View File

@ -11,6 +11,7 @@
#include <algorithm>
#include "xenia/base/byte_stream.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/profiling.h"
@ -163,6 +164,59 @@ void CommandProcessor::WorkerThreadMain() {
ShutdownContext();
}
void CommandProcessor::Pause() {
if (paused_) {
return;
}
paused_ = true;
threading::Fence fence;
CallInThread([&fence]() {
fence.Signal();
threading::Thread::GetCurrentThread()->Suspend();
});
// HACK - Prevents a hang in IssueSwap()
swap_state_.pending = false;
fence.Wait();
}
void CommandProcessor::Resume() {
if (!paused_) {
return;
}
paused_ = false;
worker_thread_->thread()->Resume();
}
bool CommandProcessor::Save(ByteStream* stream) {
assert_true(paused_);
stream->Write<uint32_t>(primary_buffer_ptr_);
stream->Write<uint32_t>(primary_buffer_size_);
stream->Write<uint32_t>(read_ptr_index_);
stream->Write<uint32_t>(read_ptr_update_freq_);
stream->Write<uint32_t>(read_ptr_writeback_ptr_);
stream->Write<uint32_t>(write_ptr_index_.load());
return true;
}
bool CommandProcessor::Restore(ByteStream* stream) {
assert_true(paused_);
primary_buffer_ptr_ = stream->Read<uint32_t>();
primary_buffer_size_ = stream->Read<uint32_t>();
read_ptr_index_ = stream->Read<uint32_t>();
read_ptr_update_freq_ = stream->Read<uint32_t>();
read_ptr_writeback_ptr_ = stream->Read<uint32_t>();
write_ptr_index_.store(stream->Read<uint32_t>());
return true;
}
bool CommandProcessor::SetupContext() { return true; }
void CommandProcessor::ShutdownContext() { context_.reset(); }

View File

@ -28,6 +28,9 @@
#include "xenia/ui/graphics_context.h"
namespace xe {
class ByteStream;
namespace gpu {
class GraphicsSystem;
@ -91,6 +94,13 @@ class CommandProcessor {
void ExecutePacket(uint32_t ptr, uint32_t count);
bool is_paused() const { return paused_; }
void Pause();
void Resume();
bool Save(ByteStream* stream);
bool Restore(ByteStream* stream);
protected:
class RingbufferReader;
@ -214,6 +224,9 @@ class CommandProcessor {
Shader* active_vertex_shader_ = nullptr;
Shader* active_pixel_shader_ = nullptr;
bool paused_ = false;
};
} // namespace gpu

View File

@ -9,6 +9,7 @@
#include "xenia/gpu/graphics_system.h"
#include "xenia/base/byte_stream.h"
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
@ -246,5 +247,31 @@ void GraphicsSystem::BeginTracing() {
void GraphicsSystem::EndTracing() { command_processor_->EndTracing(); }
void GraphicsSystem::Pause() {
paused_ = true;
command_processor_->Pause();
}
void GraphicsSystem::Resume() {
paused_ = false;
command_processor_->Resume();
}
bool GraphicsSystem::Save(ByteStream* stream) {
stream->Write<uint32_t>(interrupt_callback_);
stream->Write<uint32_t>(interrupt_callback_data_);
return command_processor_->Save(stream);
}
bool GraphicsSystem::Restore(ByteStream* stream) {
interrupt_callback_ = stream->Read<uint32_t>();
interrupt_callback_data_ = stream->Read<uint32_t>();
return command_processor_->Restore(stream);
}
} // namespace gpu
} // namespace xe

View File

@ -61,6 +61,13 @@ class GraphicsSystem {
void BeginTracing();
void EndTracing();
bool is_paused() const { return paused_; }
void Pause();
void Resume();
bool Save(ByteStream* stream);
bool Restore(ByteStream* stream);
protected:
GraphicsSystem();
@ -90,6 +97,8 @@ class GraphicsSystem {
RegisterFile register_file_;
std::unique_ptr<CommandProcessor> command_processor_;
bool paused_ = false;
};
} // namespace gpu