Skip to content

Commit

Permalink
PostProcessing: Move into GPU presenter
Browse files Browse the repository at this point in the history
Means that the renderer can be changed without reloading shaders,
and speeds up config change detection.
  • Loading branch information
stenzek committed Jan 18, 2025
1 parent d589696 commit e0a9bbe
Show file tree
Hide file tree
Showing 17 changed files with 401 additions and 293 deletions.
63 changes: 44 additions & 19 deletions src/core/fullscreen_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ static void DrawFloatSpinBoxSetting(SettingsInterface* bsi, const char* title, c
float step_value, float multiplier, const char* format = "%f", bool enabled = true,
float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT,
ImFont* font = UIStyle.LargeFont, ImFont* summary_font = UIStyle.MediumFont);
static void DrawIntRectSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section,
static bool DrawIntRectSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section,
const char* left_key, int default_left, const char* top_key, int default_top,
const char* right_key, int default_right, const char* bottom_key, int default_bottom,
int min_value, int max_value, const char* format = "%d", bool enabled = true,
Expand Down Expand Up @@ -2762,7 +2762,7 @@ void FullscreenUI::DrawFloatSpinBoxSetting(SettingsInterface* bsi, const char* t
ImGui::PopFont();
}

void FullscreenUI::DrawIntRectSetting(SettingsInterface* bsi, const char* title, const char* summary,
bool FullscreenUI::DrawIntRectSetting(SettingsInterface* bsi, const char* title, const char* summary,
const char* section, const char* left_key, int default_left, const char* top_key,
int default_top, const char* right_key, int default_right, const char* bottom_key,
int default_bottom, int min_value, int max_value, const char* format,
Expand Down Expand Up @@ -2799,6 +2799,7 @@ void FullscreenUI::DrawIntRectSetting(SettingsInterface* bsi, const char* title,
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f));

bool is_open = true;
bool changed = false;
if (ImGui::BeginPopupModal(title, &is_open,
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
{
Expand Down Expand Up @@ -2864,7 +2865,8 @@ void FullscreenUI::DrawIntRectSetting(SettingsInterface* bsi, const char* title,
bsi->SetIntValue(section, bottom_key, dlg_bottom_value);
}

if (left_modified || top_modified || right_modified || bottom_modified)
changed = (left_modified || top_modified || right_modified || bottom_modified);
if (changed)
SetSettingsChanged(bsi);

if (MenuButtonWithoutSummary(FSUI_CSTR("OK"), true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, UIStyle.LargeFont,
Expand All @@ -2879,6 +2881,8 @@ void FullscreenUI::DrawIntRectSetting(SettingsInterface* bsi, const char* title,

ImGui::PopStyleVar(4);
ImGui::PopFont();

return changed;
}

void FullscreenUI::DrawIntSpinBoxSetting(SettingsInterface* bsi, const char* title, const char* summary,
Expand Down Expand Up @@ -5304,16 +5308,28 @@ enum

void FullscreenUI::DrawPostProcessingSettingsPage()
{
SettingsInterface* bsi = GetEditingSettingsInterface();
static constexpr const char* section = PostProcessing::Config::DISPLAY_CHAIN_SECTION;

static constexpr auto queue_reload = []() {
if (GPUThread::HasGPUBackend())
{
Host::RunOnCPUThread([]() {
if (System::IsValid())
GPUPresenter::ReloadPostProcessingSettings(true, false, false);
});
}
};

SettingsInterface* bsi = GetEditingSettingsInterface();
bool reload_pending = false;

BeginMenuButtons();

MenuHeading(FSUI_CSTR("Controls"));

DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_MAGIC, "Enable Post Processing"),
FSUI_CSTR("If not enabled, the current post processing chain will be ignored."), "PostProcessing",
"Enabled", false);
reload_pending |= DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_MAGIC, "Enable Post Processing"),
FSUI_CSTR("If not enabled, the current post processing chain will be ignored."),
"PostProcessing", "Enabled", false);

if (MenuButton(FSUI_ICONSTR(ICON_FA_SEARCH, "Reload Shaders"),
FSUI_CSTR("Reloads the shaders from disk, applying any changes."),
Expand All @@ -5322,12 +5338,8 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
// Have to defer because of the settings lock.
if (GPUThread::HasGPUBackend())
{
Host::RunOnCPUThread([]() {
GPUThread::RunOnThread([]() {
if (PostProcessing::ReloadShaders())
ShowToast(std::string(), FSUI_STR("Post-processing shaders reloaded."));
});
});
Host::RunOnCPUThread([]() { GPUPresenter::ReloadPostProcessingSettings(true, true, true); });
ShowToast(std::string(), FSUI_STR("Post-processing shaders reloaded."));
}
}

Expand Down Expand Up @@ -5355,6 +5367,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
PostProcessing::Config::GetStageCount(*bsi, section)));
PopulatePostProcessingChain(bsi, section);
SetSettingsChanged(bsi);
queue_reload();
}
else
{
Expand All @@ -5379,6 +5392,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
PopulatePostProcessingChain(bsi, section);
SetSettingsChanged(bsi);
ShowToast(std::string(), FSUI_STR("Post-processing chain cleared."));
queue_reload();
});
}

