GPU: Propagate initialization error to caller

Avoids double error popup.
This commit is contained in:
Stenzek 2024-10-26 01:41:26 +10:00
parent 6af71beed5
commit 1ae2dcf192
No known key found for this signature in database
7 changed files with 43 additions and 48 deletions

View File

@ -95,7 +95,7 @@ GPU::~GPU()
g_gpu_device->RecycleTexture(std::move(m_chroma_smoothing_texture)); g_gpu_device->RecycleTexture(std::move(m_chroma_smoothing_texture));
} }
bool GPU::Initialize() bool GPU::Initialize(Error* error)
{ {
if (!System::IsReplayingGPUDump()) if (!System::IsReplayingGPUDump())
s_crtc_tick_event.Activate(); s_crtc_tick_event.Activate();
@ -107,11 +107,8 @@ bool GPU::Initialize()
m_console_is_pal = System::IsPALRegion(); m_console_is_pal = System::IsPALRegion();
UpdateCRTCConfig(); UpdateCRTCConfig();
if (!CompileDisplayPipelines(true, true, g_settings.display_24bit_chroma_smoothing)) if (!CompileDisplayPipelines(true, true, g_settings.display_24bit_chroma_smoothing, error))
{
Host::ReportErrorAsync("Error", "Failed to compile base GPU pipelines.");
return false; return false;
}
#ifdef PSX_GPU_STATS #ifdef PSX_GPU_STATS
s_active_gpu_cycles = 0; s_active_gpu_cycles = 0;
@ -152,7 +149,7 @@ void GPU::UpdateSettings(const Settings& old_settings)
if (!CompileDisplayPipelines(g_settings.display_scaling != old_settings.display_scaling, if (!CompileDisplayPipelines(g_settings.display_scaling != old_settings.display_scaling,
g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode, g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode,
g_settings.display_24bit_chroma_smoothing != g_settings.display_24bit_chroma_smoothing !=
old_settings.display_24bit_chroma_smoothing)) old_settings.display_24bit_chroma_smoothing, nullptr))
{ {
Panic("Failed to compile display pipeline on settings change."); Panic("Failed to compile display pipeline on settings change.");
} }
@ -1650,7 +1647,7 @@ void GPU::ReadCLUT(u16* dest, GPUTexturePaletteReg reg, bool clut_is_8bit)
} }
} }
bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_smoothing) bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_smoothing, Error* error)
{ {
GPUShaderGen shadergen(g_gpu_device->GetRenderAPI(), g_gpu_device->GetFeatures().dual_source_blend, GPUShaderGen shadergen(g_gpu_device->GetRenderAPI(), g_gpu_device->GetFeatures().dual_source_blend,
g_gpu_device->GetFeatures().framebuffer_fetch); g_gpu_device->GetFeatures().framebuffer_fetch);
@ -1693,8 +1690,10 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
break; break;
} }
std::unique_ptr<GPUShader> vso = g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), vs); std::unique_ptr<GPUShader> vso =
std::unique_ptr<GPUShader> fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), fs); g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), vs, error);
std::unique_ptr<GPUShader> fso =
g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), fs, error);
if (!vso || !fso) if (!vso || !fso)
return false; return false;
GL_OBJECT_NAME(vso, "Display Vertex Shader"); GL_OBJECT_NAME(vso, "Display Vertex Shader");
@ -1702,7 +1701,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
Settings::GetDisplayScalingName(g_settings.display_scaling)); Settings::GetDisplayScalingName(g_settings.display_scaling));
plconfig.vertex_shader = vso.get(); plconfig.vertex_shader = vso.get();
plconfig.fragment_shader = fso.get(); plconfig.fragment_shader = fso.get();
if (!(m_display_pipeline = g_gpu_device->CreatePipeline(plconfig))) if (!(m_display_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
return false; return false;
GL_OBJECT_NAME_FMT(m_display_pipeline, "Display Pipeline [{}]", GL_OBJECT_NAME_FMT(m_display_pipeline, "Display Pipeline [{}]",
Settings::GetDisplayScalingName(g_settings.display_scaling)); Settings::GetDisplayScalingName(g_settings.display_scaling));
@ -1713,14 +1712,14 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
plconfig.SetTargetFormats(GPUTexture::Format::RGBA8); plconfig.SetTargetFormats(GPUTexture::Format::RGBA8);
std::unique_ptr<GPUShader> vso = g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), std::unique_ptr<GPUShader> vso = g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(),
shadergen.GenerateScreenQuadVertexShader()); shadergen.GenerateScreenQuadVertexShader(), error);
if (!vso) if (!vso)
return false; return false;
GL_OBJECT_NAME(vso, "Deinterlace Vertex Shader"); GL_OBJECT_NAME(vso, "Deinterlace Vertex Shader");
std::unique_ptr<GPUShader> fso; std::unique_ptr<GPUShader> fso;
if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(),
shadergen.GenerateInterleavedFieldExtractFragmentShader()))) shadergen.GenerateInterleavedFieldExtractFragmentShader(), error)))
{ {
return false; return false;
} }
@ -1730,7 +1729,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
plconfig.layout = GPUPipeline::Layout::SingleTextureAndPushConstants; plconfig.layout = GPUPipeline::Layout::SingleTextureAndPushConstants;
plconfig.vertex_shader = vso.get(); plconfig.vertex_shader = vso.get();
plconfig.fragment_shader = fso.get(); plconfig.fragment_shader = fso.get();
if (!(m_deinterlace_extract_pipeline = g_gpu_device->CreatePipeline(plconfig))) if (!(m_deinterlace_extract_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
return false; return false;
GL_OBJECT_NAME(m_deinterlace_extract_pipeline, "Deinterlace Field Extract Pipeline"); GL_OBJECT_NAME(m_deinterlace_extract_pipeline, "Deinterlace Field Extract Pipeline");
@ -1744,7 +1743,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
case DisplayDeinterlacingMode::Weave: case DisplayDeinterlacingMode::Weave:
{ {
if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(),
shadergen.GenerateDeinterlaceWeaveFragmentShader()))) shadergen.GenerateDeinterlaceWeaveFragmentShader(), error)))
{ {
return false; return false;
} }
@ -1754,7 +1753,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
plconfig.layout = GPUPipeline::Layout::SingleTextureAndPushConstants; plconfig.layout = GPUPipeline::Layout::SingleTextureAndPushConstants;
plconfig.vertex_shader = vso.get(); plconfig.vertex_shader = vso.get();
plconfig.fragment_shader = fso.get(); plconfig.fragment_shader = fso.get();
if (!(m_deinterlace_pipeline = g_gpu_device->CreatePipeline(plconfig))) if (!(m_deinterlace_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
return false; return false;
GL_OBJECT_NAME(m_deinterlace_pipeline, "Weave Deinterlace Pipeline"); GL_OBJECT_NAME(m_deinterlace_pipeline, "Weave Deinterlace Pipeline");
@ -1764,7 +1763,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
case DisplayDeinterlacingMode::Blend: case DisplayDeinterlacingMode::Blend:
{ {
if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), if (!(fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(),
shadergen.GenerateDeinterlaceBlendFragmentShader()))) shadergen.GenerateDeinterlaceBlendFragmentShader(), error)))
{ {
return false; return false;
} }
@ -1774,7 +1773,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
plconfig.layout = GPUPipeline::Layout::MultiTextureAndPushConstants; plconfig.layout = GPUPipeline::Layout::MultiTextureAndPushConstants;
plconfig.vertex_shader = vso.get(); plconfig.vertex_shader = vso.get();
plconfig.fragment_shader = fso.get(); plconfig.fragment_shader = fso.get();
if (!(m_deinterlace_pipeline = g_gpu_device->CreatePipeline(plconfig))) if (!(m_deinterlace_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
return false; return false;
GL_OBJECT_NAME(m_deinterlace_pipeline, "Blend Deinterlace Pipeline"); GL_OBJECT_NAME(m_deinterlace_pipeline, "Blend Deinterlace Pipeline");
@ -1784,7 +1783,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
case DisplayDeinterlacingMode::Adaptive: case DisplayDeinterlacingMode::Adaptive:
{ {
fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(),
shadergen.GenerateFastMADReconstructFragmentShader()); shadergen.GenerateFastMADReconstructFragmentShader(), error);
if (!fso) if (!fso)
return false; return false;
@ -1792,7 +1791,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
plconfig.layout = GPUPipeline::Layout::MultiTextureAndPushConstants; plconfig.layout = GPUPipeline::Layout::MultiTextureAndPushConstants;
plconfig.fragment_shader = fso.get(); plconfig.fragment_shader = fso.get();
if (!(m_deinterlace_pipeline = g_gpu_device->CreatePipeline(plconfig))) if (!(m_deinterlace_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
return false; return false;
GL_OBJECT_NAME(m_deinterlace_pipeline, "FastMAD Reconstruct Pipeline"); GL_OBJECT_NAME(m_deinterlace_pipeline, "FastMAD Reconstruct Pipeline");
@ -1815,9 +1814,9 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
plconfig.SetTargetFormats(GPUTexture::Format::RGBA8); plconfig.SetTargetFormats(GPUTexture::Format::RGBA8);
std::unique_ptr<GPUShader> vso = g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), std::unique_ptr<GPUShader> vso = g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(),
shadergen.GenerateScreenQuadVertexShader()); shadergen.GenerateScreenQuadVertexShader(), error);
std::unique_ptr<GPUShader> fso = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), std::unique_ptr<GPUShader> fso = g_gpu_device->CreateShader(
shadergen.GenerateChromaSmoothingFragmentShader()); GPUShaderStage::Fragment, shadergen.GetLanguage(), shadergen.GenerateChromaSmoothingFragmentShader(), error);
if (!vso || !fso) if (!vso || !fso)
return false; return false;
GL_OBJECT_NAME(vso, "Chroma Smoothing Vertex Shader"); GL_OBJECT_NAME(vso, "Chroma Smoothing Vertex Shader");
@ -1825,7 +1824,7 @@ bool GPU::CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_sm
plconfig.vertex_shader = vso.get(); plconfig.vertex_shader = vso.get();
plconfig.fragment_shader = fso.get(); plconfig.fragment_shader = fso.get();
if (!(m_chroma_smoothing_pipeline = g_gpu_device->CreatePipeline(plconfig))) if (!(m_chroma_smoothing_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
return false; return false;
GL_OBJECT_NAME(m_chroma_smoothing_pipeline, "Chroma Smoothing Pipeline"); GL_OBJECT_NAME(m_chroma_smoothing_pipeline, "Chroma Smoothing Pipeline");
} }

