Merge pull request #6334 from stenzek/startup
Video Backend Initialization/Core Boot Improvements
This commit is contained in:
commit
096131c908
|
@ -241,7 +241,6 @@ bool Init(std::unique_ptr<BootParameters> boot)
|
||||||
|
|
||||||
// Start the emu thread
|
// Start the emu thread
|
||||||
s_emu_thread = std::thread(EmuThread, std::move(boot));
|
s_emu_thread = std::thread(EmuThread, std::move(boot));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,9 +310,13 @@ void UndeclareAsCPUThread()
|
||||||
// For the CPU Thread only.
|
// For the CPU Thread only.
|
||||||
static void CPUSetInitialExecutionState()
|
static void CPUSetInitialExecutionState()
|
||||||
{
|
{
|
||||||
QueueHostJob([] {
|
// The CPU starts in stepping state, and will wait until a new state is set before executing.
|
||||||
|
// SetState must be called on the host thread, so we defer it for later.
|
||||||
|
QueueHostJob([]() {
|
||||||
SetState(SConfig::GetInstance().bBootToPause ? State::Paused : State::Running);
|
SetState(SConfig::GetInstance().bBootToPause ? State::Paused : State::Running);
|
||||||
|
Host_UpdateDisasmDialog();
|
||||||
Host_UpdateMainFrame();
|
Host_UpdateMainFrame();
|
||||||
|
Host_Message(WM_USER_CREATE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,17 +326,10 @@ static void CpuThread(const std::optional<std::string>& savestate_path, bool del
|
||||||
DeclareAsCPUThread();
|
DeclareAsCPUThread();
|
||||||
|
|
||||||
const SConfig& _CoreParameter = SConfig::GetInstance();
|
const SConfig& _CoreParameter = SConfig::GetInstance();
|
||||||
|
|
||||||
if (_CoreParameter.bCPUThread)
|
if (_CoreParameter.bCPUThread)
|
||||||
{
|
|
||||||
Common::SetCurrentThreadName("CPU thread");
|
Common::SetCurrentThreadName("CPU thread");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
Common::SetCurrentThreadName("CPU-GPU thread");
|
Common::SetCurrentThreadName("CPU-GPU thread");
|
||||||
g_video_backend->Video_Prepare();
|
|
||||||
Host_Message(WM_USER_CREATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This needs to be delayed until after the video backend is ready.
|
// This needs to be delayed until after the video backend is ready.
|
||||||
DolphinAnalytics::Instance()->ReportGameStart();
|
DolphinAnalytics::Instance()->ReportGameStart();
|
||||||
|
@ -341,6 +337,17 @@ static void CpuThread(const std::optional<std::string>& savestate_path, bool del
|
||||||
if (_CoreParameter.bFastmem)
|
if (_CoreParameter.bFastmem)
|
||||||
EMM::InstallExceptionHandler(); // Let's run under memory watch
|
EMM::InstallExceptionHandler(); // Let's run under memory watch
|
||||||
|
|
||||||
|
#ifdef USE_MEMORYWATCHER
|
||||||
|
MemoryWatcher::Init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (savestate_path)
|
||||||
|
{
|
||||||
|
::State::LoadAs(*savestate_path);
|
||||||
|
if (delete_savestate)
|
||||||
|
File::Delete(*savestate_path);
|
||||||
|
}
|
||||||
|
|
||||||
s_is_started = true;
|
s_is_started = true;
|
||||||
CPUSetInitialExecutionState();
|
CPUSetInitialExecutionState();
|
||||||
|
|
||||||
|
@ -361,25 +368,11 @@ static void CpuThread(const std::optional<std::string>& savestate_path, bool del
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_MEMORYWATCHER
|
|
||||||
MemoryWatcher::Init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (savestate_path)
|
|
||||||
{
|
|
||||||
::State::LoadAs(*savestate_path);
|
|
||||||
if (delete_savestate)
|
|
||||||
File::Delete(*savestate_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enter CPU run loop. When we leave it - we are done.
|
// Enter CPU run loop. When we leave it - we are done.
|
||||||
CPU::Run();
|
CPU::Run();
|
||||||
|
|
||||||
s_is_started = false;
|
s_is_started = false;
|
||||||
|
|
||||||
if (!_CoreParameter.bCPUThread)
|
|
||||||
g_video_backend->Video_CleanupShared();
|
|
||||||
|
|
||||||
if (_CoreParameter.bFastmem)
|
if (_CoreParameter.bFastmem)
|
||||||
EMM::UninstallExceptionHandler();
|
EMM::UninstallExceptionHandler();
|
||||||
}
|
}
|
||||||
|
@ -388,18 +381,12 @@ static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
|
||||||
bool delete_savestate)
|
bool delete_savestate)
|
||||||
{
|
{
|
||||||
DeclareAsCPUThread();
|
DeclareAsCPUThread();
|
||||||
const SConfig& _CoreParameter = SConfig::GetInstance();
|
|
||||||
|
|
||||||
|
const SConfig& _CoreParameter = SConfig::GetInstance();
|
||||||
if (_CoreParameter.bCPUThread)
|
if (_CoreParameter.bCPUThread)
|
||||||
{
|
|
||||||
Common::SetCurrentThreadName("FIFO player thread");
|
Common::SetCurrentThreadName("FIFO player thread");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
g_video_backend->Video_Prepare();
|
|
||||||
Host_Message(WM_USER_CREATE);
|
|
||||||
Common::SetCurrentThreadName("FIFO-GPU thread");
|
Common::SetCurrentThreadName("FIFO-GPU thread");
|
||||||
}
|
|
||||||
|
|
||||||
// Enter CPU run loop. When we leave it - we are done.
|
// Enter CPU run loop. When we leave it - we are done.
|
||||||
if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore())
|
if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore())
|
||||||
|
@ -412,26 +399,15 @@ static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
|
||||||
|
|
||||||
s_is_started = false;
|
s_is_started = false;
|
||||||
PowerPC::InjectExternalCPUCore(nullptr);
|
PowerPC::InjectExternalCPUCore(nullptr);
|
||||||
|
FifoPlayer::GetInstance().Close();
|
||||||
}
|
}
|
||||||
FifoPlayer::GetInstance().Close();
|
else
|
||||||
|
|
||||||
// If we did not enter the CPU Run Loop above then run a fake one instead.
|
|
||||||
// We need to be IsRunningAndStarted() for DolphinWX to stop us.
|
|
||||||
if (CPU::GetState() != CPU::State::PowerDown)
|
|
||||||
{
|
{
|
||||||
s_is_started = true;
|
// FIFO log does not contain any frames, cannot continue.
|
||||||
Host_Message(WM_USER_STOP);
|
PanicAlert("FIFO file is invalid, cannot playback.");
|
||||||
while (CPU::GetState() != CPU::State::PowerDown)
|
FifoPlayer::GetInstance().Close();
|
||||||
{
|
return;
|
||||||
if (!_CoreParameter.bCPUThread)
|
|
||||||
g_video_backend->PeekMessages();
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
||||||
}
|
|
||||||
s_is_started = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_CoreParameter.bCPUThread)
|
|
||||||
g_video_backend->Video_CleanupShared();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize and create emulation thread
|
// Initialize and create emulation thread
|
||||||
|
@ -455,9 +431,6 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
||||||
INFO_LOG(CONSOLE, "Stop\t\t---- Shutdown complete ----");
|
INFO_LOG(CONSOLE, "Stop\t\t---- Shutdown complete ----");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// Prevent the UI from getting stuck whenever an error occurs.
|
|
||||||
Common::ScopeGuard stop_message_guard{[] { Host_Message(WM_USER_STOP); }};
|
|
||||||
|
|
||||||
Common::SetCurrentThreadName("Emuthread - Starting");
|
Common::SetCurrentThreadName("Emuthread - Starting");
|
||||||
|
|
||||||
// For a time this acts as the CPU thread...
|
// For a time this acts as the CPU thread...
|
||||||
|
@ -493,8 +466,6 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
||||||
}
|
}
|
||||||
Common::ScopeGuard video_guard{[] { g_video_backend->Shutdown(); }};
|
Common::ScopeGuard video_guard{[] { g_video_backend->Shutdown(); }};
|
||||||
|
|
||||||
OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000);
|
|
||||||
|
|
||||||
if (cpu_info.HTT)
|
if (cpu_info.HTT)
|
||||||
SConfig::GetInstance().bDSPThread = cpu_info.num_cores > 4;
|
SConfig::GetInstance().bDSPThread = cpu_info.num_cores > 4;
|
||||||
else
|
else
|
||||||
|
@ -574,9 +545,6 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
||||||
// This adds the SyncGPU handler to CoreTiming, so now CoreTiming::Advance might block.
|
// This adds the SyncGPU handler to CoreTiming, so now CoreTiming::Advance might block.
|
||||||
Fifo::Prepare();
|
Fifo::Prepare();
|
||||||
|
|
||||||
// Thread is no longer acting as CPU Thread
|
|
||||||
UndeclareAsCPUThread();
|
|
||||||
|
|
||||||
// Setup our core, but can't use dynarec if we are compare server
|
// Setup our core, but can't use dynarec if we are compare server
|
||||||
if (core_parameter.iCPUCore != PowerPC::CORE_INTERPRETER &&
|
if (core_parameter.iCPUCore != PowerPC::CORE_INTERPRETER &&
|
||||||
(!core_parameter.bRunCompareServer || core_parameter.bRunCompareClient))
|
(!core_parameter.bRunCompareServer || core_parameter.bRunCompareClient))
|
||||||
|
@ -588,21 +556,15 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
||||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the window again because all stuff is initialized
|
|
||||||
Host_UpdateDisasmDialog();
|
|
||||||
Host_UpdateMainFrame();
|
|
||||||
|
|
||||||
// ENTER THE VIDEO THREAD LOOP
|
// ENTER THE VIDEO THREAD LOOP
|
||||||
if (core_parameter.bCPUThread)
|
if (core_parameter.bCPUThread)
|
||||||
{
|
{
|
||||||
// This thread, after creating the EmuWindow, spawns a CPU
|
// This thread, after creating the EmuWindow, spawns a CPU
|
||||||
// thread, and then takes over and becomes the video thread
|
// thread, and then takes over and becomes the video thread
|
||||||
Common::SetCurrentThreadName("Video thread");
|
Common::SetCurrentThreadName("Video thread");
|
||||||
|
UndeclareAsCPUThread();
|
||||||
|
|
||||||
g_video_backend->Video_Prepare();
|
// Spawn the CPU thread. The CPU thread will signal the event that boot is complete.
|
||||||
Host_Message(WM_USER_CREATE);
|
|
||||||
|
|
||||||
// Spawn the CPU thread
|
|
||||||
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path, delete_savestate);
|
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path, delete_savestate);
|
||||||
|
|
||||||
// become the GPU thread
|
// become the GPU thread
|
||||||
|
@ -610,46 +572,22 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
|
||||||
|
|
||||||
// We have now exited the Video Loop
|
// We have now exited the Video Loop
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(false, "Video Loop Ended").c_str());
|
INFO_LOG(CONSOLE, "%s", StopMessage(false, "Video Loop Ended").c_str());
|
||||||
|
|
||||||
|
// Join with the CPU thread.
|
||||||
|
s_cpu_thread.join();
|
||||||
|
INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());
|
||||||
}
|
}
|
||||||
else // SingleCore mode
|
else // SingleCore mode
|
||||||
{
|
{
|
||||||
// The spawned CPU Thread also does the graphics.
|
// Become the CPU thread
|
||||||
// The EmuThread is thus an idle thread, which sleeps while
|
cpuThreadFunc(savestate_path, delete_savestate);
|
||||||
// waiting for the program to terminate. Without this extra
|
|
||||||
// thread, the video backend window hangs in single core mode
|
|
||||||
// because no one is pumping messages.
|
|
||||||
Common::SetCurrentThreadName("Emuthread - Idle");
|
|
||||||
|
|
||||||
// Spawn the CPU+GPU thread
|
|
||||||
s_cpu_thread = std::thread(cpuThreadFunc, savestate_path, delete_savestate);
|
|
||||||
|
|
||||||
while (CPU::GetState() != CPU::State::PowerDown)
|
|
||||||
{
|
|
||||||
g_video_backend->PeekMessages();
|
|
||||||
Common::SleepCurrentThread(20);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str());
|
|
||||||
|
|
||||||
// Wait for s_cpu_thread to exit
|
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str());
|
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
#ifdef USE_GDBSTUB
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB ...").c_str());
|
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB ...").c_str());
|
||||||
gdb_deinit();
|
gdb_deinit();
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str());
|
INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s_cpu_thread.join();
|
|
||||||
|
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());
|
|
||||||
|
|
||||||
if (core_parameter.bCPUThread)
|
|
||||||
g_video_backend->Video_CleanupShared();
|
|
||||||
|
|
||||||
// If we shut down normally, the stop message does not need to be triggered.
|
|
||||||
stop_message_guard.Dismiss();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set or get the running state
|
// Set or get the running state
|
||||||
|
|
|
@ -83,10 +83,9 @@ static Common::Event updateMainFrameEvent;
|
||||||
void Host_Message(int Id)
|
void Host_Message(int Id)
|
||||||
{
|
{
|
||||||
if (Id == WM_USER_STOP)
|
if (Id == WM_USER_STOP)
|
||||||
{
|
|
||||||
s_running.Clear();
|
s_running.Clear();
|
||||||
|
if (Id == WM_USER_JOB_DISPATCH || Id == WM_USER_STOP)
|
||||||
updateMainFrameEvent.Set();
|
updateMainFrameEvent.Set();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* s_window_handle = nullptr;
|
static void* s_window_handle = nullptr;
|
||||||
|
|
|
@ -761,6 +761,8 @@ void CFrame::OnHostMessage(wxCommandEvent& event)
|
||||||
case WM_USER_CREATE:
|
case WM_USER_CREATE:
|
||||||
if (SConfig::GetInstance().bHideCursor)
|
if (SConfig::GetInstance().bHideCursor)
|
||||||
m_render_parent->SetCursor(wxCURSOR_BLANK);
|
m_render_parent->SetCursor(wxCURSOR_BLANK);
|
||||||
|
if (SConfig::GetInstance().bFullscreen)
|
||||||
|
DoFullscreen(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDM_PANIC:
|
case IDM_PANIC:
|
||||||
|
|
|
@ -717,6 +717,7 @@ void CFrame::StartGame(std::unique_ptr<BootParameters> boot)
|
||||||
m_render_parent = new wxPanel(m_render_frame, IDM_MPANEL, wxDefaultPosition, wxDefaultSize, 0);
|
m_render_parent = new wxPanel(m_render_frame, IDM_MPANEL, wxDefaultPosition, wxDefaultSize, 0);
|
||||||
#endif
|
#endif
|
||||||
m_render_frame->Show();
|
m_render_frame->Show();
|
||||||
|
m_render_frame->Raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
@ -724,15 +725,10 @@ void CFrame::StartGame(std::unique_ptr<BootParameters> boot)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wxBusyCursor hourglass;
|
wxBusyCursor hourglass;
|
||||||
|
|
||||||
DoFullscreen(SConfig::GetInstance().bFullscreen);
|
|
||||||
|
|
||||||
SetDebuggerStartupParameters();
|
SetDebuggerStartupParameters();
|
||||||
|
|
||||||
if (!BootManager::BootCore(std::move(boot)))
|
if (!BootManager::BootCore(std::move(boot)))
|
||||||
{
|
{
|
||||||
DoFullscreen(false);
|
|
||||||
|
|
||||||
// Destroy the renderer frame when not rendering to main
|
// Destroy the renderer frame when not rendering to main
|
||||||
if (!SConfig::GetInstance().bRenderToMain)
|
if (!SConfig::GetInstance().bRenderToMain)
|
||||||
m_render_frame->Destroy();
|
m_render_frame->Destroy();
|
||||||
|
|
|
@ -17,13 +17,6 @@ class VideoBackend : public VideoBackendBase
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
std::string GetDisplayName() const override;
|
std::string GetDisplayName() const override;
|
||||||
|
|
||||||
void Video_Prepare() override;
|
|
||||||
void Video_Cleanup() override;
|
|
||||||
|
|
||||||
void InitBackendInfo() override;
|
void InitBackendInfo() override;
|
||||||
|
|
||||||
unsigned int PeekMessages() override;
|
|
||||||
|
|
||||||
void* m_window_handle;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,19 +26,6 @@
|
||||||
|
|
||||||
namespace DX11
|
namespace DX11
|
||||||
{
|
{
|
||||||
unsigned int VideoBackend::PeekMessages()
|
|
||||||
{
|
|
||||||
MSG msg;
|
|
||||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
|
||||||
{
|
|
||||||
if (msg.message == WM_QUIT)
|
|
||||||
return FALSE;
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string VideoBackend::GetName() const
|
std::string VideoBackend::GetName() const
|
||||||
{
|
{
|
||||||
return "D3D";
|
return "D3D";
|
||||||
|
@ -145,32 +132,30 @@ bool VideoBackend::Initialize(void* window_handle)
|
||||||
InitBackendInfo();
|
InitBackendInfo();
|
||||||
InitializeShared();
|
InitializeShared();
|
||||||
|
|
||||||
m_window_handle = window_handle;
|
if (FAILED(D3D::Create(reinterpret_cast<HWND>(window_handle))))
|
||||||
|
{
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoBackend::Video_Prepare()
|
|
||||||
{
|
|
||||||
if (FAILED(D3D::Create(reinterpret_cast<HWND>(m_window_handle))))
|
|
||||||
PanicAlert("Failed to create D3D device.");
|
PanicAlert("Failed to create D3D device.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// internal interfaces
|
|
||||||
g_renderer = std::make_unique<Renderer>();
|
g_renderer = std::make_unique<Renderer>();
|
||||||
g_texture_cache = std::make_unique<TextureCache>();
|
g_texture_cache = std::make_unique<TextureCache>();
|
||||||
g_vertex_manager = std::make_unique<VertexManager>();
|
g_vertex_manager = std::make_unique<VertexManager>();
|
||||||
g_perf_query = std::make_unique<PerfQuery>();
|
g_perf_query = std::make_unique<PerfQuery>();
|
||||||
|
|
||||||
VertexShaderCache::Init();
|
VertexShaderCache::Init();
|
||||||
PixelShaderCache::Init();
|
PixelShaderCache::Init();
|
||||||
GeometryShaderCache::Init();
|
GeometryShaderCache::Init();
|
||||||
VertexShaderCache::WaitForBackgroundCompilesToComplete();
|
VertexShaderCache::WaitForBackgroundCompilesToComplete();
|
||||||
D3D::InitUtils();
|
D3D::InitUtils();
|
||||||
BBox::Init();
|
BBox::Init();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoBackend::Shutdown()
|
void VideoBackend::Shutdown()
|
||||||
{
|
{
|
||||||
// TODO: should be in Video_Cleanup
|
g_renderer->Shutdown();
|
||||||
|
|
||||||
D3D::ShutdownUtils();
|
D3D::ShutdownUtils();
|
||||||
PixelShaderCache::Shutdown();
|
PixelShaderCache::Shutdown();
|
||||||
VertexShaderCache::Shutdown();
|
VertexShaderCache::Shutdown();
|
||||||
|
@ -182,13 +167,8 @@ void VideoBackend::Shutdown()
|
||||||
g_texture_cache.reset();
|
g_texture_cache.reset();
|
||||||
g_renderer.reset();
|
g_renderer.reset();
|
||||||
|
|
||||||
D3D::Close();
|
|
||||||
|
|
||||||
ShutdownShared();
|
ShutdownShared();
|
||||||
}
|
|
||||||
|
|
||||||
void VideoBackend::Video_Cleanup()
|
D3D::Close();
|
||||||
{
|
|
||||||
CleanupShared();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,38 +58,32 @@ bool VideoBackend::Initialize(void* window_handle)
|
||||||
InitializeShared();
|
InitializeShared();
|
||||||
InitBackendInfo();
|
InitBackendInfo();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called after Initialize() from the Core
|
|
||||||
// Run from the graphics thread
|
|
||||||
void VideoBackend::Video_Prepare()
|
|
||||||
{
|
|
||||||
g_renderer = std::make_unique<Renderer>();
|
g_renderer = std::make_unique<Renderer>();
|
||||||
g_vertex_manager = std::make_unique<VertexManager>();
|
g_vertex_manager = std::make_unique<VertexManager>();
|
||||||
g_perf_query = std::make_unique<PerfQuery>();
|
g_perf_query = std::make_unique<PerfQuery>();
|
||||||
g_framebuffer_manager = std::make_unique<FramebufferManagerBase>();
|
g_framebuffer_manager = std::make_unique<FramebufferManagerBase>();
|
||||||
g_texture_cache = std::make_unique<TextureCache>();
|
g_texture_cache = std::make_unique<TextureCache>();
|
||||||
|
|
||||||
VertexShaderCache::s_instance = std::make_unique<VertexShaderCache>();
|
VertexShaderCache::s_instance = std::make_unique<VertexShaderCache>();
|
||||||
GeometryShaderCache::s_instance = std::make_unique<GeometryShaderCache>();
|
GeometryShaderCache::s_instance = std::make_unique<GeometryShaderCache>();
|
||||||
PixelShaderCache::s_instance = std::make_unique<PixelShaderCache>();
|
PixelShaderCache::s_instance = std::make_unique<PixelShaderCache>();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoBackend::Shutdown()
|
void VideoBackend::Shutdown()
|
||||||
{
|
{
|
||||||
ShutdownShared();
|
g_renderer->Shutdown();
|
||||||
}
|
|
||||||
|
|
||||||
void VideoBackend::Video_Cleanup()
|
|
||||||
{
|
|
||||||
CleanupShared();
|
|
||||||
PixelShaderCache::s_instance.reset();
|
PixelShaderCache::s_instance.reset();
|
||||||
VertexShaderCache::s_instance.reset();
|
VertexShaderCache::s_instance.reset();
|
||||||
GeometryShaderCache::s_instance.reset();
|
GeometryShaderCache::s_instance.reset();
|
||||||
|
|
||||||
g_texture_cache.reset();
|
g_texture_cache.reset();
|
||||||
g_perf_query.reset();
|
g_perf_query.reset();
|
||||||
g_vertex_manager.reset();
|
g_vertex_manager.reset();
|
||||||
g_framebuffer_manager.reset();
|
g_framebuffer_manager.reset();
|
||||||
g_renderer.reset();
|
g_renderer.reset();
|
||||||
|
|
||||||
|
ShutdownShared();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,6 @@ class VideoBackend : public VideoBackendBase
|
||||||
|
|
||||||
std::string GetName() const override { return "Null"; }
|
std::string GetName() const override { return "Null"; }
|
||||||
std::string GetDisplayName() const override { return "Null"; }
|
std::string GetDisplayName() const override { return "Null"; }
|
||||||
void Video_Prepare() override;
|
|
||||||
void Video_Cleanup() override;
|
|
||||||
|
|
||||||
void InitBackendInfo() override;
|
void InitBackendInfo() override;
|
||||||
|
|
||||||
unsigned int PeekMessages() override { return 0; }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -809,6 +809,7 @@ Renderer::~Renderer() = default;
|
||||||
|
|
||||||
void Renderer::Shutdown()
|
void Renderer::Shutdown()
|
||||||
{
|
{
|
||||||
|
::Renderer::Shutdown();
|
||||||
g_framebuffer_manager.reset();
|
g_framebuffer_manager.reset();
|
||||||
|
|
||||||
UpdateActiveConfig();
|
UpdateActiveConfig();
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
~Renderer() override;
|
~Renderer() override;
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown() override;
|
||||||
|
|
||||||
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
||||||
std::unique_ptr<AbstractStagingTexture>
|
std::unique_ptr<AbstractStagingTexture>
|
||||||
|
|
|
@ -17,13 +17,8 @@ class VideoBackend : public VideoBackendBase
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
std::string GetDisplayName() const override;
|
std::string GetDisplayName() const override;
|
||||||
|
|
||||||
void Video_Prepare() override;
|
|
||||||
void Video_Cleanup() override;
|
|
||||||
|
|
||||||
void InitBackendInfo() override;
|
void InitBackendInfo() override;
|
||||||
|
|
||||||
unsigned int PeekMessages() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool InitializeGLExtensions();
|
bool InitializeGLExtensions();
|
||||||
bool FillBackendInfo();
|
bool FillBackendInfo();
|
||||||
|
|
|
@ -58,12 +58,6 @@ Make AA apply instantly during gameplay if possible
|
||||||
|
|
||||||
namespace OGL
|
namespace OGL
|
||||||
{
|
{
|
||||||
// Draw messages on top of the screen
|
|
||||||
unsigned int VideoBackend::PeekMessages()
|
|
||||||
{
|
|
||||||
return GLInterface->PeekMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string VideoBackend::GetName() const
|
std::string VideoBackend::GetName() const
|
||||||
{
|
{
|
||||||
return "OGL";
|
return "OGL";
|
||||||
|
@ -172,23 +166,11 @@ bool VideoBackend::Initialize(void* window_handle)
|
||||||
if (!GLInterface->Create(window_handle, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer))
|
if (!GLInterface->Create(window_handle, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called after Initialize() from the Core
|
|
||||||
// Run from the graphics thread
|
|
||||||
void VideoBackend::Video_Prepare()
|
|
||||||
{
|
|
||||||
GLInterface->MakeCurrent();
|
GLInterface->MakeCurrent();
|
||||||
if (!InitializeGLExtensions() || !FillBackendInfo())
|
if (!InitializeGLExtensions() || !FillBackendInfo())
|
||||||
{
|
return false;
|
||||||
// TODO: Handle this better. We'll likely end up crashing anyway, but this method doesn't
|
|
||||||
// return anything, so we can't inform the caller that startup failed.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_renderer = std::make_unique<Renderer>();
|
g_renderer = std::make_unique<Renderer>();
|
||||||
|
|
||||||
g_vertex_manager = std::make_unique<VertexManager>();
|
g_vertex_manager = std::make_unique<VertexManager>();
|
||||||
g_perf_query = GetPerfQuery();
|
g_perf_query = GetPerfQuery();
|
||||||
ProgramShaderCache::Init();
|
ProgramShaderCache::Init();
|
||||||
|
@ -197,21 +179,12 @@ void VideoBackend::Video_Prepare()
|
||||||
static_cast<Renderer*>(g_renderer.get())->Init();
|
static_cast<Renderer*>(g_renderer.get())->Init();
|
||||||
TextureConverter::Init();
|
TextureConverter::Init();
|
||||||
BoundingBox::Init(g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight());
|
BoundingBox::Init(g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoBackend::Shutdown()
|
void VideoBackend::Shutdown()
|
||||||
{
|
{
|
||||||
GLInterface->Shutdown();
|
g_renderer->Shutdown();
|
||||||
GLInterface.reset();
|
|
||||||
ShutdownShared();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoBackend::Video_Cleanup()
|
|
||||||
{
|
|
||||||
// The following calls are NOT Thread Safe
|
|
||||||
// And need to be called from the video thread
|
|
||||||
CleanupShared();
|
|
||||||
static_cast<Renderer*>(g_renderer.get())->Shutdown();
|
|
||||||
BoundingBox::Shutdown();
|
BoundingBox::Shutdown();
|
||||||
TextureConverter::Shutdown();
|
TextureConverter::Shutdown();
|
||||||
g_sampler_cache.reset();
|
g_sampler_cache.reset();
|
||||||
|
@ -221,5 +194,8 @@ void VideoBackend::Video_Cleanup()
|
||||||
g_vertex_manager.reset();
|
g_vertex_manager.reset();
|
||||||
g_renderer.reset();
|
g_renderer.reset();
|
||||||
GLInterface->ClearCurrent();
|
GLInterface->ClearCurrent();
|
||||||
|
GLInterface->Shutdown();
|
||||||
|
GLInterface.reset();
|
||||||
|
ShutdownShared();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,15 +26,6 @@ SWRenderer::SWRenderer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWRenderer::Init()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SWRenderer::Shutdown()
|
|
||||||
{
|
|
||||||
UpdateActiveConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<AbstractTexture> SWRenderer::CreateTexture(const TextureConfig& config)
|
std::unique_ptr<AbstractTexture> SWRenderer::CreateTexture(const TextureConfig& config)
|
||||||
{
|
{
|
||||||
return std::make_unique<SW::SWTexture>(config);
|
return std::make_unique<SW::SWTexture>(config);
|
||||||
|
|
|
@ -13,9 +13,6 @@ class SWRenderer : public Renderer
|
||||||
public:
|
public:
|
||||||
SWRenderer();
|
SWRenderer();
|
||||||
|
|
||||||
static void Init();
|
|
||||||
static void Shutdown();
|
|
||||||
|
|
||||||
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
|
||||||
std::unique_ptr<AbstractStagingTexture>
|
std::unique_ptr<AbstractStagingTexture>
|
||||||
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
|
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
|
||||||
|
|
|
@ -88,38 +88,8 @@ bool VideoSoftware::Initialize(void* window_handle)
|
||||||
|
|
||||||
Clipper::Init();
|
Clipper::Init();
|
||||||
Rasterizer::Init();
|
Rasterizer::Init();
|
||||||
SWRenderer::Init();
|
|
||||||
DebugUtil::Init();
|
DebugUtil::Init();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoSoftware::Shutdown()
|
|
||||||
{
|
|
||||||
SWOGLWindow::Shutdown();
|
|
||||||
|
|
||||||
ShutdownShared();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoSoftware::Video_Cleanup()
|
|
||||||
{
|
|
||||||
CleanupShared();
|
|
||||||
|
|
||||||
SWRenderer::Shutdown();
|
|
||||||
DebugUtil::Shutdown();
|
|
||||||
// The following calls are NOT Thread Safe
|
|
||||||
// And need to be called from the video thread
|
|
||||||
SWRenderer::Shutdown();
|
|
||||||
g_framebuffer_manager.reset();
|
|
||||||
g_texture_cache.reset();
|
|
||||||
g_perf_query.reset();
|
|
||||||
g_vertex_manager.reset();
|
|
||||||
g_renderer.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called after Video_Initialize() from the Core
|
|
||||||
void VideoSoftware::Video_Prepare()
|
|
||||||
{
|
|
||||||
GLInterface->MakeCurrent();
|
GLInterface->MakeCurrent();
|
||||||
SWOGLWindow::s_instance->Prepare();
|
SWOGLWindow::s_instance->Prepare();
|
||||||
|
|
||||||
|
@ -127,11 +97,21 @@ void VideoSoftware::Video_Prepare()
|
||||||
g_vertex_manager = std::make_unique<SWVertexLoader>();
|
g_vertex_manager = std::make_unique<SWVertexLoader>();
|
||||||
g_perf_query = std::make_unique<PerfQuery>();
|
g_perf_query = std::make_unique<PerfQuery>();
|
||||||
g_texture_cache = std::make_unique<TextureCache>();
|
g_texture_cache = std::make_unique<TextureCache>();
|
||||||
SWRenderer::Init();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int VideoSoftware::PeekMessages()
|
void VideoSoftware::Shutdown()
|
||||||
{
|
{
|
||||||
return SWOGLWindow::s_instance->PeekMessages();
|
if (g_renderer)
|
||||||
|
g_renderer->Shutdown();
|
||||||
|
|
||||||
|
DebugUtil::Shutdown();
|
||||||
|
SWOGLWindow::Shutdown();
|
||||||
|
g_framebuffer_manager.reset();
|
||||||
|
g_texture_cache.reset();
|
||||||
|
g_perf_query.reset();
|
||||||
|
g_vertex_manager.reset();
|
||||||
|
g_renderer.reset();
|
||||||
|
ShutdownShared();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,6 @@ class VideoSoftware : public VideoBackendBase
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
std::string GetDisplayName() const override;
|
std::string GetDisplayName() const override;
|
||||||
|
|
||||||
void Video_Prepare() override;
|
|
||||||
void Video_Cleanup() override;
|
|
||||||
|
|
||||||
void InitBackendInfo() override;
|
void InitBackendInfo() override;
|
||||||
|
|
||||||
unsigned int PeekMessages() override;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,9 @@ void ShaderCache::Shutdown()
|
||||||
m_async_shader_compiler->StopWorkerThreads();
|
m_async_shader_compiler->StopWorkerThreads();
|
||||||
m_async_shader_compiler->RetrieveWorkItems();
|
m_async_shader_compiler->RetrieveWorkItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_ActiveConfig.bShaderCache && m_pipeline_cache != VK_NULL_HANDLE)
|
||||||
|
SavePipelineCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsStripPrimitiveTopology(VkPrimitiveTopology topology)
|
static bool IsStripPrimitiveTopology(VkPrimitiveTopology topology)
|
||||||
|
|
|
@ -16,11 +16,6 @@ public:
|
||||||
|
|
||||||
std::string GetName() const override { return "Vulkan"; }
|
std::string GetName() const override { return "Vulkan"; }
|
||||||
std::string GetDisplayName() const override { return "Vulkan (experimental)"; }
|
std::string GetDisplayName() const override { return "Vulkan (experimental)"; }
|
||||||
void Video_Prepare() override;
|
|
||||||
void Video_Cleanup() override;
|
|
||||||
|
|
||||||
void InitBackendInfo() override;
|
void InitBackendInfo() override;
|
||||||
|
|
||||||
unsigned int PeekMessages() override { return 0; }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,22 +245,16 @@ bool VideoBackend::Initialize(void* window_handle)
|
||||||
if (g_ActiveConfig.CanPrecompileUberShaders())
|
if (g_ActiveConfig.CanPrecompileUberShaders())
|
||||||
g_shader_cache->PrecompileUberShaders();
|
g_shader_cache->PrecompileUberShaders();
|
||||||
|
|
||||||
|
// Display the name so the user knows which device was actually created.
|
||||||
|
INFO_LOG(VIDEO, "Vulkan Device: %s", g_vulkan_context->GetDeviceProperties().deviceName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called after Initialize() from the Core
|
|
||||||
// Run from the graphics thread
|
|
||||||
void VideoBackend::Video_Prepare()
|
|
||||||
{
|
|
||||||
// Display the name so the user knows which device was actually created
|
|
||||||
OSD::AddMessage(StringFromFormat("Using physical adapter %s",
|
|
||||||
g_vulkan_context->GetDeviceProperties().deviceName)
|
|
||||||
.c_str(),
|
|
||||||
5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoBackend::Shutdown()
|
void VideoBackend::Shutdown()
|
||||||
{
|
{
|
||||||
|
if (g_renderer)
|
||||||
|
g_renderer->Shutdown();
|
||||||
|
|
||||||
if (g_command_buffer_mgr)
|
if (g_command_buffer_mgr)
|
||||||
g_command_buffer_mgr->WaitForGPUIdle();
|
g_command_buffer_mgr->WaitForGPUIdle();
|
||||||
|
|
||||||
|
@ -279,15 +273,4 @@ void VideoBackend::Shutdown()
|
||||||
ShutdownShared();
|
ShutdownShared();
|
||||||
UnloadVulkanLibrary();
|
UnloadVulkanLibrary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoBackend::Video_Cleanup()
|
|
||||||
{
|
|
||||||
g_command_buffer_mgr->WaitForGPUIdle();
|
|
||||||
|
|
||||||
// Save all cached pipelines out to disk for next time.
|
|
||||||
if (g_ActiveConfig.bShaderCache)
|
|
||||||
g_shader_cache->SavePipelineCache();
|
|
||||||
|
|
||||||
CleanupShared();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,8 +299,6 @@ void RunGpuLoop()
|
||||||
[] {
|
[] {
|
||||||
const SConfig& param = SConfig::GetInstance();
|
const SConfig& param = SConfig::GetInstance();
|
||||||
|
|
||||||
g_video_backend->PeekMessages();
|
|
||||||
|
|
||||||
// Do nothing while paused
|
// Do nothing while paused
|
||||||
if (!s_emu_running_state.IsSet())
|
if (!s_emu_running_state.IsSet())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -45,15 +45,6 @@ void VideoBackendBase::Video_ExitLoop()
|
||||||
s_FifoShuttingDown.Set();
|
s_FifoShuttingDown.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoBackendBase::Video_CleanupShared()
|
|
||||||
{
|
|
||||||
// First stop any framedumping, which might need to dump the last xfb frame. This process
|
|
||||||
// can require additional graphics sub-systems so it needs to be done first
|
|
||||||
g_renderer->ShutdownFrameDumping();
|
|
||||||
|
|
||||||
Video_Cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run from the CPU thread (from VideoInterface.cpp)
|
// Run from the CPU thread (from VideoInterface.cpp)
|
||||||
void VideoBackendBase::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
void VideoBackendBase::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
|
||||||
u64 ticks)
|
u64 ticks)
|
||||||
|
@ -211,12 +202,8 @@ void VideoBackendBase::ShutdownShared()
|
||||||
|
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
|
|
||||||
Fifo::Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoBackendBase::CleanupShared()
|
|
||||||
{
|
|
||||||
VertexLoaderManager::Clear();
|
VertexLoaderManager::Clear();
|
||||||
|
Fifo::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run from the CPU thread
|
// Run from the CPU thread
|
||||||
|
|
|
@ -101,6 +101,13 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height)
|
||||||
|
|
||||||
Renderer::~Renderer() = default;
|
Renderer::~Renderer() = default;
|
||||||
|
|
||||||
|
void Renderer::Shutdown()
|
||||||
|
{
|
||||||
|
// First stop any framedumping, which might need to dump the last xfb frame. This process
|
||||||
|
// can require additional graphics sub-systems so it needs to be done first
|
||||||
|
ShutdownFrameDumping();
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStride, u32 fbHeight,
|
void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbStride, u32 fbHeight,
|
||||||
float Gamma)
|
float Gamma)
|
||||||
{
|
{
|
||||||
|
|
|
@ -154,7 +154,7 @@ public:
|
||||||
virtual void ChangeSurface(void* new_surface_handle) {}
|
virtual void ChangeSurface(void* new_surface_handle) {}
|
||||||
bool UseVertexDepthRange() const;
|
bool UseVertexDepthRange() const;
|
||||||
|
|
||||||
void ShutdownFrameDumping();
|
virtual void Shutdown();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::tuple<int, int> CalculateTargetScale(int x, int y) const;
|
std::tuple<int, int> CalculateTargetScale(int x, int y) const;
|
||||||
|
@ -243,6 +243,7 @@ private:
|
||||||
std::string GetFrameDumpNextImageFileName() const;
|
std::string GetFrameDumpNextImageFileName() const;
|
||||||
bool StartFrameDumpToImage(const FrameDumpConfig& config);
|
bool StartFrameDumpToImage(const FrameDumpConfig& config);
|
||||||
void DumpFrameToImage(const FrameDumpConfig& config);
|
void DumpFrameToImage(const FrameDumpConfig& config);
|
||||||
|
void ShutdownFrameDumping();
|
||||||
|
|
||||||
bool IsFrameDumping();
|
bool IsFrameDumping();
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,6 @@ class VideoBackendBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~VideoBackendBase() {}
|
virtual ~VideoBackendBase() {}
|
||||||
virtual unsigned int PeekMessages() = 0;
|
|
||||||
|
|
||||||
virtual bool Initialize(void* window_handle) = 0;
|
virtual bool Initialize(void* window_handle) = 0;
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
|
|
||||||
|
@ -45,12 +43,8 @@ public:
|
||||||
void ShowConfig(void*);
|
void ShowConfig(void*);
|
||||||
virtual void InitBackendInfo() = 0;
|
virtual void InitBackendInfo() = 0;
|
||||||
|
|
||||||
virtual void Video_Prepare() = 0;
|
|
||||||
void Video_ExitLoop();
|
void Video_ExitLoop();
|
||||||
|
|
||||||
void Video_CleanupShared(); // called from gl/d3d thread
|
|
||||||
virtual void Video_Cleanup() = 0;
|
|
||||||
|
|
||||||
void Video_BeginField(u32, u32, u32, u32, u64);
|
void Video_BeginField(u32, u32, u32, u32, u64);
|
||||||
|
|
||||||
u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
|
u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
|
||||||
|
@ -70,7 +64,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void InitializeShared();
|
void InitializeShared();
|
||||||
void ShutdownShared();
|
void ShutdownShared();
|
||||||
void CleanupShared();
|
|
||||||
|
|
||||||
bool m_initialized = false;
|
bool m_initialized = false;
|
||||||
bool m_invalid = false;
|
bool m_invalid = false;
|
||||||
|
|
Loading…
Reference in New Issue