Expand Down Expand Up @@ -5435,6 +5449,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
opt.value[0].int_value = (value != 0);
PostProcessing::Config::SetStageOption(*bsi, section, stage_index, opt);
SetSettingsChanged(bsi);
queue_reload();
}
}
break;
Expand Down Expand Up @@ -5520,6 +5535,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
{
PostProcessing::Config::SetStageOption(*bsi, section, stage_index, opt);
SetSettingsChanged(bsi);
reload_pending = true;
}
#endif

Expand Down Expand Up @@ -5619,6 +5635,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
{
PostProcessing::Config::SetStageOption(*bsi, section, stage_index, opt);
SetSettingsChanged(bsi);
reload_pending = true;
}
#endif

Expand Down Expand Up @@ -5656,20 +5673,23 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
PostProcessing::Config::RemoveStage(*bsi, section, postprocessing_action_index);
PopulatePostProcessingChain(bsi, section);
SetSettingsChanged(bsi);
reload_pending = true;
}
break;
case POSTPROCESSING_ACTION_MOVE_UP:
{
PostProcessing::Config::MoveStageUp(*bsi, section, postprocessing_action_index);
PopulatePostProcessingChain(bsi, section);
SetSettingsChanged(bsi);
reload_pending = true;
}
break;
case POSTPROCESSING_ACTION_MOVE_DOWN:
{
PostProcessing::Config::MoveStageDown(*bsi, section, postprocessing_action_index);
PopulatePostProcessingChain(bsi, section);
SetSettingsChanged(bsi);
reload_pending = true;
}
break;
default:
Expand Down Expand Up @@ -5723,6 +5743,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
bsi->SetStringValue("BorderOverlay", "PresetName", new_value);
}
SetSettingsChanged(bsi);
queue_reload();
});
}

Expand All @@ -5740,23 +5761,27 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
SettingsInterface* const bsi = GetEditingSettingsInterface(game_settings);
bsi->SetStringValue("BorderOverlay", "ImagePath", path.c_str());
SetSettingsChanged(bsi);
queue_reload();
},
GetImageFilters());
}

DrawIntRectSetting(bsi, FSUI_ICONSTR(ICON_FA_BORDER_STYLE, "Display Area"),
FSUI_CSTR("Determines the area of the overlay image that the display will be drawn within."),
"BorderOverlay", "DisplayStartX", 0, "DisplayStartY", 0, "DisplayEndX", 0, "DisplayEndY", 0, 0,
65535, "%dpx");
reload_pending |= DrawIntRectSetting(
bsi, FSUI_ICONSTR(ICON_FA_BORDER_STYLE, "Display Area"),
FSUI_CSTR("Determines the area of the overlay image that the display will be drawn within."), "BorderOverlay",
"DisplayStartX", 0, "DisplayStartY", 0, "DisplayEndX", 0, "DisplayEndY", 0, 0, 65535, "%dpx");

DrawToggleSetting(
reload_pending |= DrawToggleSetting(
bsi, FSUI_ICONSTR(ICON_FA_BLENDER, "Destination Alpha Blending"),
FSUI_CSTR("If enabled, the display will be blended with the transparency of the overlay image."),
"BorderOverlay", "AlphaBlend", false);
}
}

EndMenuButtons();

if (reload_pending)
queue_reload();
}

void FullscreenUI::DrawAudioSettingsPage()
Expand Down Expand Up @@ -8409,7 +8434,7 @@ LoadingScreenProgressCallback::~LoadingScreenProgressCallback()
else
{
// since this was pushing frames, we need to restore the context. do that by pushing a frame ourselves
GPUThread::Internal::DoRunIdle();
GPUThread::Internal::PresentFrameAndRestoreContext();
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/core/gpu_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ bool GPUBackend::UpdateSettings(const GPUSettings& old_settings, Error* error)
return true;
}