View File

@ -92,7 +92,7 @@ public:
virtual const Threading::Thread* GetSWThread() const = 0; virtual const Threading::Thread* GetSWThread() const = 0;
virtual bool IsHardwareRenderer() const = 0; virtual bool IsHardwareRenderer() const = 0;
virtual bool Initialize(); virtual bool Initialize(Error* error);
virtual void Reset(bool clear_vram); virtual void Reset(bool clear_vram);
virtual bool DoState(StateWrapper& sw, GPUTexture** save_to_texture, bool update_display); virtual bool DoState(StateWrapper& sw, GPUTexture** save_to_texture, bool update_display);
@ -184,8 +184,8 @@ public:
float ComputeVerticalFrequency() const; float ComputeVerticalFrequency() const;
float ComputeDisplayAspectRatio() const; float ComputeDisplayAspectRatio() const;
static std::unique_ptr<GPU> CreateHardwareRenderer(); static std::unique_ptr<GPU> CreateHardwareRenderer(Error* error);
static std::unique_ptr<GPU> CreateSoftwareRenderer(); static std::unique_ptr<GPU> CreateSoftwareRenderer(Error* error);
// Converts window coordinates into horizontal ticks and scanlines. Returns false if out of range. Used for lightguns. // Converts window coordinates into horizontal ticks and scanlines. Returns false if out of range. Used for lightguns.
void ConvertScreenCoordinatesToDisplayCoordinates(float window_x, float window_y, float* display_x, void ConvertScreenCoordinatesToDisplayCoordinates(float window_x, float window_y, float* display_x,
@ -631,7 +631,7 @@ protected:
Stats m_stats = {}; Stats m_stats = {};
private: private:
bool CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_smoothing); bool CompileDisplayPipelines(bool display, bool deinterlace, bool chroma_smoothing, Error* error);
using GP0CommandHandler = bool (GPU::*)(); using GP0CommandHandler = bool (GPU::*)();
using GP0CommandHandlerTable = std::array<GP0CommandHandler, 256>; using GP0CommandHandlerTable = std::array<GP0CommandHandler, 256>;

View File

@ -245,9 +245,9 @@ bool GPU_HW::IsHardwareRenderer() const
return true; return true;
} }
bool GPU_HW::Initialize() bool GPU_HW::Initialize(Error* error)
{ {
if (!GPU::Initialize()) if (!GPU::Initialize(error))
return false; return false;
const GPUDevice::Features features = g_gpu_device->GetFeatures(); const GPUDevice::Features features = g_gpu_device->GetFeatures();
@ -275,16 +275,12 @@ bool GPU_HW::Initialize()
PrintSettingsToLog(); PrintSettingsToLog();
Error error; if (!CompilePipelines(error))
if (!CompilePipelines(&error))
{
ERROR_LOG("Failed to compile pipelines: {}", error.GetDescription());
return false; return false;
}
if (!CreateBuffers()) if (!CreateBuffers())
{ {
ERROR_LOG("Failed to create framebuffer"); Error::SetStringView(error, "Failed to create framebuffer");
return false; return false;
} }
@ -4214,11 +4210,11 @@ void GPU_HW::DrawRendererStats()
} }
} }
std::unique_ptr<GPU> GPU::CreateHardwareRenderer() std::unique_ptr<GPU> GPU::CreateHardwareRenderer(Error* error)
{ {
std::unique_ptr<GPU_HW> gpu(std::make_unique<GPU_HW>()); std::unique_ptr<GPU_HW> gpu(std::make_unique<GPU_HW>());
if (!gpu->Initialize()) if (!gpu->Initialize(error))
return nullptr; gpu.reset();
return gpu; return gpu;
} }

