mirror of
https://github.com/stenzek/duckstation.git
synced 2026-02-10 16:34:36 +00:00
PostProcessing: Support unscaled input
Needed for slang support.
This commit is contained in:
@@ -4072,7 +4072,9 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd)
|
||||
|
||||
// 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))
|
||||
m_internal_postfx->CheckTargets(m_vram_texture->GetFormat(), scaled_display_width, scaled_display_height,
|
||||
m_vram_texture->GetFormat(), scaled_display_width, scaled_display_height,
|
||||
scaled_display_width, scaled_display_height))
|
||||
{
|
||||
GPUTexture* const postfx_output = m_internal_postfx->GetOutputTexture();
|
||||
m_internal_postfx->Apply(
|
||||
|
||||
@@ -452,6 +452,7 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
|
||||
// Compute draw area.
|
||||
GSVector4i display_rect;
|
||||
GSVector4i draw_rect;
|
||||
GSVector4i real_draw_rect;
|
||||
GSVector4i overlay_display_rect = GSVector4i::zero();
|
||||
GSVector4i overlay_rect = GSVector4i::zero();
|
||||
if (have_overlay)
|
||||
@@ -471,15 +472,16 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
|
||||
|
||||
// Draw to the overlay area instead of the whole screen. Always align in center, we align the overlay instead.
|
||||
CalculateDrawRect(overlay_display_rect.width(), overlay_display_rect.height(), apply_aspect_ratio, integer_scale,
|
||||
false, &display_rect, &draw_rect);
|
||||
false, &display_rect, &real_draw_rect);
|
||||
|
||||
// Apply overlay area offset.
|
||||
display_rect = display_rect.add32(overlay_display_rect.xyxy());
|
||||
draw_rect = draw_rect.add32(overlay_display_rect.xyxy());
|
||||
draw_rect = real_draw_rect.add32(overlay_display_rect.xyxy());
|
||||
}
|
||||
else
|
||||
{
|
||||
CalculateDrawRect(target_size.x, target_size.y, apply_aspect_ratio, integer_scale, true, &display_rect, &draw_rect);
|
||||
real_draw_rect = draw_rect;
|
||||
}
|
||||
|
||||
// There's a bunch of scenarios where we need to use intermediate buffers.
|
||||
@@ -489,7 +491,10 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
|
||||
const GSVector2i postfx_size = have_overlay ? overlay_display_rect.rsize() : target_size;
|
||||
const bool really_postfx =
|
||||
(postfx && !is_vram_view && m_display_postfx && m_display_postfx->IsActive() && m_display_postfx &&
|
||||
m_display_postfx->CheckTargets(m_present_format, postfx_size.x, postfx_size.y));
|
||||
m_display_postfx->CheckTargets(m_display_texture ? m_display_texture->GetFormat() : GPUTexture::Format::Unknown,
|
||||
m_display_texture_view_width, m_display_texture_view_height, m_present_format,
|
||||
postfx_size.x, postfx_size.y, m_display_texture ? real_draw_rect.width() : 0,
|
||||
m_display_texture ? real_draw_rect.height() : 0));
|
||||
GL_INS(really_postfx ? "Post-processing is ENABLED" : "Post-processing is disabled");
|
||||
GL_INS_FMT("Post-processing render target size: {}x{}", postfx_size.x, postfx_size.y);
|
||||
|
||||
@@ -517,26 +522,61 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
|
||||
// If postfx is enabled, we need to draw to an intermediate buffer first.
|
||||
if (really_postfx)
|
||||
{
|
||||
// Remove draw offset if we're using an overlay.
|
||||
const GSVector4i real_draw_rect = have_overlay ? draw_rect.sub32(overlay_display_rect.xyxy()) : draw_rect;
|
||||
|
||||
// Display is always drawn to the postfx input.
|
||||
GPUTexture* const postfx_input = m_display_postfx->GetInputTexture();
|
||||
g_gpu_device->ClearRenderTarget(postfx_input, GPUDevice::DEFAULT_CLEAR_COLOR);
|
||||
g_gpu_device->SetRenderTarget(postfx_input);
|
||||
g_gpu_device->SetViewport(GSVector4i::loadh(postfx_size));
|
||||
if (m_display_texture)
|
||||
GPUTexture* postfx_input;
|
||||
if (!m_display_postfx->WantsUnscaledInput() || !m_display_texture)
|
||||
{
|
||||
DrawDisplay(postfx_size, postfx_size, real_draw_rect, false, g_gpu_settings.display_rotation,
|
||||
WindowInfo::PreRotation::Identity);
|
||||
postfx_input = m_display_postfx->GetInputTexture();
|
||||
g_gpu_device->ClearRenderTarget(postfx_input, GPUDevice::DEFAULT_CLEAR_COLOR);
|
||||
g_gpu_device->SetRenderTarget(postfx_input);
|
||||
g_gpu_device->SetViewport(GSVector4i::loadh(postfx_size));
|
||||
if (m_display_texture)
|
||||
{
|
||||
DrawDisplay(postfx_size, postfx_size, real_draw_rect, false, g_gpu_settings.display_rotation,
|
||||
WindowInfo::PreRotation::Identity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: If there's padding, it needs to be applied here.
|
||||
// TODO: If rotating, we need to apply it here too.
|
||||
postfx_input = m_display_texture;
|
||||
if (g_gpu_device->UsesLowerLeftOrigin() || g_settings.display_rotation != DisplayRotation::Normal)
|
||||
{
|
||||
// OpenGL needs to flip the correct way around.
|
||||
const GSVector2i input_size = GSVector2i(m_display_texture_view_width, m_display_texture_view_height);
|
||||
const GSVector4 src_uv_rect = GSVector4(GSVector4i(m_display_texture_view_x, m_display_texture_view_y,
|
||||
m_display_texture_view_x + m_display_texture_view_width,
|
||||
m_display_texture_view_y + m_display_texture_view_height)) /
|
||||
GSVector4::xyxy(GSVector2(m_display_texture->GetSizeVec()));
|
||||
|
||||
postfx_input = m_display_postfx->GetInputTexture();
|
||||
m_display_texture->MakeReadyForSampling();
|
||||
g_gpu_device->SetRenderTarget(postfx_input);
|
||||
g_gpu_device->SetViewportAndScissor(GSVector4i::loadh(input_size));
|
||||
g_gpu_device->SetPipeline(m_present_copy_pipeline.get());
|
||||
g_gpu_device->SetTextureSampler(0, m_display_texture, g_gpu_device->GetNearestSampler());
|
||||
DrawScreenQuad(GSVector4i::loadh(input_size), src_uv_rect, input_size, input_size, g_settings.display_rotation,
|
||||
prerotation, nullptr, 0);
|
||||
}
|
||||
else if (m_display_texture_view_x != 0 || m_display_texture_view_y != 0 ||
|
||||
m_display_texture->GetWidth() != static_cast<u32>(m_display_texture_view_width) ||
|
||||
m_display_texture->GetHeight() != static_cast<u32>(m_display_texture_view_height))
|
||||
{
|
||||
postfx_input = m_display_postfx->GetInputTexture();
|
||||
g_gpu_device->CopyTextureRegion(postfx_input, 0, 0, 0, 0, m_display_texture, m_display_texture_view_x,
|
||||
m_display_texture_view_y, 0, 0, m_display_texture_view_width,
|
||||
m_display_texture_view_height);
|
||||
}
|
||||
}
|
||||
|
||||
postfx_input->MakeReadyForSampling();
|
||||
|
||||
// Apply postprocessing to an intermediate texture if we're prerotating or have an overlay.
|
||||
if (have_prerotation || have_overlay)
|
||||
{
|
||||
GPUTexture* const postfx_output = m_display_postfx->GetTextureUnusedAtEndOfChain();
|
||||
ApplyDisplayPostProcess(postfx_output, postfx_input, real_draw_rect);
|
||||
ApplyDisplayPostProcess(postfx_output, postfx_input, real_draw_rect, postfx_size);
|
||||
postfx_output->MakeReadyForSampling();
|
||||
|
||||
// Start draw to final buffer.
|
||||
@@ -577,7 +617,7 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
|
||||
else
|
||||
{
|
||||
// Otherwise apply postprocessing directly to swap chain.
|
||||
return ApplyDisplayPostProcess(target, postfx_input, display_rect);
|
||||
return ApplyDisplayPostProcess(target, postfx_input, display_rect, postfx_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -826,10 +866,18 @@ void GPUPresenter::DrawScreenQuad(const GSVector4i rect, const GSVector4 uv_rect
|
||||
}
|
||||
|
||||
GPUDevice::PresentResult GPUPresenter::ApplyDisplayPostProcess(GPUTexture* target, GPUTexture* input,
|
||||
const GSVector4i display_rect)
|
||||
const GSVector4i display_rect,
|
||||
const GSVector2i postfx_size)
|
||||
{
|
||||
DebugAssert(!g_gpu_settings.gpu_show_vram);
|
||||
|
||||
if (!m_display_texture)
|
||||
{
|
||||
// Avoid passing invalid rectangles into the postfx backend.
|
||||
return m_display_postfx->Apply(input, nullptr, target, GSVector4i::loadh(postfx_size), postfx_size.x, postfx_size.y,
|
||||
postfx_size.x, postfx_size.y);
|
||||
}
|
||||
|
||||
// "original size" in postfx includes padding.
|
||||
const float upscale_x =
|
||||
m_display_texture ? static_cast<float>(m_display_texture_view_width) / static_cast<float>(m_display_vram_width) :
|
||||
|
||||
@@ -114,7 +114,7 @@ private:
|
||||
void DrawDisplay(const GSVector2i target_size, const GSVector2i final_target_size, const GSVector4i display_rect,
|
||||
bool dst_alpha_blend, DisplayRotation rotation, WindowInfo::PreRotation prerotation);
|
||||
GPUDevice::PresentResult ApplyDisplayPostProcess(GPUTexture* target, GPUTexture* input,
|
||||
const GSVector4i display_rect);
|
||||
const GSVector4i display_rect, const GSVector2i postfx_size);
|
||||
|
||||
bool DeinterlaceSetTargetSize(u32 width, u32 height, bool preserve);
|
||||
void DestroyDeinterlaceTextures();
|
||||
|
||||
@@ -410,6 +410,7 @@ void PostProcessing::Chain::LoadStages(std::unique_lock<std::mutex>& settings_lo
|
||||
|
||||
m_enabled = si.GetBoolValue(m_section, "Enabled", false);
|
||||
m_wants_depth_buffer = false;
|
||||
m_wants_unscaled_input = false;
|
||||
|
||||
const u32 stage_count = Config::GetStageCount(si, m_section);
|
||||
if (stage_count == 0)
|
||||
@@ -453,13 +454,18 @@ void PostProcessing::Chain::LoadStages(std::unique_lock<std::mutex>& settings_lo
|
||||
// precompile shaders
|
||||
if (preload_swap_chain_size && g_gpu_device && g_gpu_device->HasMainSwapChain())
|
||||
{
|
||||
CheckTargets(g_gpu_device->GetMainSwapChain()->GetFormat(), g_gpu_device->GetMainSwapChain()->GetWidth(),
|
||||
g_gpu_device->GetMainSwapChain()->GetHeight(), &progress);
|
||||
const GPUSwapChain* swap_chain = g_gpu_device->GetMainSwapChain();
|
||||
CheckTargets(swap_chain->GetFormat(), swap_chain->GetWidth(), swap_chain->GetHeight(), swap_chain->GetFormat(),
|
||||
swap_chain->GetWidth(), swap_chain->GetHeight(), swap_chain->GetWidth(), swap_chain->GetHeight(),
|
||||
&progress);
|
||||
}
|
||||
|
||||
// must be down here, because we need to compile first, triggered by CheckTargets()
|
||||
for (std::unique_ptr<Shader>& shader : m_stages)
|
||||
{
|
||||
m_wants_depth_buffer |= shader->WantsDepthBuffer();
|
||||
m_wants_unscaled_input |= shader->WantsUnscaledInput();
|
||||
}
|
||||
m_needs_depth_buffer = m_enabled && m_wants_depth_buffer;
|
||||
if (m_wants_depth_buffer)
|
||||
DEV_LOG("Depth buffer is needed.");
|
||||
@@ -531,7 +537,10 @@ void PostProcessing::Chain::UpdateSettings(std::unique_lock<std::mutex>& setting
|
||||
}
|
||||
|
||||
if (prev_format != GPUTexture::Format::Unknown)
|
||||
CheckTargets(prev_format, m_target_width, m_target_height, &progress);
|
||||
{
|
||||
CheckTargets(prev_format, m_target_width, m_target_height, m_source_format, m_source_width, m_source_height,
|
||||
m_viewport_width, m_viewport_height, &progress);
|
||||
}
|
||||
|
||||
if (stage_count > 0)
|
||||
{
|
||||
@@ -573,64 +582,120 @@ void PostProcessing::Chain::Toggle()
|
||||
s_start_time = Timer::GetCurrentValue();
|
||||
}
|
||||
|
||||
bool PostProcessing::Chain::CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height,
|
||||
bool PostProcessing::Chain::CheckTargets(GPUTexture::Format source_format, u32 source_width, u32 source_height,
|
||||
GPUTexture::Format target_format, u32 target_width, u32 target_height,
|
||||
u32 viewport_width, u32 viewport_height,
|
||||
ProgressCallback* progress /* = nullptr */)
|
||||
{
|
||||
if (m_target_format == target_format && m_target_width == target_width && m_target_height == target_height)
|
||||
// might not have a source, this is okay
|
||||
if (!m_wants_unscaled_input || source_width == 0 || source_height == 0)
|
||||
{
|
||||
source_format = target_format;
|
||||
source_width = target_width;
|
||||
source_height = target_height;
|
||||
viewport_width = target_width;
|
||||
viewport_height = target_height;
|
||||
}
|
||||
|
||||
if (m_target_width == target_width && m_target_height == target_height && m_source_width == source_width &&
|
||||
m_source_height == source_height && m_viewport_width == viewport_width && m_viewport_height == viewport_height &&
|
||||
m_source_format == source_format && m_target_format == target_format)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Error error;
|
||||
|
||||
// In case any allocs fail.
|
||||
DestroyTextures();
|
||||
|
||||
if (!(m_input_texture =
|
||||
g_gpu_device->FetchTexture(target_width, target_height, 1, 1, 1, GPUTexture::Type::RenderTarget,
|
||||
target_format, GPUTexture::Flags::None, nullptr, 0, &error)) ||
|
||||
!(m_output_texture =
|
||||
g_gpu_device->FetchTexture(target_width, target_height, 1, 1, 1, GPUTexture::Type::RenderTarget,
|
||||
target_format, GPUTexture::Flags::None, nullptr, 0, &error)))
|
||||
if (!g_gpu_device->ResizeTexture(&m_input_texture, source_width, source_height, GPUTexture::Type::RenderTarget,
|
||||
source_format, GPUTexture::Flags::None, false, &error) ||
|
||||
!g_gpu_device->ResizeTexture(&m_output_texture, target_width, target_height, GPUTexture::Type::RenderTarget,
|
||||
target_format, GPUTexture::Flags::None, false, &error))
|
||||
{
|
||||
ERROR_LOG("Failed to create input/output textures: {}", error.GetDescription());
|
||||
ERROR_LOG("Failed to resize input/output textures: {}", error.GetDescription());
|
||||
DestroyTextures();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!progress)
|
||||
progress = ProgressCallback::NullProgressCallback;
|
||||
// we change source after the first pass, so save the original values here
|
||||
m_source_width = source_width;
|
||||
m_source_height = source_height;
|
||||
m_source_format = source_format;
|
||||
m_viewport_width = viewport_width;
|
||||
m_viewport_height = viewport_height;
|
||||
|
||||
progress->SetProgressRange(static_cast<u32>(m_stages.size()));
|
||||
progress->SetProgressValue(0);
|
||||
|
||||
m_wants_depth_buffer = false;
|
||||
|
||||
for (size_t i = 0; i < m_stages.size(); i++)
|
||||
// shortcut if only the source size changed
|
||||
if (m_target_width != target_width || m_target_height != target_height || m_target_format != target_format)
|
||||
{
|
||||
Shader* const shader = m_stages[i].get();
|
||||
if (!progress)
|
||||
progress = ProgressCallback::NullProgressCallback;
|
||||
|
||||
progress->FormatStatusText("Compiling {}...", shader->GetName());
|
||||
progress->SetProgressRange(static_cast<u32>(m_stages.size()));
|
||||
progress->SetProgressValue(0);
|
||||
|
||||
if (!shader->CompilePipeline(target_format, target_width, target_height, &error, progress) ||
|
||||
!shader->ResizeOutput(target_format, target_width, target_height, &error))
|
||||
m_wants_depth_buffer = false;
|
||||
|
||||
for (size_t i = 0; i < m_stages.size(); i++)
|
||||
{
|
||||
ERROR_LOG("Failed to compile post-processing shader '{}':\n{}", shader->GetName(), error.GetDescription());
|
||||
Host::AddIconOSDMessage(
|
||||
"PostProcessLoadFail", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
fmt::format(TRANSLATE_FS("PostProcessing",
|
||||
"Failed to compile post-processing shader '{}'. Disabling post-processing.\n{}"),
|
||||
shader->GetName(), error.GetDescription()),
|
||||
Host::OSD_ERROR_DURATION);
|
||||
m_enabled = false;
|
||||
return false;
|
||||
}
|
||||
Shader* const shader = m_stages[i].get();
|
||||
|
||||
progress->SetProgressValue(static_cast<u32>(i + 1));
|
||||
m_wants_depth_buffer |= shader->WantsDepthBuffer();
|
||||
progress->FormatStatusText("Compiling {}...", shader->GetName());
|
||||
|
||||
if (!shader->CompilePipeline(target_format, target_width, target_height, &error, progress) ||
|
||||
!shader->ResizeTargets(source_width, source_height, target_format, target_width, target_height,
|
||||
viewport_width, viewport_height, &error))
|
||||
{
|
||||
ERROR_LOG("Failed to compile post-processing shader '{}':\n{}", shader->GetName(), error.GetDescription());
|
||||
Host::AddIconOSDMessage(
|
||||
"PostProcessLoadFail", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
fmt::format(TRANSLATE_FS("PostProcessing",
|
||||
"Failed to compile post-processing shader '{}'. Disabling post-processing.\n{}"),
|
||||
shader->GetName(), error.GetDescription()),
|
||||
Host::OSD_ERROR_DURATION);
|
||||
m_enabled = false;
|
||||
DestroyTextures();
|
||||
return false;
|
||||
}
|
||||
|
||||
progress->SetProgressValue(static_cast<u32>(i + 1));
|
||||
m_wants_depth_buffer |= shader->WantsDepthBuffer();
|
||||
|
||||
// First shader outputs at target size, so the input is now target size.
|
||||
source_width = target_width;
|
||||
source_height = target_height;
|
||||
viewport_width = target_width;
|
||||
viewport_height = target_height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::unique_ptr<Shader>& shader : m_stages)
|
||||
{
|
||||
if (!shader->ResizeTargets(source_width, source_height, target_format, target_width, target_height,
|
||||
viewport_width, viewport_height, &error))
|
||||
{
|
||||
ERROR_LOG("Failed to resize post-processing shader '{}':\n{}", shader->GetName(), error.GetDescription());
|
||||
Host::AddIconOSDMessage(
|
||||
"PostProcessLoadFail", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
fmt::format(TRANSLATE_FS("PostProcessing",
|
||||
"Failed to resize post-processing shader '{}'. Disabling post-processing.\n{}"),
|
||||
shader->GetName(), error.GetDescription()),
|
||||
Host::OSD_ERROR_DURATION);
|
||||
m_enabled = false;
|
||||
DestroyTextures();
|
||||
return false;
|
||||
}
|
||||
|
||||
// First shader outputs at target size, so the input is now target size.
|
||||
source_width = target_width;
|
||||
source_height = target_height;
|
||||
viewport_width = target_width;
|
||||
viewport_height = target_height;
|
||||
}
|
||||
}
|
||||
|
||||
m_target_format = target_format;
|
||||
m_target_width = target_width;
|
||||
m_target_height = target_height;
|
||||
m_target_format = target_format;
|
||||
m_needs_depth_buffer = m_enabled && m_wants_depth_buffer;
|
||||
return true;
|
||||
}
|
||||
@@ -646,8 +711,9 @@ void PostProcessing::Chain::DestroyTextures()
|
||||
}
|
||||
|
||||
GPUDevice::PresentResult PostProcessing::Chain::Apply(GPUTexture* input_color, GPUTexture* input_depth,
|
||||
GPUTexture* final_target, GSVector4i final_rect, s32 orig_width,
|
||||
s32 orig_height, s32 native_width, s32 native_height)
|
||||
GPUTexture* final_target, const GSVector4i final_rect,
|
||||
s32 orig_width, s32 orig_height, s32 native_width,
|
||||
s32 native_height)
|
||||
{
|
||||
GL_SCOPE_FMT("{} Apply", m_section);
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ public:
|
||||
|
||||
ALWAYS_INLINE bool HasStages() const { return !m_stages.empty(); }
|
||||
ALWAYS_INLINE bool NeedsDepthBuffer() const { return m_needs_depth_buffer; }
|
||||
ALWAYS_INLINE bool WantsUnscaledInput() const { return m_wants_unscaled_input; }
|
||||
ALWAYS_INLINE GPUTexture* GetInputTexture() const { return m_input_texture.get(); }
|
||||
ALWAYS_INLINE GPUTexture* GetOutputTexture() const { return m_output_texture.get(); }
|
||||
|
||||
@@ -135,8 +136,9 @@ public:
|
||||
/// Temporarily toggles post-processing on/off.
|
||||
void Toggle();
|
||||
|
||||
bool CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height,
|
||||
ProgressCallback* progress = nullptr);
|
||||
bool CheckTargets(GPUTexture::Format source_format, u32 source_width, u32 source_height,
|
||||
GPUTexture::Format target_format, u32 target_width, u32 target_height, u32 viewport_width,
|
||||
u32 viewport_height, ProgressCallback* progress = nullptr);
|
||||
|
||||
GPUDevice::PresentResult Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target,
|
||||
const GSVector4i final_rect, s32 orig_width, s32 orig_height, s32 native_width,
|
||||
@@ -148,12 +150,18 @@ private:
|
||||
|
||||
const char* m_section;
|
||||
|
||||
GPUTexture::Format m_target_format = GPUTexture::Format::Unknown;
|
||||
u32 m_source_width = 0;
|
||||
u32 m_source_height = 0;
|
||||
u32 m_target_width = 0;
|
||||
u32 m_target_height = 0;
|
||||
u32 m_viewport_width = 0;
|
||||
u32 m_viewport_height = 0;
|
||||
GPUTexture::Format m_source_format = GPUTexture::Format::Unknown;
|
||||
GPUTexture::Format m_target_format = GPUTexture::Format::Unknown;
|
||||
bool m_enabled = false;
|
||||
bool m_wants_depth_buffer = false;
|
||||
bool m_needs_depth_buffer = false;
|
||||
bool m_wants_unscaled_input = false;
|
||||
|
||||
std::vector<std::unique_ptr<PostProcessing::Shader>> m_stages;
|
||||
std::unique_ptr<GPUTexture> m_input_texture;
|
||||
|
||||
@@ -56,7 +56,12 @@ PostProcessing::Shader::Shader(std::string name) : m_name(std::move(name))
|
||||
|
||||
PostProcessing::Shader::~Shader() = default;
|
||||
|
||||
bool PostProcessing::Shader::IsValid() const
|
||||
bool PostProcessing::Shader::WantsDepthBuffer() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PostProcessing::Shader::WantsUnscaledInput() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -116,6 +121,13 @@ const PostProcessing::ShaderOption* PostProcessing::Shader::GetOptionByName(std:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool PostProcessing::Shader::ResizeTargets(u32 source_width, u32 source_height, GPUTexture::Format target_format,
|
||||
u32 target_width, u32 target_height, u32 viewport_width, u32 viewport_height,
|
||||
Error* error)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PostProcessing::ShaderOption* PostProcessing::Shader::GetOptionByName(std::string_view name)
|
||||
{
|
||||
for (ShaderOption& option : m_options)
|
||||
|
||||
@@ -35,8 +35,8 @@ public:
|
||||
ALWAYS_INLINE std::vector<ShaderOption>& GetOptions() { return m_options; }
|
||||
ALWAYS_INLINE bool HasOptions() const { return !m_options.empty(); }
|
||||
|
||||
virtual bool IsValid() const = 0;
|
||||
virtual bool WantsDepthBuffer() const = 0;
|
||||
virtual bool WantsDepthBuffer() const;
|
||||
virtual bool WantsUnscaledInput() const;
|
||||
|
||||
std::vector<ShaderOption> TakeOptions();
|
||||
void LoadOptions(const SettingsInterface& si, const char* section);
|
||||
@@ -44,7 +44,8 @@ public:
|
||||
const ShaderOption* GetOptionByName(std::string_view name) const;
|
||||
ShaderOption* GetOptionByName(std::string_view name);
|
||||
|
||||
virtual bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height, Error* error) = 0;
|
||||
virtual bool ResizeTargets(u32 source_width, u32 source_height, GPUTexture::Format target_format, u32 target_width,
|
||||
u32 target_height, u32 viewport_width, u32 viewport_height, Error* error);
|
||||
|
||||
virtual bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, Error* error,
|
||||
ProgressCallback* progress) = 0;
|
||||
|
||||
@@ -397,16 +397,9 @@ bool PostProcessing::ReShadeFXShader::LoadFromString(std::string name, std::stri
|
||||
}
|
||||
}
|
||||
|
||||
// Might go invalid when creating pipelines.
|
||||
m_valid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PostProcessing::ReShadeFXShader::IsValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
bool PostProcessing::ReShadeFXShader::WantsDepthBuffer() const
|
||||
{
|
||||
return m_wants_depth_buffer;
|
||||
@@ -1442,7 +1435,6 @@ GPUTexture* PostProcessing::ReShadeFXShader::GetTextureByID(TextureID id, GPUTex
|
||||
bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format, u32 width, u32 height, Error* error,
|
||||
ProgressCallback* progress)
|
||||
{
|
||||
m_valid = false;
|
||||
m_textures.clear();
|
||||
m_passes.clear();
|
||||
m_wants_depth_buffer = false;
|
||||
@@ -1589,31 +1581,29 @@ bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format,
|
||||
|
||||
progress->PopState();
|
||||
|
||||
m_valid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PostProcessing::ReShadeFXShader::ResizeOutput(GPUTexture::Format format, u32 width, u32 height, Error* error)
|
||||
bool PostProcessing::ReShadeFXShader::ResizeTargets(u32 source_width, u32 source_height,
|
||||
GPUTexture::Format target_format, u32 target_width,
|
||||
u32 target_height, u32 viewport_width, u32 viewport_height,
|
||||
Error* error)
|
||||
{
|
||||
m_valid = false;
|
||||
|
||||
for (Texture& tex : m_textures)
|
||||
{
|
||||
if (!tex.render_target)
|
||||
continue;
|
||||
|
||||
g_gpu_device->RecycleTexture(std::move(tex.texture));
|
||||
|
||||
const u32 t_width = (tex.render_target_width > 0) ? tex.render_target_width : width;
|
||||
const u32 t_height = (tex.render_target_height > 0) ? tex.render_target_height : height;
|
||||
tex.texture = g_gpu_device->FetchTexture(
|
||||
t_width, t_height, 1, 1, 1, GPUTexture::Type::RenderTarget, tex.format,
|
||||
tex.storage_access ? GPUTexture::Flags::AllowBindAsImage : GPUTexture::Flags::None, nullptr, 0, error);
|
||||
if (!tex.texture)
|
||||
return {};
|
||||
const u32 t_width = (tex.render_target_width > 0) ? tex.render_target_width : target_width;
|
||||
const u32 t_height = (tex.render_target_height > 0) ? tex.render_target_height : target_height;
|
||||
if (!g_gpu_device->ResizeTexture(&tex.texture, t_width, t_height, GPUTexture::Type::RenderTarget, tex.format,
|
||||
tex.storage_access ? GPUTexture::Flags::AllowBindAsImage : GPUTexture::Flags::None,
|
||||
false, error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_valid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,15 +27,17 @@ public:
|
||||
ReShadeFXShader();
|
||||
~ReShadeFXShader();
|
||||
|
||||
bool IsValid() const override;
|
||||
bool WantsDepthBuffer() const override;
|
||||
|
||||
bool LoadFromFile(std::string name, std::string filename, bool only_config, Error* error);
|
||||
bool LoadFromString(std::string name, std::string filename, std::string code, bool only_config, Error* error);
|
||||
|
||||
bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height, Error* error) override;
|
||||
bool ResizeTargets(u32 source_width, u32 source_height, GPUTexture::Format target_format, u32 target_width,
|
||||
u32 target_height, u32 viewport_width, u32 viewport_height, Error* error) override;
|
||||
|
||||
bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, Error* error,
|
||||
ProgressCallback* progress) override;
|
||||
|
||||
GPUDevice::PresentResult Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target,
|
||||
GSVector4i final_rect, s32 orig_width, s32 orig_height, s32 native_width,
|
||||
s32 native_height, u32 target_width, u32 target_height, float time) override;
|
||||
@@ -149,7 +151,6 @@ private:
|
||||
std::vector<Texture> m_textures;
|
||||
std::vector<SourceOption> m_source_options;
|
||||
u32 m_uniforms_size = 0;
|
||||
bool m_valid = false;
|
||||
bool m_wants_depth_buffer = false;
|
||||
|
||||
Timer m_frame_timer;
|
||||
|
||||
@@ -57,16 +57,6 @@ bool PostProcessing::GLSLShader::LoadFromString(std::string name, std::string co
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PostProcessing::GLSLShader::IsValid() const
|
||||
{
|
||||
return !m_name.empty() && !m_code.empty();
|
||||
}
|
||||
|
||||
bool PostProcessing::GLSLShader::WantsDepthBuffer() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 PostProcessing::GLSLShader::GetUniformsSize() const
|
||||
{
|
||||
// lazy packing. todo improve.
|
||||
@@ -211,11 +201,6 @@ GPUDevice::PresentResult PostProcessing::GLSLShader::Apply(GPUTexture* input_col
|
||||
return GPUDevice::PresentResult::OK;
|
||||
}
|
||||
|
||||
bool PostProcessing::GLSLShader::ResizeOutput(GPUTexture::Format format, u32 width, u32 height, Error* error)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void PostProcessing::GLSLShader::LoadOptions()
|
||||
{
|
||||
// Adapted from Dolphin's PostProcessingConfiguration::LoadOptions().
|
||||
|
||||
@@ -16,15 +16,12 @@ public:
|
||||
|
||||
ALWAYS_INLINE const std::string& GetCode() const { return m_code; }
|
||||
|
||||
bool IsValid() const override;
|
||||
bool WantsDepthBuffer() const override;
|
||||
|
||||
bool LoadFromFile(std::string name, const char* filename, Error* error);
|
||||
bool LoadFromString(std::string name, std::string code, Error* error);
|
||||
|
||||
bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height, Error* error) override;
|
||||
bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, Error* error,
|
||||
ProgressCallback* progress) override;
|
||||
|
||||
GPUDevice::PresentResult Apply(GPUTexture* input_color, GPUTexture* input_depth, GPUTexture* final_target,
|
||||
GSVector4i final_rect, s32 orig_width, s32 orig_height, s32 native_width,
|
||||
s32 native_height, u32 target_width, u32 target_height, float time) override;
|
||||
|
||||
Reference in New Issue
Block a user