void GPUBackend::UpdatePostProcessingSettings(bool force_reload)
{
}

GPUThreadCommand* GPUBackend::NewClearVRAMCommand()
{
return static_cast<GPUThreadCommand*>(
Expand Down
2 changes: 2 additions & 0 deletions src/core/gpu_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,12 @@ class ALIGN_TO_CACHE_LINE GPUBackend
virtual ~GPUBackend();

ALWAYS_INLINE const GPUPresenter& GetPresenter() const { return m_presenter; }
ALWAYS_INLINE GPUPresenter& GetPresenter() { return m_presenter; }

virtual bool Initialize(bool upload_vram, Error* error);

virtual bool UpdateSettings(const GPUSettings& old_settings, Error* error);
virtual void UpdatePostProcessingSettings(bool force_reload);

/// Returns the current resolution scale.
virtual u32 GetResolutionScale() const = 0;
Expand Down
86 changes: 69 additions & 17 deletions src/core/gpu_hw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ bool GPU_HW::Initialize(bool upload_vram, Error* error)
UpdateVRAMOnGPU(0, 0, VRAM_WIDTH, VRAM_HEIGHT, g_vram, VRAM_WIDTH * sizeof(u16), false, false, VRAM_SIZE_RECT);

m_drawing_area_changed = true;
LoadInternalPostProcessing();
return true;
}

Expand Down Expand Up @@ -1995,7 +1996,7 @@ void GPU_HW::CopyAndClearDepthBuffer()
{
// Take a copy of the current depth buffer so it can be used when the previous frame/buffer gets scanned out.
// Don't bother when we're not postprocessing, it'd just be a wasted copy.
if (PostProcessing::InternalChain.NeedsDepthBuffer())
if (m_internal_postfx && m_internal_postfx->NeedsDepthBuffer())
{
// TODO: Shrink this to only the active area.
GL_SCOPE("Copy Depth Buffer");
Expand Down Expand Up @@ -3849,12 +3850,12 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd)
if (IsUsingMultisampling())
{
UpdateVRAMReadTexture(!m_vram_dirty_draw_rect.eq(INVALID_RECT), !m_vram_dirty_write_rect.eq(INVALID_RECT));
m_presenter.SetDisplayTexture(m_vram_read_texture.get(), nullptr, 0, 0, m_vram_read_texture->GetWidth(),
m_presenter.SetDisplayTexture(m_vram_read_texture.get(), 0, 0, m_vram_read_texture->GetWidth(),
m_vram_read_texture->GetHeight());
}
else
{
m_presenter.SetDisplayTexture(m_vram_texture.get(), nullptr, 0, 0, m_vram_texture->GetWidth(),
m_presenter.SetDisplayTexture(m_vram_texture.get(), 0, 0, m_vram_texture->GetWidth(),
m_vram_texture->GetHeight());
}

Expand All @@ -3871,12 +3872,6 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd)
const u32 scaled_display_height = cmd->display_vram_height * resolution_scale;
bool drew_anything = false;

// Don't bother grabbing depth if postfx doesn't need it.
GPUTexture* depth_source =
(!cmd->display_24bit && m_pgxp_depth_buffer && PostProcessing::InternalChain.NeedsDepthBuffer()) ?
(m_depth_was_copied ? m_vram_depth_copy_texture.get() : m_vram_depth_texture.get()) :
nullptr;

if (cmd->display_disabled)
{
m_presenter.ClearDisplayTexture();
Expand All @@ -3885,9 +3880,9 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd)
else if (!cmd->display_24bit && line_skip == 0 && !IsUsingMultisampling() &&
(scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() &&
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight() &&
!PostProcessing::InternalChain.IsActive())
(!m_internal_postfx || !m_internal_postfx->IsActive()))
{
m_presenter.SetDisplayTexture(m_vram_texture.get(), depth_source, scaled_vram_offset_x, scaled_vram_offset_y,
m_presenter.SetDisplayTexture(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y,
scaled_display_width, scaled_display_height);

// Fast path if no copies are needed.
Expand Down Expand Up @@ -3915,6 +3910,11 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd)
m_vram_texture->MakeReadyForSampling();
g_gpu_device->InvalidateRenderTarget(m_vram_extract_texture.get());

// Don't bother grabbing depth if postfx doesn't need it.
GPUTexture* depth_source =
(!cmd->display_24bit && m_pgxp_depth_buffer && m_internal_postfx && m_internal_postfx->NeedsDepthBuffer()) ?
(m_depth_was_copied ? m_vram_depth_copy_texture.get() : m_vram_depth_texture.get()) :
nullptr;
if (depth_source &&
g_gpu_device->ResizeTexture(&m_vram_extract_depth_texture, scaled_display_width, scaled_display_height,
GPUTexture::Type::RenderTarget, VRAM_DS_COLOR_FORMAT, GPUTexture::Flags::None))
Expand Down Expand Up @@ -3968,9 +3968,21 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd)

drew_anything = true;

m_presenter.SetDisplayTexture(m_vram_extract_texture.get(),
depth_source ? m_vram_extract_depth_texture.get() : nullptr, 0, 0,
scaled_display_width, scaled_display_height);
m_presenter.SetDisplayTexture(m_vram_extract_texture.get(), 0, 0, scaled_display_width, scaled_display_height);

// Apply internal postfx if enabled.
if (m_internal_postfx && m_internal_postfx->IsActive() &&
m_internal_postfx->CheckTargets(m_vram_texture->GetFormat(), scaled_display_width, scaled_display_height))
{
GPUTexture* const postfx_output = m_internal_postfx->GetOutputTexture();
m_internal_postfx->Apply(
m_vram_extract_texture.get(), depth_source ? m_vram_extract_depth_texture.get() : nullptr,
m_internal_postfx->GetOutputTexture(), GSVector4i(0, 0, scaled_display_width, scaled_display_height),
m_presenter.GetDisplayWidth(), m_presenter.GetDisplayHeight(), cmd->display_vram_width,
cmd->display_vram_height);
m_presenter.SetDisplayTexture(postfx_output, 0, 0, postfx_output->GetWidth(), postfx_output->GetHeight());
}

if (g_settings.display_24bit_chroma_smoothing)
{
if (m_presenter.ApplyChromaSmoothing())
Expand Down Expand Up @@ -4158,7 +4170,7 @@ void GPU_HW::DownsampleFramebufferAdaptive(GPUTexture* source, u32 left, u32 top

RestoreDeviceContext();

m_presenter.SetDisplayTexture(m_downsample_texture.get(), m_presenter.GetDisplayDepthBuffer(), 0, 0, width, height);
m_presenter.SetDisplayTexture(m_downsample_texture.get(), 0, 0, width, height);
}

void GPU_HW::DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 top, u32 width, u32 height)
Expand Down Expand Up @@ -4190,8 +4202,48 @@ void GPU_HW::DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 to

RestoreDeviceContext();

m_presenter.SetDisplayTexture(m_downsample_texture.get(), m_presenter.GetDisplayDepthBuffer(), 0, 0, ds_width,
ds_height);
m_presenter.SetDisplayTexture(m_downsample_texture.get(), 0, 0, ds_width, ds_height);
}

void GPU_HW::LoadInternalPostProcessing()
{
static constexpr const char* section = PostProcessing::Config::INTERNAL_CHAIN_SECTION;

auto lock = Host::GetSettingsLock();
const SettingsInterface& si = GPUPresenter::GetPostProcessingSettingsInterface(section);

if (PostProcessing::Config::GetStageCount(si, section) == 0 || !PostProcessing::Config::IsEnabled(si, section))
return;

m_internal_postfx = std::make_unique<PostProcessing::Chain>(section);
m_internal_postfx->LoadStages(lock, si, false);
}

void GPU_HW::UpdatePostProcessingSettings(bool force_reload)
{
static constexpr const char* section = PostProcessing::Config::INTERNAL_CHAIN_SECTION;

auto lock = Host::GetSettingsLock();
const SettingsInterface& si = *Host::GetSettingsInterface();

// Don't delete the chain if we're just temporarily disabling.
if (PostProcessing::Config::GetStageCount(si, section) == 0)
{
m_internal_postfx.reset();
}
else
{
if (!m_internal_postfx || force_reload)
{
if (!m_internal_postfx)
m_internal_postfx = std::make_unique<PostProcessing::Chain>(section);
m_internal_postfx->LoadStages(lock, si, true);
}
else
{
m_internal_postfx->UpdateSettings(lock, si);
}
}
}

std::unique_ptr<GPUBackend> GPUBackend::CreateHardwareBackend(GPUPresenter& presenter)
Expand Down
Loading

0 comments on commit e0a9bbe

Please sign in to comment.