diff --git a/src/util/postprocessing_shader_fx.cpp b/src/util/postprocessing_shader_fx.cpp index 98522b08a..aa104a8b2 100644 --- a/src/util/postprocessing_shader_fx.cpp +++ b/src/util/postprocessing_shader_fx.cpp @@ -754,6 +754,7 @@ bool PostProcessing::ReShadeFXShader::CreateOptions(const reshadefx::module& mod bool PostProcessing::ReShadeFXShader::GetSourceOption(const reshadefx::uniform_info& ui, SourceOptionType* si, Error* error) { + // TODO: Rewrite these to a lookup table instead, this if chain is terrible. const std::string_view source = GetStringAnnotationValue(ui.annotations, "source", {}); if (!source.empty()) { @@ -879,14 +880,134 @@ bool PostProcessing::ReShadeFXShader::GetSourceOption(const reshadefx::uniform_i { 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)); + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); return false; } *si = SourceOptionType::UpscaleMultiplier; return true; } + else if (source == "viewportx") + { + if (!ui.type.is_floating_point() || ui.type.components() != 1) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::ViewportX; + return true; + } + else if (source == "viewporty") + { + if (!ui.type.is_floating_point() || ui.type.components() != 1) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::ViewportY; + return true; + } + else if (source == "viewportwidth") + { + if (!ui.type.is_floating_point() || ui.type.components() != 1) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::ViewportWidth; + return true; + } + else if (source == "viewportheight") + { + if (!ui.type.is_floating_point() || ui.type.components() != 1) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::ViewportHeight; + return true; + } + else if (source == "viewportsize") + { + if (!ui.type.is_floating_point() || ui.type.components() != 2) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::ViewportSize; + return true; + } + else if (source == "internal_pixel_size") + { + if (!ui.type.is_floating_point() || ui.type.components() != 2) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::InternalPixelSize; + return true; + } + else if (source == "normalized_internal_pixel_size") + { + if (!ui.type.is_floating_point() || ui.type.components() != 2) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::InternalNormPixelSize; + return true; + } + else if (source == "native_pixel_size") + { + if (!ui.type.is_floating_point() || ui.type.components() != 2) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::NativePixelSize; + return true; + } + else if (source == "normalized_native_pixel_size") + { + if (!ui.type.is_floating_point() || ui.type.components() != 2) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::NativeNormPixelSize; + return true; + } + else if (source == "buffer_to_viewport_ratio") + { + if (!ui.type.is_floating_point() || ui.type.components() != 2) + { + Error::SetString(error, fmt::format("Unexpected type '{}' for {} source in uniform '{}'", ui.type.description(), + source, ui.name)); + return false; + } + + *si = SourceOptionType::BufferToViewportRatio; + return true; + } else { Error::SetString(error, fmt::format("Unknown source '{}' in uniform '{}'", source, ui.name)); @@ -1516,6 +1637,83 @@ bool PostProcessing::ReShadeFXShader::Apply(GPUTexture* input, GPUTexture* final } break; + case SourceOptionType::ViewportX: + { + const float value = static_cast(final_left); + std::memcpy(dst, &value, sizeof(value)); + } + break; + + case SourceOptionType::ViewportY: + { + const float value = static_cast(final_top); + std::memcpy(dst, &value, sizeof(value)); + } + break; + + case SourceOptionType::ViewportWidth: + { + const float value = static_cast(final_width); + std::memcpy(dst, &value, sizeof(value)); + } + break; + + case SourceOptionType::ViewportHeight: + { + const float value = static_cast(final_height); + std::memcpy(dst, &value, sizeof(value)); + } + break; + + case SourceOptionType::ViewportSize: + { + const float value[2] = {static_cast(final_width), static_cast(final_height)}; + std::memcpy(dst, &value, sizeof(value)); + } + break; + + case SourceOptionType::InternalPixelSize: + { + const float value[2] = {static_cast(final_width) / static_cast(orig_width), + static_cast(final_height) / static_cast(orig_height)}; + std::memcpy(dst, value, sizeof(value)); + } + break; + + case SourceOptionType::InternalNormPixelSize: + { + const float value[2] = { + (static_cast(final_width) / static_cast(orig_width)) / static_cast(target_height), + (static_cast(final_height) / static_cast(orig_height)) / static_cast(target_height)}; + std::memcpy(dst, value, sizeof(value)); + } + break; + + case SourceOptionType::NativePixelSize: + { + const float value[2] = {static_cast(final_width) / static_cast(native_width), + static_cast(final_height) / static_cast(native_height)}; + std::memcpy(dst, value, sizeof(value)); + } + break; + + case SourceOptionType::NativeNormPixelSize: + { + const float value[2] = { + (static_cast(final_width) / static_cast(native_width)) / static_cast(target_height), + (static_cast(final_height) / static_cast(native_height)) / static_cast(target_height)}; + std::memcpy(dst, value, sizeof(value)); + } + break; + + case SourceOptionType::BufferToViewportRatio: + { + const float value[2] = {static_cast(target_width) / static_cast(final_width), + static_cast(target_height) / static_cast(final_height)}; + std::memcpy(dst, value, sizeof(value)); + } + break; + default: UnreachableCode(); break; diff --git a/src/util/postprocessing_shader_fx.h b/src/util/postprocessing_shader_fx.h index 690a8c49f..2be747e1c 100644 --- a/src/util/postprocessing_shader_fx.h +++ b/src/util/postprocessing_shader_fx.h @@ -66,6 +66,16 @@ private: NativeWidthF, NativeHeightF, UpscaleMultiplier, + ViewportX, + ViewportY, + ViewportWidth, + ViewportHeight, + ViewportSize, + InternalPixelSize, + InternalNormPixelSize, + NativePixelSize, + NativeNormPixelSize, + BufferToViewportRatio, MaxCount }; diff --git a/src/util/postprocessing_shader_glsl.cpp b/src/util/postprocessing_shader_glsl.cpp index 0728f821d..6eb898368 100644 --- a/src/util/postprocessing_shader_glsl.cpp +++ b/src/util/postprocessing_shader_glsl.cpp @@ -68,34 +68,43 @@ u32 PostProcessing::GLSLShader::GetUniformsSize() const return sizeof(CommonUniforms) + (sizeof(ShaderOption::ValueVector) * static_cast(m_options.size())); } -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, +void PostProcessing::GLSLShader::FillUniformBuffer(void* buffer, s32 viewport_x, s32 viewport_y, s32 viewport_width, + s32 viewport_height, u32 window_width, u32 window_height, s32 original_width, s32 original_height, s32 native_width, s32 native_height, float time) const { CommonUniforms* common = static_cast(buffer); - const float rcp_texture_width = 1.0f / static_cast(texture_width); - const float rcp_texture_height = 1.0f / static_cast(texture_height); - common->src_rect[0] = static_cast(texture_view_x) * rcp_texture_width; - common->src_rect[1] = static_cast(texture_view_y) * rcp_texture_height; - common->src_rect[2] = (static_cast(texture_view_x + texture_view_width - 1)) * rcp_texture_width; - common->src_rect[3] = (static_cast(texture_view_y + texture_view_height - 1)) * rcp_texture_height; - common->src_size[0] = (static_cast(texture_view_width)) * rcp_texture_width; - common->src_size[1] = (static_cast(texture_view_height)) * rcp_texture_height; - common->resolution[0] = static_cast(texture_width); - common->resolution[1] = static_cast(texture_height); - common->rcp_resolution[0] = rcp_texture_width; - common->rcp_resolution[1] = rcp_texture_height; - common->window_resolution[0] = static_cast(window_width); - 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); - common->original_size[0] = static_cast(original_width); - common->original_size[1] = static_cast(original_height); + const float internal_pixel_width = static_cast(viewport_width) / static_cast(original_width); + const float internal_pixel_height = static_cast(viewport_height) / static_cast(original_height); + const float native_pixel_width = (static_cast(viewport_width) / static_cast(native_width)); + const float native_pixel_height = (static_cast(viewport_height) / static_cast(native_height)); + common->src_rect[0] = static_cast(viewport_x) / static_cast(window_width); + common->src_rect[1] = static_cast(viewport_y) / static_cast(window_height); + common->src_rect[2] = (static_cast(viewport_x + viewport_width - 1)) / static_cast(window_width); + common->src_rect[3] = (static_cast(viewport_y + viewport_height - 1)) / static_cast(window_height); + common->src_size[0] = static_cast(viewport_width) / static_cast(window_width); + common->src_size[1] = static_cast(viewport_height) / static_cast(window_height); + common->window_size[0] = static_cast(window_width); + common->window_size[1] = static_cast(window_height); + common->rcp_window_size[0] = 1.0f / static_cast(window_width); + common->rcp_window_size[1] = 1.0f / static_cast(window_height); + common->viewport_size[0] = static_cast(viewport_width); + common->viewport_size[1] = static_cast(viewport_height); + common->window_to_viewport_ratio[0] = static_cast(window_width) / static_cast(viewport_width); + common->window_to_viewport_ratio[1] = static_cast(window_height) / static_cast(viewport_height); + common->internal_size[0] = static_cast(original_width); + common->internal_size[1] = static_cast(original_height); + common->internal_pixel_size[0] = internal_pixel_width; + common->internal_pixel_size[1] = internal_pixel_height; + common->norm_internal_pixel_size[0] = internal_pixel_width / static_cast(window_width); + common->norm_internal_pixel_size[1] = internal_pixel_height / static_cast(window_height); common->native_size[0] = static_cast(native_width); common->native_size[1] = static_cast(native_height); + common->native_pixel_size[0] = native_pixel_width; + common->native_pixel_size[1] = native_pixel_height; + common->norm_native_pixel_size[0] = native_pixel_width / static_cast(window_width); + common->norm_native_pixel_size[1] = native_pixel_height / static_cast(window_height); common->upscale_multiplier = static_cast(original_width) / static_cast(native_width); common->time = time; @@ -177,8 +186,8 @@ 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, native_width, native_height, + FillUniformBuffer(uniforms, final_left, final_top, final_width, final_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); @@ -341,7 +350,7 @@ std::string PostProcessingGLSLShaderGen::GeneratePostProcessingVertexShader(cons #if API_OPENGL || API_OPENGL_ES || API_VULKAN v_pos.y = -v_pos.y; #endif - v_tex0 = src_rect.xy + (src_size * v_tex0); + v_tex0 = u_src_rect.xy + (u_src_size * v_tex0); } )"; @@ -403,18 +412,27 @@ 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 GetNativeSize() { return native_size; } -float GetUpscaleMultiplier() { return upscale_multiplier; } -float GetTime() { return time; } +float2 GetWindowSize() { return u_window_size; } +float2 GetInvWindowSize() { return u_rcp_window_size; } +float2 GetViewportSize() { return u_viewport_size; } +float2 GetWindowToViewportRatio() { return u_window_to_viewport_ratio; } +float2 GetInternalSize() { return u_internal_size; } +float2 GetInternalPixelSize() { return u_internal_pixel_size; } +float2 GetInvInternalPixelSize() { return u_norm_internal_pixel_size; } +float2 GetNativeSize() { return u_native_size; } +float2 GetNativePixelSize() { return u_native_pixel_size; } +float2 GetInvNativePixelSize() { return u_norm_native_pixel_size; } +float GetUpscaleMultiplier() { return u_upscale_multiplier; } +float GetTime() { return u_time; } void SetOutput(float4 color) { o_col0 = color; } // Deprecated, only present for backwards compatibility. -float2 GetPaddedOriginalSize() { return original_size; } +float2 GetResolution() { return u_window_size; } +float2 GetInvResolution() { return u_rcp_window_size; } +float2 GetOriginalSize() { return u_internal_size; } +float2 GetPaddedOriginalSize() { return u_internal_size * u_window_to_viewport_ratio; } +float2 GetWindowResolution() { return u_window_size; } #define GetOption(x) (x) #define OptionEnabled(x) ((x) != 0) @@ -446,16 +464,20 @@ void PostProcessingGLSLShaderGen::WriteUniformBuffer(std::stringstream& ss, cons WriteUniformBufferDeclaration(ss, use_push_constants); ss << "{\n"; - ss << " float4 src_rect;\n"; - ss << " float2 src_size;\n"; - ss << " float2 resolution;\n"; - ss << " float2 rcp_resolution;\n"; - ss << " float2 window_resolution;\n"; - ss << " float2 rcp_window_resolution;\n"; - ss << " float2 original_size;\n"; - ss << " float2 native_size;\n"; - ss << " float time;\n"; - ss << " float upscale_multiplier;\n"; + ss << " float4 u_src_rect;\n"; + ss << " float2 u_src_size;\n"; + ss << " float2 u_window_size;\n"; + ss << " float2 u_rcp_window_size;\n"; + ss << " float2 u_viewport_size;\n"; + ss << " float2 u_window_to_viewport_ratio;\n"; + ss << " float2 u_internal_size;\n"; + ss << " float2 u_internal_pixel_size;\n"; + ss << " float2 u_norm_internal_pixel_size;\n"; + ss << " float2 u_native_size;\n"; + ss << " float2 u_native_pixel_size;\n"; + ss << " float2 u_norm_native_pixel_size;\n"; + ss << " float u_upscale_multiplier;\n"; + ss << " float u_time;\n"; ss << "\n"; static constexpr std::array vector_size_suffix = @@ -467,14 +489,14 @@ void PostProcessingGLSLShaderGen::WriteUniformBuffer(std::stringstream& ss, cons case PostProcessing::ShaderOption::Type::Bool: ss << " int " << option.name << ";\n"; for (u32 i = option.vector_size; i < PostProcessing::ShaderOption::MAX_VECTOR_COMPONENTS; i++) - ss << " int ubo_pad" << (pad_counter++) << ";\n"; + ss << " int u_ubo_pad" << (pad_counter++) << ";\n"; break; case PostProcessing::ShaderOption::Type::Int: { ss << " int" << vector_size_suffix[option.vector_size] << " " << option.name << ";\n"; for (u32 i = option.vector_size; i < PostProcessing::ShaderOption::MAX_VECTOR_COMPONENTS; i++) - ss << " int ubo_pad" << (pad_counter++) << ";\n"; + ss << " int u_ubo_pad" << (pad_counter++) << ";\n"; } break; @@ -483,7 +505,7 @@ void PostProcessingGLSLShaderGen::WriteUniformBuffer(std::stringstream& ss, cons { ss << " float" << vector_size_suffix[option.vector_size] << " " << option.name << ";\n"; for (u32 i = option.vector_size; i < PostProcessing::ShaderOption::MAX_VECTOR_COMPONENTS; i++) - ss << " float ubo_pad" << (pad_counter++) << ";\n"; + ss << " float u_ubo_pad" << (pad_counter++) << ";\n"; } break; } diff --git a/src/util/postprocessing_shader_glsl.h b/src/util/postprocessing_shader_glsl.h index 8c72f6833..d4203171f 100644 --- a/src/util/postprocessing_shader_glsl.h +++ b/src/util/postprocessing_shader_glsl.h @@ -32,12 +32,16 @@ private: { float src_rect[4]; float src_size[2]; - float resolution[2]; - float rcp_resolution[2]; - float window_resolution[2]; - float rcp_window_resolution[2]; - float original_size[2]; + float window_size[2]; + float rcp_window_size[2]; + float viewport_size[2]; + float window_to_viewport_ratio[2]; + float internal_size[2]; + float internal_pixel_size[2]; + float norm_internal_pixel_size[2]; float native_size[2]; + float native_pixel_size[2]; + float norm_native_pixel_size[2]; float upscale_multiplier; float time; }; @@ -45,10 +49,9 @@ private: void LoadOptions(); 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, s32 native_width, s32 native_height, - float time) const; + void FillUniformBuffer(void* buffer, s32 viewport_x, s32 viewport_y, s32 viewport_width, s32 viewport_height, + u32 window_width, u32 window_height, s32 original_width, s32 original_height, s32 native_width, + s32 native_height, float time) const; std::string m_code;