View File

@ -66,7 +66,7 @@ public:
const Threading::Thread* GetSWThread() const override; const Threading::Thread* GetSWThread() const override;
bool IsHardwareRenderer() const override; bool IsHardwareRenderer() const override;
bool Initialize() override; bool Initialize(Error* error) override;
void Reset(bool clear_vram) override; void Reset(bool clear_vram) override;
bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override; bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;

View File

@ -36,9 +36,9 @@ bool GPU_SW::IsHardwareRenderer() const
return false; return false;
} }
bool GPU_SW::Initialize() bool GPU_SW::Initialize(Error* error)
{ {
if (!GPU::Initialize() || !m_backend.Initialize(g_settings.gpu_use_thread)) if (!GPU::Initialize(error) || !m_backend.Initialize(g_settings.gpu_use_thread))
return false; return false;
static constexpr const std::array formats_for_16bit = {GPUTexture::Format::RGB565, GPUTexture::Format::RGBA5551, static constexpr const std::array formats_for_16bit = {GPUTexture::Format::RGB565, GPUTexture::Format::RGBA5551,
@ -810,11 +810,11 @@ void GPU_SW::UpdateCLUT(GPUTexturePaletteReg reg, bool clut_is_8bit)
m_backend.PushCommand(cmd); m_backend.PushCommand(cmd);
} }
std::unique_ptr<GPU> GPU::CreateSoftwareRenderer() std::unique_ptr<GPU> GPU::CreateSoftwareRenderer(Error* error)
{ {
std::unique_ptr<GPU_SW> gpu(std::make_unique<GPU_SW>()); std::unique_ptr<GPU_SW> gpu(std::make_unique<GPU_SW>());
if (!gpu->Initialize()) if (!gpu->Initialize(error))
return nullptr; gpu.reset();
return gpu; return gpu;
} }

View File

@ -29,7 +29,7 @@ public:
const Threading::Thread* GetSWThread() const override; const Threading::Thread* GetSWThread() const override;
bool IsHardwareRenderer() const override; bool IsHardwareRenderer() const override;
bool Initialize() override; bool Initialize(Error* error) override;
bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override; bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;
void Reset(bool clear_vram) override; void Reset(bool clear_vram) override;
void UpdateSettings(const Settings& old_settings) override; void UpdateSettings(const Settings& old_settings) override;

View File

@ -2466,9 +2466,9 @@ bool System::CreateGPU(GPURenderer renderer, bool is_switching, bool fullscreen,
} }
if (renderer == GPURenderer::Software) if (renderer == GPURenderer::Software)
g_gpu = GPU::CreateSoftwareRenderer(); g_gpu = GPU::CreateSoftwareRenderer(error);
else else
g_gpu = GPU::CreateHardwareRenderer(); g_gpu = GPU::CreateHardwareRenderer(error);
if (!g_gpu) if (!g_gpu)
{ {
@ -2479,7 +2479,7 @@ bool System::CreateGPU(GPURenderer renderer, bool is_switching, bool fullscreen,
Settings::GetRendererName(renderer)), Settings::GetRendererName(renderer)),
Host::OSD_CRITICAL_ERROR_DURATION); Host::OSD_CRITICAL_ERROR_DURATION);
g_gpu.reset(); g_gpu.reset();
g_gpu = GPU::CreateSoftwareRenderer(); g_gpu = GPU::CreateSoftwareRenderer(error);
if (!g_gpu) if (!g_gpu)
{ {
ERROR_LOG("Failed to create fallback software renderer."); ERROR_LOG("Failed to create fallback software renderer.");