diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 680700396..8e6bf8173 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -2066,9 +2066,17 @@ bool GPU::RenderDisplay(GPUTexture* target, const Common::Rectangle& draw_r if (really_postfx) { + // "original size" in postfx includes padding. + const float upscale_x = + static_cast(m_display_texture_view_width) / static_cast(m_display_active_width); + const float upscale_y = + static_cast(m_display_texture_view_height) / static_cast(m_display_active_height); + const s32 orig_width = static_cast(std::ceil(m_display_width * upscale_x)); + const s32 orig_height = static_cast(std::ceil(m_display_height * upscale_y)); + return PostProcessing::Apply(target, real_draw_rect.left, real_draw_rect.top, real_draw_rect.GetWidth(), - real_draw_rect.GetHeight(), m_display_texture_view_width, - m_display_texture_view_height); + real_draw_rect.GetHeight(), orig_width, orig_height, m_display_width, + m_display_height); } else { diff --git a/src/util/postprocessing.cpp b/src/util/postprocessing.cpp index 4ade7426f..ff89b0092 100644 --- a/src/util/postprocessing.cpp +++ b/src/util/postprocessing.cpp @@ -728,7 +728,7 @@ void PostProcessing::DestroyTextures() } bool PostProcessing::Apply(GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height, - s32 orig_width, s32 orig_height) + s32 orig_width, s32 orig_height, s32 native_width, s32 native_height) { GL_SCOPE("PostProcessing Apply"); @@ -741,7 +741,7 @@ bool PostProcessing::Apply(GPUTexture* final_target, s32 final_left, s32 final_t const bool is_final = (stage.get() == s_stages.back().get()); if (!stage->Apply(input, is_final ? final_target : output, final_left, final_top, final_width, final_height, - orig_width, orig_height, s_target_width, s_target_height)) + orig_width, orig_height, native_width, native_height, s_target_width, s_target_height)) { return false; } diff --git a/src/util/postprocessing.h b/src/util/postprocessing.h index 1c4988807..20acecbe0 100644 --- a/src/util/postprocessing.h +++ b/src/util/postprocessing.h @@ -125,10 +125,11 @@ void Shutdown(); GPUTexture* GetInputTexture(); const Common::Timer& GetTimer(); -bool CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height, ProgressCallback* progress = nullptr); +bool CheckTargets(GPUTexture::Format target_format, u32 target_width, u32 target_height, + ProgressCallback* progress = nullptr); bool Apply(GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width, - s32 orig_height); + s32 orig_height, s32 native_width, s32 native_height); GPUSampler* GetSampler(const GPUSampler::Config& config); GPUTexture* GetDummyTexture(); diff --git a/src/util/postprocessing_shader.h b/src/util/postprocessing_shader.h index 32e171636..5dabda31e 100644 --- a/src/util/postprocessing_shader.h +++ b/src/util/postprocessing_shader.h @@ -49,7 +49,8 @@ public: virtual bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) = 0; virtual bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, - s32 final_height, s32 orig_width, s32 orig_height, u32 target_width, u32 target_height) = 0; + s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height, + u32 target_width, u32 target_height) = 0; protected: static void ParseKeyValue(std::string_view line, std::string_view* key, std::string_view* value); diff --git a/src/util/postprocessing_shader_fx.cpp b/src/util/postprocessing_shader_fx.cpp index af1add1cf..98522b08a 100644 --- a/src/util/postprocessing_shader_fx.cpp +++ b/src/util/postprocessing_shader_fx.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "postprocessing_shader_fx.h" @@ -863,6 +864,29 @@ bool PostProcessing::ReShadeFXShader::GetSourceOption(const reshadefx::uniform_i SourceOptionType::InternalHeight; return true; } + else if (source == "nativewidth") + { + *si = (ui.type.base == reshadefx::type::t_float) ? SourceOptionType::NativeWidthF : SourceOptionType::NativeWidth; + return true; + } + else if (source == "nativeheight") + { + *si = + (ui.type.base == reshadefx::type::t_float) ? SourceOptionType::NativeHeightF : SourceOptionType::NativeHeight; + return true; + } + else if (source == "upscale_multiplier") + { + if (!ui.type.is_floating_point() || ui.type.components() != 1) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for upscale_multiplier source in uniform '{}'", + ui.type.description(), ui.name)); + return false; + } + + *si = SourceOptionType::UpscaleMultiplier; + return true; + } else { Error::SetString(error, fmt::format("Unknown source '{}' in uniform '{}'", source, ui.name)); @@ -1318,7 +1342,7 @@ bool PostProcessing::ReShadeFXShader::ResizeOutput(GPUTexture::Format format, u3 bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, - u32 target_width, u32 target_height) + s32 native_width, s32 native_height, u32 target_width, u32 target_height) { GL_PUSH_FMT("PostProcessingShaderFX {}", m_name); @@ -1452,8 +1476,8 @@ bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final case SourceOptionType::InternalWidth: case SourceOptionType::InternalHeight: { - const s32 value = - (so.source == SourceOptionType::BufferWidth) ? static_cast(orig_width) : static_cast(orig_height); + const s32 value = (so.source == SourceOptionType::InternalWidth) ? static_cast(orig_width) : + static_cast(orig_height); std::memcpy(dst, &value, sizeof(value)); } break; @@ -1461,8 +1485,33 @@ bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final case SourceOptionType::InternalWidthF: case SourceOptionType::InternalHeightF: { - const float value = (so.source == SourceOptionType::BufferWidthF) ? static_cast(orig_width) : - static_cast(orig_height); + const float value = (so.source == SourceOptionType::InternalWidthF) ? static_cast(orig_width) : + static_cast(orig_height); + std::memcpy(dst, &value, sizeof(value)); + } + break; + + case SourceOptionType::NativeWidth: + case SourceOptionType::NativeHeight: + { + const s32 value = (so.source == SourceOptionType::NativeWidth) ? static_cast(native_width) : + static_cast(native_height); + std::memcpy(dst, &value, sizeof(value)); + } + break; + + case SourceOptionType::NativeWidthF: + case SourceOptionType::NativeHeightF: + { + const float value = (so.source == SourceOptionType::NativeWidthF) ? static_cast(native_width) : + static_cast(native_height); + std::memcpy(dst, &value, sizeof(value)); + } + break; + + case SourceOptionType::UpscaleMultiplier: + { + const float value = static_cast(orig_width) / static_cast(native_width); std::memcpy(dst, &value, sizeof(value)); } break; diff --git a/src/util/postprocessing_shader_fx.h b/src/util/postprocessing_shader_fx.h index d6fa941f3..690a8c49f 100644 --- a/src/util/postprocessing_shader_fx.h +++ b/src/util/postprocessing_shader_fx.h @@ -31,7 +31,8 @@ public: bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height) override; bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) override; bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, - s32 final_height, s32 orig_width, s32 orig_height, u32 target_width, u32 target_height) override; + s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height, u32 target_width, + u32 target_height) override; private: using TextureID = s32; @@ -60,6 +61,11 @@ private: InternalHeight, InternalWidthF, InternalHeightF, + NativeWidth, + NativeHeight, + NativeWidthF, + NativeHeightF, + UpscaleMultiplier, MaxCount }; diff --git a/src/util/postprocessing_shader_glsl.cpp b/src/util/postprocessing_shader_glsl.cpp index 6f4eb1ea2..0728f821d 100644 --- a/src/util/postprocessing_shader_glsl.cpp +++ b/src/util/postprocessing_shader_glsl.cpp @@ -71,7 +71,8 @@ u32 PostProcessing::GLSLShader::GetUniformsSize() const void PostProcessing::GLSLShader::FillUniformBuffer(void* buffer, u32 texture_width, s32 texture_height, s32 texture_view_x, s32 texture_view_y, s32 texture_view_width, s32 texture_view_height, u32 window_width, u32 window_height, - s32 original_width, s32 original_height, float time) const + s32 original_width, s32 original_height, s32 native_width, + s32 native_height, float time) const { CommonUniforms* common = static_cast(buffer); @@ -91,17 +92,11 @@ void PostProcessing::GLSLShader::FillUniformBuffer(void* buffer, u32 texture_wid common->window_resolution[1] = static_cast(window_height); common->rcp_window_resolution[0] = 1.0f / static_cast(window_width); common->rcp_window_resolution[1] = 1.0f / static_cast(window_height); - - // pad the "original size" relative to the positioning on the screen - const float view_scale_x = static_cast(original_width) / static_cast(texture_view_width); - const float view_scale_y = static_cast(original_height) / static_cast(texture_view_height); - const s32 view_pad_x = texture_view_x + (texture_width - texture_view_width - texture_view_x); - const s32 view_pad_y = texture_view_y + (texture_height - texture_view_height - texture_view_y); common->original_size[0] = static_cast(original_width); common->original_size[1] = static_cast(original_height); - common->padded_original_size[0] = common->original_size[0] + static_cast(view_pad_x) * view_scale_x; - common->padded_original_size[1] = common->original_size[1] + static_cast(view_pad_y) * view_scale_y; - + common->native_size[0] = static_cast(native_width); + common->native_size[1] = static_cast(native_height); + common->upscale_multiplier = static_cast(original_width) / static_cast(native_width); common->time = time; u8* option_values = reinterpret_cast(common + 1); @@ -160,7 +155,7 @@ bool PostProcessing::GLSLShader::CompilePipeline(GPUTexture::Format format, u32 bool PostProcessing::GLSLShader::Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, s32 final_height, s32 orig_width, s32 orig_height, - u32 target_width, u32 target_height) + s32 native_width, s32 native_height, u32 target_width, u32 target_height) { GL_SCOPE_FMT("GLSL Shader {}", m_name); @@ -183,7 +178,7 @@ bool PostProcessing::GLSLShader::Apply(GPUTexture* input, GPUTexture* final_targ const u32 uniforms_size = GetUniformsSize(); void* uniforms = g_gpu_device->MapUniformBuffer(uniforms_size); FillUniformBuffer(uniforms, input->GetWidth(), input->GetHeight(), final_left, final_top, final_width, final_height, - target_width, target_height, orig_width, orig_height, + target_width, target_height, orig_width, orig_height, native_width, native_height, static_cast(PostProcessing::GetTimer().GetTimeSeconds())); g_gpu_device->UnmapUniformBuffer(uniforms_size); g_gpu_device->Draw(3, 0); @@ -407,42 +402,20 @@ static float4 o_col0; float4 Sample() { return texture(samp0, v_tex0); } float4 SampleLocation(float2 location) { return texture(samp0, location); } #define SampleOffset(offset) textureOffset(samp0, v_tex0, offset) -float2 GetFragCoord() -{ - return gl_FragCoord.xy; -} -float2 GetWindowResolution() -{ - return window_resolution; -} -float2 GetResolution() -{ - return resolution; -} -float2 GetInvResolution() -{ - return rcp_resolution; -} -float2 GetCoordinates() -{ - return v_tex0; -} -float2 GetOriginalSize() -{ - return original_size; -} -float2 GetPaddedOriginalSize() -{ - return padded_original_size; -} -float GetTime() -{ - return time; -} -void SetOutput(float4 color) -{ - o_col0 = color; -} +float2 GetFragCoord() { return gl_FragCoord.xy; } +float2 GetWindowResolution() { return window_resolution; } +float2 GetResolution() { return resolution; } +float2 GetInvResolution() { return rcp_resolution; } +float2 GetCoordinates() { return v_tex0; } +float2 GetOriginalSize() { return original_size; } +float2 GetNativeSize() { return native_size; } +float GetUpscaleMultiplier() { return upscale_multiplier; } +float GetTime() { return time; } +void SetOutput(float4 color) { o_col0 = color; } + +// Deprecated, only present for backwards compatibility. +float2 GetPaddedOriginalSize() { return original_size; } + #define GetOption(x) (x) #define OptionEnabled(x) ((x) != 0) )"; @@ -480,9 +453,9 @@ void PostProcessingGLSLShaderGen::WriteUniformBuffer(std::stringstream& ss, cons ss << " float2 window_resolution;\n"; ss << " float2 rcp_window_resolution;\n"; ss << " float2 original_size;\n"; - ss << " float2 padded_original_size;\n"; + ss << " float2 native_size;\n"; ss << " float time;\n"; - ss << " float ubo_pad" << (pad_counter++) << ";\n"; + ss << " float upscale_multiplier;\n"; ss << "\n"; static constexpr std::array vector_size_suffix = diff --git a/src/util/postprocessing_shader_glsl.h b/src/util/postprocessing_shader_glsl.h index ec6d99ce3..8c72f6833 100644 --- a/src/util/postprocessing_shader_glsl.h +++ b/src/util/postprocessing_shader_glsl.h @@ -24,7 +24,8 @@ public: bool ResizeOutput(GPUTexture::Format format, u32 width, u32 height) override; bool CompilePipeline(GPUTexture::Format format, u32 width, u32 height, ProgressCallback* progress) override; bool Apply(GPUTexture* input, GPUTexture* final_target, s32 final_left, s32 final_top, s32 final_width, - s32 final_height, s32 orig_width, s32 orig_height, u32 target_width, u32 target_height) override; + s32 final_height, s32 orig_width, s32 orig_height, s32 native_width, s32 native_height, u32 target_width, + u32 target_height) override; private: struct CommonUniforms @@ -36,9 +37,9 @@ private: float window_resolution[2]; float rcp_window_resolution[2]; float original_size[2]; - float padded_original_size[2]; + float native_size[2]; + float upscale_multiplier; float time; - float padding; }; void LoadOptions(); @@ -46,7 +47,8 @@ private: u32 GetUniformsSize() const; void FillUniformBuffer(void* buffer, u32 texture_width, s32 texture_height, s32 texture_view_x, s32 texture_view_y, s32 texture_view_width, s32 texture_view_height, u32 window_width, u32 window_height, - s32 original_width, s32 original_height, float time) const; + s32 original_width, s32 original_height, s32 native_width, s32 native_height, + float time) const; std::string m_code;