PostProcessing: Split into internal and display chains
This commit is contained in:
@@ -390,7 +390,7 @@ static void DrawFolderSetting(SettingsInterface* bsi, const char* title, const c
|
||||
|
||||
static void PopulateGraphicsAdapterList();
|
||||
static void PopulateGameListDirectoryCache(SettingsInterface* si);
|
||||
static void PopulatePostProcessingChain(SettingsInterface* si);
|
||||
static void PopulatePostProcessingChain(SettingsInterface* si, const char* section);
|
||||
static void BeginInputBinding(SettingsInterface* bsi, InputBindingInfo::Type type, std::string_view section,
|
||||
std::string_view key, std::string_view display_name);
|
||||
static void DrawInputBindingWindow();
|
||||
@@ -2733,7 +2733,7 @@ void FullscreenUI::SwitchToSettings()
|
||||
s_game_settings_interface.reset();
|
||||
|
||||
PopulateGraphicsAdapterList();
|
||||
PopulatePostProcessingChain(GetEditingSettingsInterface());
|
||||
PopulatePostProcessingChain(GetEditingSettingsInterface(), PostProcessing::Config::DISPLAY_CHAIN_SECTION);
|
||||
|
||||
s_current_main_window = MainWindowType::Settings;
|
||||
s_settings_page = SettingsPage::Interface;
|
||||
@@ -4489,16 +4489,16 @@ void FullscreenUI::DrawDisplaySettingsPage()
|
||||
EndMenuButtons();
|
||||
}
|
||||
|
||||
void FullscreenUI::PopulatePostProcessingChain(SettingsInterface* si)
|
||||
void FullscreenUI::PopulatePostProcessingChain(SettingsInterface* si, const char* section)
|
||||
{
|
||||
const u32 stages = PostProcessing::Config::GetStageCount(*si);
|
||||
const u32 stages = PostProcessing::Config::GetStageCount(*si, section);
|
||||
s_postprocessing_stages.clear();
|
||||
s_postprocessing_stages.reserve(stages);
|
||||
for (u32 i = 0; i < stages; i++)
|
||||
{
|
||||
PostProcessingStageInfo psi;
|
||||
psi.name = PostProcessing::Config::GetStageShaderName(*si, i);
|
||||
psi.options = PostProcessing::Config::GetStageOptions(*si, i);
|
||||
psi.name = PostProcessing::Config::GetStageShaderName(*si, section, i);
|
||||
psi.options = PostProcessing::Config::GetStageOptions(*si, section, i);
|
||||
s_postprocessing_stages.push_back(std::move(psi));
|
||||
}
|
||||
}
|
||||
@@ -4514,6 +4514,7 @@ enum
|
||||
void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||
{
|
||||
SettingsInterface* bsi = GetEditingSettingsInterface();
|
||||
static constexpr const char* section = PostProcessing::Config::DISPLAY_CHAIN_SECTION;
|
||||
|
||||
BeginMenuButtons();
|
||||
|
||||
@@ -4549,11 +4550,11 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||
const std::string& shader_name = shaders[index].second;
|
||||
SettingsInterface* bsi = GetEditingSettingsInterface();
|
||||
Error error;
|
||||
if (PostProcessing::Config::AddStage(*bsi, shader_name, &error))
|
||||
if (PostProcessing::Config::AddStage(*bsi, section, shader_name, &error))
|
||||
{
|
||||
ShowToast(std::string(), fmt::format(FSUI_FSTR("Shader {} added as stage {}."), title,
|
||||
PostProcessing::Config::GetStageCount(*bsi)));
|
||||
PopulatePostProcessingChain(bsi);
|
||||
PostProcessing::Config::GetStageCount(*bsi, section)));
|
||||
PopulatePostProcessingChain(bsi, section);
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
else
|
||||
@@ -4577,8 +4578,8 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||
return;
|
||||
|
||||
SettingsInterface* bsi = GetEditingSettingsInterface();
|
||||
PostProcessing::Config::ClearStages(*bsi);
|
||||
PopulatePostProcessingChain(bsi);
|
||||
PostProcessing::Config::ClearStages(*bsi, section);
|
||||
PopulatePostProcessingChain(bsi, section);
|
||||
SetSettingsChanged(bsi);
|
||||
ShowToast(std::string(), FSUI_STR("Post-processing chain cleared."));
|
||||
});
|
||||
@@ -4635,7 +4636,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||
&value))
|
||||
{
|
||||
opt.value[0].int_value = (value != 0);
|
||||
PostProcessing::Config::SetStageOption(*bsi, stage_index, opt);
|
||||
PostProcessing::Config::SetStageOption(*bsi, section, stage_index, opt);
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
}
|
||||
@@ -4719,7 +4720,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||
|
||||
if (changed)
|
||||
{
|
||||
PostProcessing::Config::SetStageOption(*bsi, stage_index, opt);
|
||||
PostProcessing::Config::SetStageOption(*bsi, section, stage_index, opt);
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
#endif
|
||||
@@ -4817,7 +4818,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||
|
||||
if (changed)
|
||||
{
|
||||
PostProcessing::Config::SetStageOption(*bsi, stage_index, opt);
|
||||
PostProcessing::Config::SetStageOption(*bsi, section, stage_index, opt);
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
#endif
|
||||
@@ -4853,22 +4854,22 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||
const PostProcessingStageInfo& si = s_postprocessing_stages[postprocessing_action_index];
|
||||
ShowToast(std::string(),
|
||||
fmt::format(FSUI_FSTR("Removed stage {} ({})."), postprocessing_action_index + 1, si.name));
|
||||
PostProcessing::Config::RemoveStage(*bsi, postprocessing_action_index);
|
||||
PopulatePostProcessingChain(bsi);
|
||||
PostProcessing::Config::RemoveStage(*bsi, section, postprocessing_action_index);
|
||||
PopulatePostProcessingChain(bsi, section);
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
break;
|
||||
case POSTPROCESSING_ACTION_MOVE_UP:
|
||||
{
|
||||
PostProcessing::Config::MoveStageUp(*bsi, postprocessing_action_index);
|
||||
PopulatePostProcessingChain(bsi);
|
||||
PostProcessing::Config::MoveStageUp(*bsi, section, postprocessing_action_index);
|
||||
PopulatePostProcessingChain(bsi, section);
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
break;
|
||||
case POSTPROCESSING_ACTION_MOVE_DOWN:
|
||||
{
|
||||
PostProcessing::Config::MoveStageDown(*bsi, postprocessing_action_index);
|
||||
PopulatePostProcessingChain(bsi);
|
||||
PostProcessing::Config::MoveStageDown(*bsi, section, postprocessing_action_index);
|
||||
PopulatePostProcessingChain(bsi, section);
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -56,6 +56,8 @@ static u64 s_active_gpu_cycles = 0;
|
||||
static u32 s_active_gpu_cycles_frames = 0;
|
||||
#endif
|
||||
|
||||
static constexpr GPUTexture::Format DISPLAY_INTERNAL_POSTFX_FORMAT = GPUTexture::Format::RGBA8;
|
||||
|
||||
GPU::GPU()
|
||||
{
|
||||
ResetStatistics();
|
||||
@@ -1932,24 +1934,53 @@ bool GPU::PresentDisplay()
|
||||
|
||||
bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_rect, bool postfx)
|
||||
{
|
||||
GL_SCOPE_FMT("RenderDisplay: {}x{} at {},{}", draw_rect.left, draw_rect.top, draw_rect.GetWidth(),
|
||||
draw_rect.GetHeight());
|
||||
GL_SCOPE_FMT("RenderDisplay: {}x{} at {},{}", draw_rect.GetWidth(), draw_rect.GetHeight(), draw_rect.left,
|
||||
draw_rect.top);
|
||||
|
||||
if (m_display_texture)
|
||||
m_display_texture->MakeReadyForSampling();
|
||||
|
||||
// Internal post-processing.
|
||||
GPUTexture* display_texture = m_display_texture;
|
||||
s32 display_texture_view_x = m_display_texture_view_x;
|
||||
s32 display_texture_view_y = m_display_texture_view_y;
|
||||
s32 display_texture_view_width = m_display_texture_view_width;
|
||||
s32 display_texture_view_height = m_display_texture_view_height;
|
||||
if (postfx && display_texture && PostProcessing::InternalChain.IsActive() &&
|
||||
PostProcessing::InternalChain.CheckTargets(DISPLAY_INTERNAL_POSTFX_FORMAT, display_texture_view_width,
|
||||
display_texture_view_height))
|
||||
{
|
||||
DebugAssert(display_texture_view_x == 0 && display_texture_view_y == 0 &&
|
||||
static_cast<s32>(display_texture->GetWidth()) == display_texture_view_width &&
|
||||
static_cast<s32>(display_texture->GetHeight()) == display_texture_view_height);
|
||||
|
||||
// Now we can apply the post chain.
|
||||
GPUTexture* post_output_texture = PostProcessing::InternalChain.GetOutputTexture();
|
||||
if (PostProcessing::InternalChain.Apply(display_texture, post_output_texture, 0, 0, display_texture_view_width,
|
||||
display_texture_view_height, display_texture_view_width,
|
||||
display_texture_view_height, m_crtc_state.display_width,
|
||||
m_crtc_state.display_height))
|
||||
{
|
||||
display_texture_view_x = 0;
|
||||
display_texture_view_y = 0;
|
||||
display_texture = post_output_texture;
|
||||
display_texture->MakeReadyForSampling();
|
||||
}
|
||||
}
|
||||
|
||||
const GPUTexture::Format hdformat = target ? target->GetFormat() : g_gpu_device->GetWindowFormat();
|
||||
const u32 target_width = target ? target->GetWidth() : g_gpu_device->GetWindowWidth();
|
||||
const u32 target_height = target ? target->GetHeight() : g_gpu_device->GetWindowHeight();
|
||||
const bool really_postfx = (postfx && PostProcessing::IsActive() && !g_gpu_device->GetWindowInfo().IsSurfaceless() &&
|
||||
hdformat != GPUTexture::Format::Unknown && target_width > 0 && target_height > 0 &&
|
||||
PostProcessing::CheckTargets(hdformat, target_width, target_height));
|
||||
const bool really_postfx =
|
||||
(postfx && PostProcessing::DisplayChain.IsActive() && !g_gpu_device->GetWindowInfo().IsSurfaceless() &&
|
||||
hdformat != GPUTexture::Format::Unknown && target_width > 0 && target_height > 0 &&
|
||||
PostProcessing::DisplayChain.CheckTargets(hdformat, target_width, target_height));
|
||||
const Common::Rectangle<s32> real_draw_rect =
|
||||
g_gpu_device->UsesLowerLeftOrigin() ? GPUDevice::FlipToLowerLeft(draw_rect, target_height) : draw_rect;
|
||||
if (really_postfx)
|
||||
{
|
||||
g_gpu_device->ClearRenderTarget(PostProcessing::GetInputTexture(), 0);
|
||||
g_gpu_device->SetRenderTarget(PostProcessing::GetInputTexture());
|
||||
g_gpu_device->ClearRenderTarget(PostProcessing::DisplayChain.GetInputTexture(), 0);
|
||||
g_gpu_device->SetRenderTarget(PostProcessing::DisplayChain.GetInputTexture());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1959,7 +1990,7 @@ bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_r
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_display_texture)
|
||||
if (display_texture)
|
||||
{
|
||||
bool texture_filter_linear = false;
|
||||
|
||||
@@ -2003,26 +2034,25 @@ bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_r
|
||||
}
|
||||
|
||||
g_gpu_device->SetPipeline(m_display_pipeline.get());
|
||||
g_gpu_device->SetTextureSampler(0, m_display_texture,
|
||||
texture_filter_linear ? g_gpu_device->GetLinearSampler() :
|
||||
g_gpu_device->GetNearestSampler());
|
||||
g_gpu_device->SetTextureSampler(
|
||||
0, display_texture, texture_filter_linear ? g_gpu_device->GetLinearSampler() : g_gpu_device->GetNearestSampler());
|
||||
|
||||
// For bilinear, clamp to 0.5/SIZE-0.5 to avoid bleeding from the adjacent texels in VRAM. This is because
|
||||
// 1.0 in UV space is not the bottom-right texel, but a mix of the bottom-right and wrapped/next texel.
|
||||
const float rcp_width = 1.0f / static_cast<float>(m_display_texture->GetWidth());
|
||||
const float rcp_height = 1.0f / static_cast<float>(m_display_texture->GetHeight());
|
||||
uniforms.src_rect[0] = static_cast<float>(m_display_texture_view_x) * rcp_width;
|
||||
uniforms.src_rect[1] = static_cast<float>(m_display_texture_view_y) * rcp_height;
|
||||
uniforms.src_rect[2] = static_cast<float>(m_display_texture_view_width) * rcp_width;
|
||||
uniforms.src_rect[3] = static_cast<float>(m_display_texture_view_height) * rcp_height;
|
||||
uniforms.clamp_rect[0] = (static_cast<float>(m_display_texture_view_x) + 0.5f) * rcp_width;
|
||||
uniforms.clamp_rect[1] = (static_cast<float>(m_display_texture_view_y) + 0.5f) * rcp_height;
|
||||
const float rcp_width = 1.0f / static_cast<float>(display_texture->GetWidth());
|
||||
const float rcp_height = 1.0f / static_cast<float>(display_texture->GetHeight());
|
||||
uniforms.src_rect[0] = static_cast<float>(display_texture_view_x) * rcp_width;
|
||||
uniforms.src_rect[1] = static_cast<float>(display_texture_view_y) * rcp_height;
|
||||
uniforms.src_rect[2] = static_cast<float>(display_texture_view_width) * rcp_width;
|
||||
uniforms.src_rect[3] = static_cast<float>(display_texture_view_height) * rcp_height;
|
||||
uniforms.clamp_rect[0] = (static_cast<float>(display_texture_view_x) + 0.5f) * rcp_width;
|
||||
uniforms.clamp_rect[1] = (static_cast<float>(display_texture_view_y) + 0.5f) * rcp_height;
|
||||
uniforms.clamp_rect[2] =
|
||||
(static_cast<float>(m_display_texture_view_x + m_display_texture_view_width) - 0.5f) * rcp_width;
|
||||
(static_cast<float>(display_texture_view_x + display_texture_view_width) - 0.5f) * rcp_width;
|
||||
uniforms.clamp_rect[3] =
|
||||
(static_cast<float>(m_display_texture_view_y + m_display_texture_view_height) - 0.5f) * rcp_height;
|
||||
uniforms.src_size[0] = static_cast<float>(m_display_texture->GetWidth());
|
||||
uniforms.src_size[1] = static_cast<float>(m_display_texture->GetHeight());
|
||||
(static_cast<float>(display_texture_view_y + display_texture_view_height) - 0.5f) * rcp_height;
|
||||
uniforms.src_size[0] = static_cast<float>(display_texture->GetWidth());
|
||||
uniforms.src_size[1] = static_cast<float>(display_texture->GetHeight());
|
||||
uniforms.src_size[2] = rcp_width;
|
||||
uniforms.src_size[3] = rcp_height;
|
||||
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
|
||||
@@ -2044,9 +2074,10 @@ bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle<s32>& draw_r
|
||||
const s32 orig_width = static_cast<s32>(std::ceil(static_cast<float>(m_crtc_state.display_width) * upscale_x));
|
||||
const s32 orig_height = static_cast<s32>(std::ceil(static_cast<float>(m_crtc_state.display_height) * upscale_y));
|
||||
|
||||
return PostProcessing::Apply(target, real_draw_rect.left, real_draw_rect.top, real_draw_rect.GetWidth(),
|
||||
real_draw_rect.GetHeight(), orig_width, orig_height, m_crtc_state.display_width,
|
||||
m_crtc_state.display_height);
|
||||
return PostProcessing::DisplayChain.Apply(PostProcessing::DisplayChain.GetInputTexture(), target,
|
||||
real_draw_rect.left, real_draw_rect.top, real_draw_rect.GetWidth(),
|
||||
real_draw_rect.GetHeight(), orig_width, orig_height,
|
||||
m_crtc_state.display_width, m_crtc_state.display_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "system.h"
|
||||
|
||||
#include "util/imgui_manager.h"
|
||||
#include "util/postprocessing.h"
|
||||
#include "util/state_wrapper.h"
|
||||
|
||||
#include "common/align.h"
|
||||
@@ -3311,7 +3312,8 @@ void GPU_HW::UpdateDisplay()
|
||||
}
|
||||
else if (!m_GPUSTAT.display_area_color_depth_24 && !IsUsingMultisampling() &&
|
||||
(scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() &&
|
||||
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight())
|
||||
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight() &&
|
||||
!PostProcessing::InternalChain.IsActive())
|
||||
{
|
||||
SetDisplayTexture(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y, scaled_display_width,
|
||||
read_height);
|
||||
|
||||
@@ -406,7 +406,13 @@ DEFINE_HOTKEY("DecreaseResolutionScale", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
DEFINE_HOTKEY("TogglePostProcessing", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Toggle Post-Processing"), [](s32 pressed) {
|
||||
if (!pressed && System::IsValid())
|
||||
PostProcessing::Toggle();
|
||||
PostProcessing::DisplayChain.Toggle();
|
||||
})
|
||||
|
||||
DEFINE_HOTKEY("ToggleInternalPostProcessing", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Toggle Internal Post-Processing"), [](s32 pressed) {
|
||||
if (!pressed && System::IsValid())
|
||||
PostProcessing::InternalChain.Toggle();
|
||||
})
|
||||
|
||||
DEFINE_HOTKEY("ReloadPostProcessingShaders", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
|
||||
Reference in New Issue
Block a user