System: Add fatal error shutdown path
Switch to a null backend and shut down the system instead of crashing.
This commit is contained in:
parent
155e365855
commit
01db85fa62
|
@ -985,7 +985,7 @@ void GPU::UpdateCRTCDisplayParameters()
|
|||
if ((cs.display_vram_width != old_vram_width || cs.display_vram_height != old_vram_height) &&
|
||||
g_settings.gpu_resolution_scale == 0)
|
||||
{
|
||||
GPUThread::RunOnBackend([](GPUBackend* backend) { backend->UpdateResolutionScale(); }, false, false);
|
||||
GPUBackend::QueueUpdateResolutionScale();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,10 +125,12 @@ bool GPUBackend::Initialize(bool clear_vram, Error* error)
|
|||
return true;
|
||||
}
|
||||
|
||||
void GPUBackend::UpdateSettings(const GPUSettings& old_settings)
|
||||
bool GPUBackend::UpdateSettings(const GPUSettings& old_settings, Error* error)
|
||||
{
|
||||
if (g_gpu_settings.display_show_gpu_stats != old_settings.display_show_gpu_stats)
|
||||
GPUBackend::ResetStatistics();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GPUThreadCommand* GPUBackend::NewClearVRAMCommand()
|
||||
|
@ -369,6 +371,20 @@ bool GPUBackend::AllocateMemorySaveStates(std::span<System::MemorySaveState> sta
|
|||
return result;
|
||||
}
|
||||
|
||||
void GPUBackend::QueueUpdateResolutionScale()
|
||||
{
|
||||
DebugAssert(!GPUThread::IsOnThread());
|
||||
|
||||
GPUThread::RunOnBackend(
|
||||
[](GPUBackend* backend) {
|
||||
Error error;
|
||||
if (!backend->UpdateResolutionScale(&error)) [[unlikely]]
|
||||
GPUThread::ReportFatalErrorAndShutdown(
|
||||
fmt::format("Failed to update resolution scale: {}", error.GetDescription()));
|
||||
},
|
||||
false, true);
|
||||
}
|
||||
|
||||
void GPUBackend::HandleCommand(const GPUThreadCommand* cmd)
|
||||
{
|
||||
switch (cmd->type)
|
||||
|
@ -753,3 +769,158 @@ void GPUBackend::RenderScreenshotToFile(const std::string_view path, DisplayScre
|
|||
},
|
||||
false, false);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class GPUNullBackend final : public GPUBackend
|
||||
{
|
||||
public:
|
||||
GPUNullBackend(GPUPresenter& presenter);
|
||||
~GPUNullBackend() override;
|
||||
|
||||
bool Initialize(bool upload_vram, Error* error) override;
|
||||
bool UpdateSettings(const GPUSettings& old_settings, Error* error) override;
|
||||
|
||||
u32 GetResolutionScale() const override;
|
||||
bool UpdateResolutionScale(Error* error) override;
|
||||
|
||||
void RestoreDeviceContext() override;
|
||||
void FlushRender() override;
|
||||
|
||||
void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override;
|
||||
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color, bool interlaced_rendering,
|
||||
u8 interlaced_display_field) override;
|
||||
void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override;
|
||||
void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height, bool set_mask,
|
||||
bool check_mask) override;
|
||||
|
||||
void DrawPolygon(const GPUBackendDrawPolygonCommand* cmd) override;
|
||||
void DrawPrecisePolygon(const GPUBackendDrawPrecisePolygonCommand* cmd) override;
|
||||
void DrawSprite(const GPUBackendDrawRectangleCommand* cmd) override;
|
||||
void DrawLine(const GPUBackendDrawLineCommand* cmd) override;
|
||||
void DrawPreciseLine(const GPUBackendDrawPreciseLineCommand* cmd) override;
|
||||
|
||||
void DrawingAreaChanged() override;
|
||||
void ClearCache() override;
|
||||
void OnBufferSwapped() override;
|
||||
void ClearVRAM() override;
|
||||
|
||||
void UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) override;
|
||||
|
||||
void LoadState(const GPUBackendLoadStateCommand* cmd) override;
|
||||
|
||||
bool AllocateMemorySaveState(System::MemorySaveState& mss, Error* error) override;
|
||||
void DoMemoryState(StateWrapper& sw, System::MemorySaveState& mss) override;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
GPUNullBackend::GPUNullBackend(GPUPresenter& presenter) : GPUBackend(presenter)
|
||||
{
|
||||
}
|
||||
|
||||
GPUNullBackend::~GPUNullBackend() = default;
|
||||
|
||||
bool GPUNullBackend::Initialize(bool upload_vram, Error* error)
|
||||
{
|
||||
return GPUBackend::Initialize(upload_vram, error);
|
||||
}
|
||||
|
||||
bool GPUNullBackend::UpdateSettings(const GPUSettings& old_settings, Error* error)
|
||||
{
|
||||
return GPUBackend::UpdateSettings(old_settings, error);
|
||||
}
|
||||
|
||||
u32 GPUNullBackend::GetResolutionScale() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool GPUNullBackend::UpdateResolutionScale(Error* error)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPUNullBackend::RestoreDeviceContext()
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::FlushRender()
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color, bool interlaced_rendering,
|
||||
u8 interlaced_display_field)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height, bool set_mask,
|
||||
bool check_mask)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::DrawPolygon(const GPUBackendDrawPolygonCommand* cmd)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::DrawPrecisePolygon(const GPUBackendDrawPrecisePolygonCommand* cmd)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::DrawSprite(const GPUBackendDrawRectangleCommand* cmd)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::DrawLine(const GPUBackendDrawLineCommand* cmd)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::DrawPreciseLine(const GPUBackendDrawPreciseLineCommand* cmd)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::DrawingAreaChanged()
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::ClearCache()
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::OnBufferSwapped()
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::ClearVRAM()
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd)
|
||||
{
|
||||
}
|
||||
|
||||
void GPUNullBackend::LoadState(const GPUBackendLoadStateCommand* cmd)
|
||||
{
|
||||
}
|
||||
|
||||
bool GPUNullBackend::AllocateMemorySaveState(System::MemorySaveState& mss, Error* error)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUNullBackend::DoMemoryState(StateWrapper& sw, System::MemorySaveState& mss)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<GPUBackend> GPUBackend::CreateNullBackend(GPUPresenter& presenter)
|
||||
{
|
||||
return std::make_unique<GPUNullBackend>(presenter);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ public:
|
|||
|
||||
static std::unique_ptr<GPUBackend> CreateHardwareBackend(GPUPresenter& presenter);
|
||||
static std::unique_ptr<GPUBackend> CreateSoftwareBackend(GPUPresenter& presenter);
|
||||
static std::unique_ptr<GPUBackend> CreateNullBackend(GPUPresenter& presenter);
|
||||
|
||||
static bool RenderScreenshotToBuffer(u32 width, u32 height, bool postfx, Image* out_image);
|
||||
static void RenderScreenshotToFile(const std::string_view path, DisplayScreenshotMode mode, u8 quality,
|
||||
|
@ -67,6 +68,8 @@ public:
|
|||
|
||||
static bool AllocateMemorySaveStates(std::span<System::MemorySaveState> states, Error* error);
|
||||
|
||||
static void QueueUpdateResolutionScale();
|
||||
|
||||
public:
|
||||
GPUBackend(GPUPresenter& presenter);
|
||||
virtual ~GPUBackend();
|
||||
|
@ -75,13 +78,13 @@ public:
|
|||
|
||||
virtual bool Initialize(bool upload_vram, Error* error);
|
||||
|
||||
virtual void UpdateSettings(const GPUSettings& old_settings);
|
||||
virtual bool UpdateSettings(const GPUSettings& old_settings, Error* error);
|
||||
|
||||
/// Returns the current resolution scale.
|
||||
virtual u32 GetResolutionScale() const = 0;
|
||||
|
||||
/// Updates the resolution scale when it's set to automatic.
|
||||
virtual void UpdateResolutionScale() = 0;
|
||||
virtual bool UpdateResolutionScale(Error* error) = 0;
|
||||
|
||||
// Graphics API state reset/restore - call when drawing the UI etc.
|
||||
// TODO: replace with "invalidate cached state"
|
||||
|
|
|
@ -277,11 +277,8 @@ bool GPU_HW::Initialize(bool upload_vram, Error* error)
|
|||
|
||||
if (m_use_texture_cache)
|
||||
{
|
||||
if (!GPUTextureCache::Initialize(this))
|
||||
{
|
||||
ERROR_LOG("Failed to initialize texture cache, disabling.");
|
||||
m_use_texture_cache = false;
|
||||
}
|
||||
if (!GPUTextureCache::Initialize(this, error))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -435,9 +432,10 @@ void GPU_HW::RestoreDeviceContext()
|
|||
m_batch_ubo_dirty = true;
|
||||
}
|
||||
|
||||
void GPU_HW::UpdateSettings(const GPUSettings& old_settings)
|
||||
bool GPU_HW::UpdateSettings(const GPUSettings& old_settings, Error* error)
|
||||
{
|
||||
GPUBackend::UpdateSettings(old_settings);
|
||||
if (!GPUBackend::UpdateSettings(old_settings, error))
|
||||
return false;
|
||||
|
||||
FlushRender();
|
||||
|
||||
|
@ -543,21 +541,19 @@ void GPU_HW::UpdateSettings(const GPUSettings& old_settings)
|
|||
|
||||
if (shaders_changed)
|
||||
{
|
||||
Error error;
|
||||
if (!CompilePipelines(&error))
|
||||
if (!CompilePipelines(error))
|
||||
{
|
||||
ERROR_LOG("Failed to recompile pipelines: {}", error.GetDescription());
|
||||
Panic("Failed to recompile pipelines.");
|
||||
Error::AddPrefix(error, "Failed to recompile pipelines: ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (resolution_dependent_shaders_changed || downsampling_shaders_changed)
|
||||
{
|
||||
Error error;
|
||||
if ((resolution_dependent_shaders_changed && !CompileResolutionDependentPipelines(&error)) ||
|
||||
(downsampling_shaders_changed && !CompileDownsamplePipelines(&error)))
|
||||
if ((resolution_dependent_shaders_changed && !CompileResolutionDependentPipelines(error)) ||
|
||||
(downsampling_shaders_changed && !CompileDownsamplePipelines(error)))
|
||||
{
|
||||
ERROR_LOG("Failed to recompile resolution dependent pipelines: {}", error.GetDescription());
|
||||
Panic("Failed to recompile resolution dependent pipelines.");
|
||||
Error::AddPrefix(error, "Failed to recompile resolution dependent pipelines: ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,11 +564,10 @@ void GPU_HW::UpdateSettings(const GPUSettings& old_settings)
|
|||
g_gpu_device->PurgeTexturePool();
|
||||
g_gpu_device->WaitForGPUIdle();
|
||||
|
||||
Error error;
|
||||
if (!CreateBuffers(&error))
|
||||
if (!CreateBuffers(error))
|
||||
{
|
||||
ERROR_LOG("Failed to recreate buffers: {}", error.GetDescription());
|
||||
Panic("Failed to recreate buffers.");
|
||||
Error::AddPrefix(error, "Failed to recreate buffers: ");
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateDownsamplingLevels();
|
||||
|
@ -591,10 +586,10 @@ void GPU_HW::UpdateSettings(const GPUSettings& old_settings)
|
|||
|
||||
if (m_use_texture_cache && !old_settings.gpu_texture_cache)
|
||||
{
|
||||
if (!GPUTextureCache::Initialize(this))
|
||||
if (!GPUTextureCache::Initialize(this, error))
|
||||
{
|
||||
ERROR_LOG("Failed to initialize texture cache, disabling.");
|
||||
m_use_texture_cache = false;
|
||||
Error::AddPrefix(error, "Failed to initialize texture cache: ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!m_use_texture_cache && old_settings.gpu_texture_cache)
|
||||
|
@ -602,7 +597,8 @@ void GPU_HW::UpdateSettings(const GPUSettings& old_settings)
|
|||
GPUTextureCache::Shutdown();
|
||||
}
|
||||
|
||||
GPUTextureCache::UpdateSettings(m_use_texture_cache, old_settings);
|
||||
if (!GPUTextureCache::UpdateSettings(m_use_texture_cache, old_settings, error))
|
||||
return false;
|
||||
|
||||
if (g_gpu_settings.gpu_downsample_mode != old_settings.gpu_downsample_mode ||
|
||||
(g_gpu_settings.gpu_downsample_mode == GPUDownsampleMode::Box &&
|
||||
|
@ -622,6 +618,8 @@ void GPU_HW::UpdateSettings(const GPUSettings& old_settings)
|
|||
m_draw_mode.mode_reg.texture_mode == GPUTextureMode::Palette8Bit);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPU_HW::CheckSettings()
|
||||
|
@ -783,10 +781,12 @@ u32 GPU_HW::CalculateResolutionScale() const
|
|||
return std::clamp<u32>(scale, 1, GetMaxResolutionScale());
|
||||
}
|
||||
|
||||
void GPU_HW::UpdateResolutionScale()
|
||||
bool GPU_HW::UpdateResolutionScale(Error* error)
|
||||
{
|
||||
if (CalculateResolutionScale() != m_resolution_scale)
|
||||
UpdateSettings(g_settings);
|
||||
if (CalculateResolutionScale() == m_resolution_scale)
|
||||
return true;
|
||||
|
||||
return UpdateSettings(g_settings, error);
|
||||
}
|
||||
|
||||
GPUDownsampleMode GPU_HW::GetDownsampleMode(u32 resolution_scale) const
|
||||
|
@ -900,8 +900,6 @@ GPUTexture::Format GPU_HW::GetDepthBufferFormat() const
|
|||
|
||||
bool GPU_HW::CreateBuffers(Error* error)
|
||||
{
|
||||
DestroyBuffers();
|
||||
|
||||
// scale vram size to internal resolution
|
||||
const u32 texture_width = VRAM_WIDTH * m_resolution_scale;
|
||||
const u32 texture_height = VRAM_HEIGHT * m_resolution_scale;
|
||||
|
|
|
@ -67,10 +67,9 @@ public:
|
|||
void RestoreDeviceContext() override;
|
||||
void FlushRender() override;
|
||||
|
||||
protected:
|
||||
void UpdateSettings(const GPUSettings& old_settings) override;
|
||||
bool UpdateSettings(const GPUSettings& old_settings, Error* error) override;
|
||||
|
||||
void UpdateResolutionScale() override;
|
||||
bool UpdateResolutionScale(Error* error) override;
|
||||
|
||||
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color, bool interlaced_rendering, u8 active_line_lsb) override;
|
||||
void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override;
|
||||
|
|
|
@ -249,7 +249,7 @@ static bool IsDumpingVRAMWriteTextures();
|
|||
static void UpdateVRAMTrackingState();
|
||||
|
||||
static void SetHashCacheTextureFormat();
|
||||
static bool CompilePipelines();
|
||||
static bool CompilePipelines(Error* error);
|
||||
static void DestroyPipelines();
|
||||
|
||||
static const Source* ReturnSource(Source* source, const GSVector4i uv_rect, PaletteRecordFlags flags);
|
||||
|
@ -581,20 +581,20 @@ bool GPUTextureCache::IsDumpingVRAMWriteTextures()
|
|||
return (g_gpu_settings.texture_replacements.dump_textures && !s_state.config.dump_texture_pages);
|
||||
}
|
||||
|
||||
bool GPUTextureCache::Initialize(GPU_HW* backend)
|
||||
bool GPUTextureCache::Initialize(GPU_HW* backend, Error* error)
|
||||
{
|
||||
s_state.hw_backend = backend;
|
||||
|
||||
SetHashCacheTextureFormat();
|
||||
ReloadTextureReplacements(false);
|
||||
UpdateVRAMTrackingState();
|
||||
if (!CompilePipelines())
|
||||
if (!CompilePipelines(error))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPUTextureCache::UpdateSettings(bool use_texture_cache, const GPUSettings& old_settings)
|
||||
bool GPUTextureCache::UpdateSettings(bool use_texture_cache, const GPUSettings& old_settings, Error* error)
|
||||
{
|
||||
const bool prev_tracking_state = s_state.track_vram_writes;
|
||||
|
||||
|
@ -613,8 +613,11 @@ void GPUTextureCache::UpdateSettings(bool use_texture_cache, const GPUSettings&
|
|||
s_state.config.replacement_scale_linear_filter != old_replacement_scale_linear_filter)
|
||||
{
|
||||
DestroyPipelines();
|
||||
if (!CompilePipelines()) [[unlikely]]
|
||||
Panic("Failed to compile pipelines on TC replacement settings change");
|
||||
if (!CompilePipelines(error)) [[unlikely]]
|
||||
{
|
||||
Error::AddPrefix(error, "Failed to compile pipelines on TC replacement settings change: ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,6 +628,8 @@ void GPUTextureCache::UpdateSettings(bool use_texture_cache, const GPUSettings&
|
|||
|
||||
if (s_state.track_vram_writes != prev_tracking_state)
|
||||
Invalidate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GPUTextureCache::GetStateSize(StateWrapper& sw, u32* size)
|
||||
|
@ -828,7 +833,7 @@ void GPUTextureCache::SetHashCacheTextureFormat()
|
|||
INFO_LOG("Using {} format for hash cache entries.", GPUTexture::GetFormatName(s_state.hash_cache_texture_format));
|
||||
}
|
||||
|
||||
bool GPUTextureCache::CompilePipelines()
|
||||
bool GPUTextureCache::CompilePipelines(Error* error)
|
||||
{
|
||||
if (!g_gpu_settings.texture_replacements.enable_texture_replacements)
|
||||
return true;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "gpu_types.h"
|
||||
|
||||
class Error;
|
||||
class Image;
|
||||
class GPUTexture;
|
||||
class StateWrapper;
|
||||
|
@ -103,8 +104,8 @@ struct Source
|
|||
TListNode<Source> hash_cache_ref;
|
||||
};
|
||||
|
||||
bool Initialize(GPU_HW* backend);
|
||||
void UpdateSettings(bool use_texture_cache, const GPUSettings& old_settings);
|
||||
bool Initialize(GPU_HW* backend, Error* error);
|
||||
bool UpdateSettings(bool use_texture_cache, const GPUSettings& old_settings, Error* error);
|
||||
|
||||
bool GetStateSize(StateWrapper& sw, u32* size);
|
||||
bool DoState(StateWrapper& sw, bool skip);
|
||||
|
|
|
@ -56,7 +56,7 @@ bool GPUPresenter::Initialize(Error* error)
|
|||
return true;
|
||||
}
|
||||
|
||||
void GPUPresenter::UpdateSettings(const GPUSettings& old_settings)
|
||||
bool GPUPresenter::UpdateSettings(const GPUSettings& old_settings, Error* error)
|
||||
{
|
||||
if (g_gpu_settings.display_scaling != old_settings.display_scaling ||
|
||||
g_gpu_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode ||
|
||||
|
@ -69,11 +69,14 @@ void GPUPresenter::UpdateSettings(const GPUSettings& old_settings)
|
|||
if (!CompileDisplayPipelines(
|
||||
g_gpu_settings.display_scaling != old_settings.display_scaling,
|
||||
g_gpu_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode,
|
||||
g_gpu_settings.display_24bit_chroma_smoothing != old_settings.display_24bit_chroma_smoothing, nullptr))
|
||||
g_gpu_settings.display_24bit_chroma_smoothing != old_settings.display_24bit_chroma_smoothing, error))
|
||||
{
|
||||
Panic("Failed to compile display pipeline on settings change.");
|
||||
Error::AddPrefix(error, "Failed to compile display pipeline on settings change:\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GPUPresenter::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_smoothing, Error* error)
|
||||
|
@ -818,6 +821,7 @@ bool GPUPresenter::PresentFrame(GPUPresenter* presenter, GPUBackend* backend, bo
|
|||
if (pres == GPUDevice::PresentResult::DeviceLost) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG("GPU device lost during present.");
|
||||
GPUThread::ReportFatalErrorAndShutdown("GPU device lost. The log may contain more information.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
bool Initialize(Error* error);
|
||||
|
||||
void UpdateSettings(const GPUSettings& old_settings);
|
||||
bool UpdateSettings(const GPUSettings& old_settings, Error* error);
|
||||
|
||||
void ClearDisplay();
|
||||
void ClearDisplayTexture();
|
||||
|
|
|
@ -65,8 +65,9 @@ void GPU_SW::ClearVRAM()
|
|||
std::memset(g_gpu_clut, 0, sizeof(g_gpu_clut));
|
||||
}
|
||||
|
||||
void GPU_SW::UpdateResolutionScale()
|
||||
bool GPU_SW::UpdateResolutionScale(Error* error)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void GPU_SW::LoadState(const GPUBackendLoadStateCommand* cmd)
|
||||
|
|
|
@ -27,7 +27,6 @@ public:
|
|||
|
||||
u32 GetResolutionScale() const override;
|
||||
|
||||
protected:
|
||||
void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override;
|
||||
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color, bool interlaced_rendering, u8 active_line_lsb) override;
|
||||
void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override;
|
||||
|
@ -47,7 +46,7 @@ protected:
|
|||
|
||||
void ClearVRAM() override;
|
||||
|
||||
void UpdateResolutionScale() override;
|
||||
bool UpdateResolutionScale(Error* error) override;
|
||||
|
||||
void LoadState(const GPUBackendLoadStateCommand* cmd) override;
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ void GPUThread::Internal::SetThreadEnabled(bool enabled)
|
|||
requested_fullscreen_ui, true, &error))
|
||||
{
|
||||
ERROR_LOG("Reconfigure failed: {}", error.GetDescription());
|
||||
Panic("Failed to reconfigure when changing thread state.");
|
||||
ReportFatalErrorAndShutdown(fmt::format("Reconfigure failed: {}", error.GetDescription()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -780,7 +780,8 @@ bool GPUThread::CreateGPUBackendOnThread(GPURenderer renderer, bool upload_vram,
|
|||
|
||||
s_state.requested_renderer = GPURenderer::Software;
|
||||
s_state.gpu_backend = GPUBackend::CreateSoftwareBackend(*s_state.gpu_presenter);
|
||||
okay = s_state.gpu_backend->Initialize(upload_vram, &local_error);
|
||||
if (!s_state.gpu_backend->Initialize(upload_vram, &local_error))
|
||||
Panic("Failed to initialize fallback software renderer");
|
||||
}
|
||||
|
||||
if (!okay)
|
||||
|
@ -971,8 +972,14 @@ void GPUThread::UpdateSettingsOnThread(const GPUSettings& old_settings)
|
|||
|
||||
PostProcessing::UpdateSettings();
|
||||
|
||||
s_state.gpu_presenter->UpdateSettings(old_settings);
|
||||
s_state.gpu_backend->UpdateSettings(old_settings);
|
||||
Error error;
|
||||
if (!s_state.gpu_presenter->UpdateSettings(old_settings, &error) ||
|
||||
!s_state.gpu_backend->UpdateSettings(old_settings, &error)) [[unlikely]]
|
||||
{
|
||||
ReportFatalErrorAndShutdown(fmt::format("Failed to update settings: {}", error.GetDescription()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGuiManager::UpdateDebugWindowConfig() || (PostProcessing::DisplayChain.IsActive() && !IsSystemPaused()))
|
||||
PresentFrameAndRestoreContext();
|
||||
else
|
||||
|
@ -1071,6 +1078,21 @@ void GPUThread::UpdateSettings(bool gpu_settings_changed, bool device_settings_c
|
|||
}
|
||||
}
|
||||
|
||||
void GPUThread::ReportFatalErrorAndShutdown(std::string_view reason)
|
||||
{
|
||||
DebugAssert(IsOnThread());
|
||||
|
||||
std::string message = fmt::format("GPU thread shut down with fatal error:\n\n{}", reason);
|
||||
Host::RunOnCPUThread([message = std::move(message)]() { System::AbnormalShutdown(message); });
|
||||
|
||||
// replace the renderer with a dummy/null backend, so that all commands get dropped
|
||||
ERROR_LOG("Switching to null renderer: {}", reason);
|
||||
s_state.gpu_backend.reset();
|
||||
s_state.gpu_backend = GPUBackend::CreateNullBackend(*s_state.gpu_presenter);
|
||||
if (!s_state.gpu_backend->Initialize(false, nullptr)) [[unlikely]]
|
||||
Panic("Failed to initialize null GPU backend");
|
||||
}
|
||||
|
||||
bool GPUThread::IsOnThread()
|
||||
{
|
||||
return (!s_state.use_gpu_thread || s_state.gpu_thread.IsCallingThread());
|
||||
|
@ -1193,7 +1215,11 @@ void GPUThread::DisplayWindowResizedOnThread()
|
|||
}
|
||||
|
||||
if (g_gpu_settings.gpu_resolution_scale == 0)
|
||||
s_state.gpu_backend->UpdateResolutionScale();
|
||||
{
|
||||
Error error;
|
||||
if (!s_state.gpu_backend->UpdateResolutionScale(&error)) [[unlikely]]
|
||||
ReportFatalErrorAndShutdown(fmt::format("Failed to update resolution scale: {}", error.GetDescription()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,9 @@ const WindowInfo& GetRenderWindowInfo();
|
|||
|
||||
void UpdateSettings(bool gpu_settings_changed, bool device_settings_changed);
|
||||
|
||||
/// Triggers an abnormal system shutdown and waits for it to destroy the backend.
|
||||
void ReportFatalErrorAndShutdown(std::string_view reason);
|
||||
|
||||
bool IsOnThread();
|
||||
bool IsUsingThread();
|
||||
void RunOnThread(AsyncCallType func);
|
||||
|
|
|
@ -2003,6 +2003,24 @@ void System::DestroySystem()
|
|||
Host::OnSystemDestroyed();
|
||||
}
|
||||
|
||||
void System::AbnormalShutdown(const std::string_view reason)
|
||||
{
|
||||
if (!IsValid())
|
||||
return;
|
||||
|
||||
ERROR_LOG("Abnormal shutdown: {}", reason);
|
||||
|
||||
Host::OnSystemAbnormalShutdown(reason);
|
||||
|
||||
// Immediately switch to destroying and exit execution to get out of here.
|
||||
s_state.state = State::Stopping;
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
if (s_state.system_executing)
|
||||
InterruptExecution();
|
||||
else
|
||||
DestroySystem();
|
||||
}
|
||||
|
||||
void System::ClearRunningGame()
|
||||
{
|
||||
UpdateSessionTime(s_state.running_game_serial);
|
||||
|
@ -4634,8 +4652,11 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
|||
Error error;
|
||||
if (!Bus::ReallocateMemoryMap(g_settings.export_shared_memory, &error)) [[unlikely]]
|
||||
{
|
||||
ERROR_LOG(error.GetDescription());
|
||||
Panic("Failed to reallocate memory map. The log may contain more information.");
|
||||
if (IsValid())
|
||||
{
|
||||
AbnormalShutdown(fmt::format("Failed to reallocate memory map: {}", error.GetDescription()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,9 @@ void DisplayWindowResized();
|
|||
/// Updates the internal GTE aspect ratio. Use with "match display" aspect ratio setting.
|
||||
void UpdateGTEAspectRatio();
|
||||
|
||||
/// Immediately terminates the virtual machine, no state is saved.
|
||||
void AbnormalShutdown(const std::string_view reason);
|
||||
|
||||
/// Performs mandatory hardware checks.
|
||||
bool PerformEarlyHardwareChecks(Error* error);
|
||||
|
||||
|
@ -96,6 +99,9 @@ void OnSystemPaused();
|
|||
/// Called when the VM is resumed after being paused.
|
||||
void OnSystemResumed();
|
||||
|
||||
/// Called when the VM abnormally exits because an error has occurred, and it cannot continue.
|
||||
void OnSystemAbnormalShutdown(const std::string_view reason);
|
||||
|
||||
/// Called when performance metrics are updated, approximately once a second.
|
||||
void OnPerformanceCountersUpdated(const GPUBackend* gpu_backend);
|
||||
|
||||
|
|
|
@ -1042,6 +1042,18 @@ void Host::OnSystemDestroyed()
|
|||
emit g_emu_thread->systemDestroyed();
|
||||
}
|
||||
|
||||
void Host::OnSystemAbnormalShutdown(const std::string_view reason)
|
||||
{
|
||||
Host::ReportErrorAsync(
|
||||
TRANSLATE_SV("QtHost", "Error"),
|
||||
fmt::format(
|
||||
TRANSLATE_FS("QtHost",
|
||||
"Unfortunately, the virtual machine has abnormally shut down and cannot be recovered. Please use "
|
||||
"the available support options for further assistance, and provide information about what you were "
|
||||
"doing when the error occurred, as well as the details below:\n\n{}"),
|
||||
reason));
|
||||
}
|
||||
|
||||
void Host::OnGPUThreadRunIdleChanged(bool is_active)
|
||||
{
|
||||
g_emu_thread->setGPUThreadRunIdle(is_active);
|
||||
|
|
|
@ -293,6 +293,11 @@ void Host::OnSystemResumed()
|
|||
//
|
||||
}
|
||||
|
||||
void Host::OnSystemAbnormalShutdown(const std::string_view reason)
|
||||
{
|
||||
// Already logged in core.
|
||||
}
|
||||
|
||||
void Host::OnGPUThreadRunIdleChanged(bool is_active)
|
||||
{
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue