Rewrite host GPU abstraction
- Don't have to repeat the same thing for 4 renderers. - Add native Metal renderer.
This commit is contained in:
@ -8,13 +8,6 @@
|
||||
#include "bus.h"
|
||||
#include "cdrom.h"
|
||||
#include "cheats.h"
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/make_array.h"
|
||||
#include "common/path.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/threading.h"
|
||||
#include "controller.h"
|
||||
#include "cpu_code_cache.h"
|
||||
#include "cpu_core.h"
|
||||
@ -40,13 +33,24 @@
|
||||
#include "spu.h"
|
||||
#include "texture_replacements.h"
|
||||
#include "timers.h"
|
||||
|
||||
#include "util/audio_stream.h"
|
||||
#include "util/cd_image.h"
|
||||
#include "util/host_display.h"
|
||||
#include "util/gpu_device.h"
|
||||
#include "util/ini_settings_interface.h"
|
||||
#include "util/iso_reader.h"
|
||||
#include "util/state_wrapper.h"
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/make_array.h"
|
||||
#include "common/path.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/threading.h"
|
||||
|
||||
#include "xxhash.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <cinttypes>
|
||||
#include <cmath>
|
||||
@ -55,6 +59,7 @@
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
|
||||
Log_SetChannel(System);
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -70,7 +75,9 @@ SystemBootParameters::SystemBootParameters(const SystemBootParameters&) = defaul
|
||||
|
||||
SystemBootParameters::SystemBootParameters(SystemBootParameters&& other) = default;
|
||||
|
||||
SystemBootParameters::SystemBootParameters(std::string filename_) : filename(std::move(filename_)) {}
|
||||
SystemBootParameters::SystemBootParameters(std::string filename_) : filename(std::move(filename_))
|
||||
{
|
||||
}
|
||||
|
||||
SystemBootParameters::~SystemBootParameters() = default;
|
||||
|
||||
@ -135,6 +142,7 @@ static std::string s_input_profile_name;
|
||||
|
||||
static System::State s_state = System::State::Shutdown;
|
||||
static std::atomic_bool s_startup_cancelled{false};
|
||||
static bool s_keep_gpu_device_on_shutdown = false;
|
||||
|
||||
static ConsoleRegion s_region = ConsoleRegion::NTSC_U;
|
||||
TickCount System::g_ticks_per_second = System::MASTER_CLOCK;
|
||||
@ -799,12 +807,10 @@ bool System::RecreateGPU(GPURenderer renderer, bool force_recreate_display, bool
|
||||
if (!state_valid)
|
||||
Log_ErrorPrintf("Failed to save old GPU state when switching renderers");
|
||||
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
|
||||
// create new renderer
|
||||
g_gpu.reset();
|
||||
if (force_recreate_display)
|
||||
Host::ReleaseHostDisplay();
|
||||
Host::ReleaseGPUDevice();
|
||||
|
||||
if (!CreateGPU(renderer))
|
||||
{
|
||||
@ -822,7 +828,6 @@ bool System::RecreateGPU(GPURenderer renderer, bool force_recreate_display, bool
|
||||
g_gpu->RestoreGraphicsAPIState();
|
||||
g_gpu->DoState(sw, nullptr, update_display);
|
||||
TimingEvents::DoState(sw);
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
}
|
||||
|
||||
// fix up vsync etc
|
||||
@ -1062,6 +1067,7 @@ bool System::LoadState(const char* filename)
|
||||
ResetPerformanceCounters();
|
||||
ResetThrottler();
|
||||
Host::RenderDisplay(false);
|
||||
g_gpu->RestoreGraphicsAPIState();
|
||||
Log_VerbosePrintf("Loading state took %.2f msec", load_timer.GetTimeMilliseconds());
|
||||
return true;
|
||||
}
|
||||
@ -1135,6 +1141,7 @@ bool System::BootSystem(SystemBootParameters parameters)
|
||||
Assert(s_state == State::Shutdown);
|
||||
s_state = State::Starting;
|
||||
s_startup_cancelled.store(false);
|
||||
s_keep_gpu_device_on_shutdown = static_cast<bool>(g_gpu_device);
|
||||
s_region = g_settings.region;
|
||||
Host::OnSystemStarting();
|
||||
|
||||
@ -1437,7 +1444,11 @@ bool System::Initialize(bool force_software_renderer)
|
||||
if (IsStartupCancelled())
|
||||
{
|
||||
g_gpu.reset();
|
||||
Host::ReleaseHostDisplay();
|
||||
if (!s_keep_gpu_device_on_shutdown)
|
||||
{
|
||||
Host::ReleaseGPUDevice();
|
||||
Host::ReleaseRenderWindow();
|
||||
}
|
||||
if (g_settings.gpu_pgxp_enable)
|
||||
PGXP::Shutdown();
|
||||
CPU::Shutdown();
|
||||
@ -1519,8 +1530,6 @@ void System::DestroySystem()
|
||||
Timers::Shutdown();
|
||||
Pad::Shutdown();
|
||||
CDROM::Shutdown();
|
||||
if (g_gpu)
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
g_gpu.reset();
|
||||
InterruptController::Shutdown();
|
||||
DMA::Shutdown();
|
||||
@ -1532,11 +1541,15 @@ void System::DestroySystem()
|
||||
ClearRunningGame();
|
||||
|
||||
// Restore present-all-frames behavior.
|
||||
if (g_host_display)
|
||||
if (s_keep_gpu_device_on_shutdown && g_gpu_device)
|
||||
{
|
||||
g_host_display->SetDisplayMaxFPS(0.0f);
|
||||
g_gpu_device->SetDisplayMaxFPS(0.0f);
|
||||
UpdateSoftwareCursor();
|
||||
Host::ReleaseHostDisplay();
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::ReleaseGPUDevice();
|
||||
Host::ReleaseRenderWindow();
|
||||
}
|
||||
|
||||
s_bios_hash = {};
|
||||
@ -1601,8 +1614,6 @@ void System::Execute()
|
||||
else
|
||||
CPU::Execute();
|
||||
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
|
||||
s_system_executing = false;
|
||||
continue;
|
||||
}
|
||||
@ -1624,6 +1635,9 @@ void System::FrameDone()
|
||||
{
|
||||
s_frame_number++;
|
||||
|
||||
// Vertex buffer is shared, need to flush what we have.
|
||||
g_gpu->FlushRender();
|
||||
|
||||
// Generate any pending samples from the SPU before sleeping, this way we reduce the chances of underruns.
|
||||
SPU::GeneratePendingSamples();
|
||||
|
||||
@ -1680,14 +1694,11 @@ void System::FrameDone()
|
||||
{
|
||||
s_last_frame_skipped = false;
|
||||
|
||||
// TODO: Purge reset/restore
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
|
||||
const bool skip_present = g_host_display->ShouldSkipDisplayingFrame();
|
||||
const bool skip_present = g_gpu_device->ShouldSkipDisplayingFrame();
|
||||
Host::RenderDisplay(skip_present);
|
||||
if (!skip_present && g_host_display->IsGPUTimingEnabled())
|
||||
if (!skip_present && g_gpu_device->IsGPUTimingEnabled())
|
||||
{
|
||||
s_accumulated_gpu_time += g_host_display->GetAndResetAccumulatedGPUTime();
|
||||
s_accumulated_gpu_time += g_gpu_device->GetAndResetAccumulatedGPUTime();
|
||||
s_presents_since_last_update++;
|
||||
}
|
||||
|
||||
@ -1784,10 +1795,9 @@ void System::SingleStepCPU()
|
||||
|
||||
CPU::SingleStep();
|
||||
|
||||
g_gpu->FlushRender();
|
||||
SPU::GeneratePendingSamples();
|
||||
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
|
||||
s_system_executing = false;
|
||||
}
|
||||
|
||||
@ -1834,35 +1844,29 @@ void System::RecreateSystem()
|
||||
|
||||
bool System::CreateGPU(GPURenderer renderer)
|
||||
{
|
||||
switch (renderer)
|
||||
const RenderAPI api = Settings::GetRenderAPIForRenderer(renderer);
|
||||
|
||||
if (!g_gpu_device || (renderer != GPURenderer::Software && g_gpu_device->GetRenderAPI() != api))
|
||||
{
|
||||
#ifdef WITH_OPENGL
|
||||
case GPURenderer::HardwareOpenGL:
|
||||
g_gpu = GPU::CreateHardwareOpenGLRenderer();
|
||||
break;
|
||||
#endif
|
||||
if (g_gpu_device)
|
||||
{
|
||||
Log_WarningPrintf("Recreating GPU device, expecting %s got %s", GPUDevice::RenderAPIToString(api),
|
||||
GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI()));
|
||||
}
|
||||
|
||||
#ifdef WITH_VULKAN
|
||||
case GPURenderer::HardwareVulkan:
|
||||
g_gpu = GPU::CreateHardwareVulkanRenderer();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
case GPURenderer::HardwareD3D11:
|
||||
g_gpu = GPU::CreateHardwareD3D11Renderer();
|
||||
break;
|
||||
case GPURenderer::HardwareD3D12:
|
||||
g_gpu = GPU::CreateHardwareD3D12Renderer();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case GPURenderer::Software:
|
||||
default:
|
||||
g_gpu = GPU::CreateSoftwareRenderer();
|
||||
break;
|
||||
Host::ReleaseGPUDevice();
|
||||
if (!Host::CreateGPUDevice(api))
|
||||
{
|
||||
Host::ReleaseRenderWindow();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (renderer == GPURenderer::Software)
|
||||
g_gpu = GPU::CreateSoftwareRenderer();
|
||||
else
|
||||
g_gpu = GPU::CreateHardwareRenderer();
|
||||
|
||||
if (!g_gpu)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to initialize %s renderer, falling back to software renderer",
|
||||
@ -1875,6 +1879,11 @@ bool System::CreateGPU(GPURenderer renderer)
|
||||
if (!g_gpu)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create fallback software renderer.");
|
||||
if (!s_keep_gpu_device_on_shutdown)
|
||||
{
|
||||
Host::ReleaseGPUDevice();
|
||||
Host::ReleaseRenderWindow();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1934,9 +1943,7 @@ bool System::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di
|
||||
return false;
|
||||
|
||||
g_gpu->RestoreGraphicsAPIState();
|
||||
const bool gpu_result = sw.DoMarker("GPU") && g_gpu->DoState(sw, host_texture, update_display);
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
if (!gpu_result)
|
||||
if (!sw.DoMarker("GPU") || !g_gpu->DoState(sw, host_texture, update_display))
|
||||
return false;
|
||||
|
||||
if (!sw.DoMarker("CDROM") || !CDROM::DoState(sw))
|
||||
@ -2071,8 +2078,6 @@ void System::InternalReset()
|
||||
#ifdef WITH_CHEEVOS
|
||||
Achievements::ResetRuntime();
|
||||
#endif
|
||||
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
}
|
||||
|
||||
std::string System::GetMediaPathFromSaveState(const char* path)
|
||||
@ -2283,7 +2288,7 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
|
||||
if (screenshot_size > 0)
|
||||
{
|
||||
// assume this size is the width
|
||||
const float display_aspect_ratio = g_host_display->GetDisplayAspectRatio();
|
||||
const float display_aspect_ratio = g_gpu_device->GetDisplayAspectRatio();
|
||||
const u32 screenshot_width = screenshot_size;
|
||||
const u32 screenshot_height =
|
||||
std::max(1u, static_cast<u32>(static_cast<float>(screenshot_width) /
|
||||
@ -2293,7 +2298,7 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
|
||||
std::vector<u32> screenshot_buffer;
|
||||
u32 screenshot_stride;
|
||||
GPUTexture::Format screenshot_format;
|
||||
if (g_host_display->RenderScreenshot(screenshot_width, screenshot_height,
|
||||
if (g_gpu_device->RenderScreenshot(screenshot_width, screenshot_height,
|
||||
Common::Rectangle<s32>::FromExtents(0, 0, screenshot_width, screenshot_height),
|
||||
&screenshot_buffer, &screenshot_stride, &screenshot_format) &&
|
||||
GPUTexture::ConvertTextureDataToRGBA8(screenshot_width, screenshot_height, screenshot_buffer, screenshot_stride,
|
||||
@ -2306,7 +2311,7 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_host_display->UsesLowerLeftOrigin())
|
||||
if (g_gpu_device->UsesLowerLeftOrigin())
|
||||
{
|
||||
GPUTexture::FlipTextureDataRGBA8(screenshot_width, screenshot_height, screenshot_buffer, screenshot_stride);
|
||||
}
|
||||
@ -2350,8 +2355,6 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
|
||||
header.data_compressed_size = static_cast<u32>(state->GetPosition() - header.offset_to_data);
|
||||
}
|
||||
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
@ -2427,7 +2430,7 @@ void System::UpdatePerformanceCounters()
|
||||
|
||||
s_fps_timer.ResetTo(now_ticks);
|
||||
|
||||
if (g_host_display->IsGPUTimingEnabled())
|
||||
if (g_gpu_device->IsGPUTimingEnabled())
|
||||
{
|
||||
s_average_gpu_time = s_accumulated_gpu_time / static_cast<float>(std::max(s_presents_since_last_update, 1u));
|
||||
s_gpu_usage = s_accumulated_gpu_time / (time * 10.0f);
|
||||
@ -2474,7 +2477,7 @@ void System::UpdateSpeedLimiterState()
|
||||
s_target_speed == 1.0f && IsValid())
|
||||
{
|
||||
float host_refresh_rate;
|
||||
if (g_host_display->GetHostRefreshRate(&host_refresh_rate))
|
||||
if (g_gpu_device->GetHostRefreshRate(&host_refresh_rate))
|
||||
{
|
||||
const float ratio = host_refresh_rate / System::GetThrottleFrequency();
|
||||
s_syncing_to_host = (ratio >= 0.95f && ratio <= 1.05f);
|
||||
@ -2530,8 +2533,8 @@ void System::UpdateDisplaySync()
|
||||
Log_VerbosePrintf("Max display fps: %f (%s)", max_display_fps,
|
||||
s_display_all_frames ? "displaying all frames" : "skipping displaying frames when needed");
|
||||
|
||||
g_host_display->SetDisplayMaxFPS(max_display_fps);
|
||||
g_host_display->SetVSync(video_sync_enabled);
|
||||
g_gpu_device->SetDisplayMaxFPS(max_display_fps);
|
||||
g_gpu_device->SetVSync(video_sync_enabled);
|
||||
}
|
||||
|
||||
bool System::ShouldUseVSync()
|
||||
@ -3038,10 +3041,7 @@ bool System::DumpVRAM(const char* filename)
|
||||
return false;
|
||||
|
||||
g_gpu->RestoreGraphicsAPIState();
|
||||
const bool result = g_gpu->DumpVRAMToFile(filename);
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
|
||||
return result;
|
||||
return g_gpu->DumpVRAMToFile(filename);
|
||||
}
|
||||
|
||||
bool System::DumpSPURAM(const char* filename)
|
||||
@ -3492,12 +3492,12 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||
{
|
||||
if (g_settings.display_post_processing && !g_settings.display_post_process_chain.empty())
|
||||
{
|
||||
if (!g_host_display->SetPostProcessingChain(g_settings.display_post_process_chain))
|
||||
if (!g_gpu_device->SetPostProcessingChain(g_settings.display_post_process_chain))
|
||||
Host::AddOSDMessage(TRANSLATE_STR("OSDMessage", "Failed to load post processing shader chain."), 20.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_host_display->SetPostProcessingChain({});
|
||||
g_gpu_device->SetPostProcessingChain({});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3708,8 +3708,6 @@ void System::DoRewind()
|
||||
|
||||
s_next_frame_time += s_frame_period;
|
||||
|
||||
// TODO: Purge reset/restore
|
||||
g_gpu->ResetGraphicsAPIState();
|
||||
Host::RenderDisplay(false);
|
||||
g_gpu->RestoreGraphicsAPIState();
|
||||
|
||||
@ -3989,7 +3987,7 @@ bool System::SaveScreenshot(const char* filename /* = nullptr */, bool full_reso
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool screenshot_saved = g_host_display->WriteScreenshotToFile(
|
||||
const bool screenshot_saved = g_gpu_device->WriteScreenshotToFile(
|
||||
filename, g_settings.display_internal_resolution_screenshots, compress_on_thread);
|
||||
|
||||
if (!screenshot_saved)
|
||||
@ -4340,13 +4338,13 @@ void System::TogglePostProcessing()
|
||||
{
|
||||
Host::AddKeyedOSDMessage("PostProcessing", TRANSLATE_STR("OSDMessage", "Post-processing is now enabled."), 10.0f);
|
||||
|
||||
if (!g_host_display->SetPostProcessingChain(g_settings.display_post_process_chain))
|
||||
if (!g_gpu_device->SetPostProcessingChain(g_settings.display_post_process_chain))
|
||||
Host::AddOSDMessage(TRANSLATE_STR("OSDMessage", "Failed to load post processing shader chain."), 20.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::AddKeyedOSDMessage("PostProcessing", TRANSLATE_STR("OSDMessage", "Post-processing is now disabled."), 10.0f);
|
||||
g_host_display->SetPostProcessingChain({});
|
||||
g_gpu_device->SetPostProcessingChain({});
|
||||
}
|
||||
}
|
||||
|
||||
@ -4355,7 +4353,7 @@ void System::ReloadPostProcessingShaders()
|
||||
if (!IsValid() || !g_settings.display_post_processing)
|
||||
return;
|
||||
|
||||
if (!g_host_display->SetPostProcessingChain(g_settings.display_post_process_chain))
|
||||
if (!g_gpu_device->SetPostProcessingChain(g_settings.display_post_process_chain))
|
||||
Host::AddOSDMessage(TRANSLATE_STR("OSDMessage", "Failed to load post-processing shader chain."), 20.0f);
|
||||
else
|
||||
Host::AddOSDMessage(TRANSLATE_STR("OSDMessage", "Post-processing shaders reloaded."), 10.0f);
|
||||
@ -4421,7 +4419,7 @@ void System::UpdateSoftwareCursor()
|
||||
if (!IsValid())
|
||||
{
|
||||
Host::SetMouseMode(false, false);
|
||||
g_host_display->ClearSoftwareCursor();
|
||||
g_gpu_device->ClearSoftwareCursor();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4444,12 +4442,12 @@ void System::UpdateSoftwareCursor()
|
||||
|
||||
if (image && image->IsValid())
|
||||
{
|
||||
g_host_display->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetPitch(),
|
||||
g_gpu_device->SetSoftwareCursor(image->GetPixels(), image->GetWidth(), image->GetHeight(), image->GetPitch(),
|
||||
image_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_host_display->ClearSoftwareCursor();
|
||||
g_gpu_device->ClearSoftwareCursor();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4462,13 +4460,13 @@ void System::RequestDisplaySize(float scale /*= 0.0f*/)
|
||||
scale = g_gpu->IsHardwareRenderer() ? static_cast<float>(g_settings.gpu_resolution_scale) : 1.0f;
|
||||
|
||||
const float y_scale =
|
||||
(static_cast<float>(g_host_display->GetDisplayWidth()) / static_cast<float>(g_host_display->GetDisplayHeight())) /
|
||||
g_host_display->GetDisplayAspectRatio();
|
||||
(static_cast<float>(g_gpu_device->GetDisplayWidth()) / static_cast<float>(g_gpu_device->GetDisplayHeight())) /
|
||||
g_gpu_device->GetDisplayAspectRatio();
|
||||
|
||||
const u32 requested_width =
|
||||
std::max<u32>(static_cast<u32>(std::ceil(static_cast<float>(g_host_display->GetDisplayWidth()) * scale)), 1);
|
||||
std::max<u32>(static_cast<u32>(std::ceil(static_cast<float>(g_gpu_device->GetDisplayWidth()) * scale)), 1);
|
||||
const u32 requested_height = std::max<u32>(
|
||||
static_cast<u32>(std::ceil(static_cast<float>(g_host_display->GetDisplayHeight()) * y_scale * scale)), 1);
|
||||
static_cast<u32>(std::ceil(static_cast<float>(g_gpu_device->GetDisplayHeight()) * y_scale * scale)), 1);
|
||||
|
||||
Host::RequestResizeHostDisplay(static_cast<s32>(requested_width), static_cast<s32>(requested_height));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user