diff --git a/rpcs3/Emu/RSX/Common/surface_utils.h b/rpcs3/Emu/RSX/Common/surface_utils.h index 28f756d6b9..de70dd436a 100644 --- a/rpcs3/Emu/RSX/Common/surface_utils.h +++ b/rpcs3/Emu/RSX/Common/surface_utils.h @@ -85,10 +85,14 @@ namespace rsx if (g_cfg.video.resolution_scale_percent != 100) { auto src = static_cast(source); - src_w = rsx::apply_resolution_scale(src_w, true, src->get_surface_width(rsx::surface_metrics::pixels)); - src_h = rsx::apply_resolution_scale(src_h, true, src->get_surface_height(rsx::surface_metrics::pixels)); - dst_w = rsx::apply_resolution_scale(dst_w, true, target_surface->get_surface_width(rsx::surface_metrics::pixels)); - dst_h = rsx::apply_resolution_scale(dst_h, true, target_surface->get_surface_height(rsx::surface_metrics::pixels)); + + std::tie(src_w, src_h) = rsx::apply_resolution_scale(src_w, src_h, + src->get_surface_width(rsx::surface_metrics::pixels), + src->get_surface_height(rsx::surface_metrics::pixels)); + + std::tie(dst_w, dst_h) = rsx::apply_resolution_scale(dst_w, dst_h, + target_surface->get_surface_width(rsx::surface_metrics::pixels), + target_surface->get_surface_height(rsx::surface_metrics::pixels)); } width = src_w; @@ -484,11 +488,8 @@ namespace rsx // Apply resolution scale if needed if (g_cfg.video.resolution_scale_percent != 100) { - auto src_width = rsx::apply_resolution_scale(slice.width, true, slice.source->width()); - auto src_height = rsx::apply_resolution_scale(slice.height, true, slice.source->height()); - - auto dst_width = rsx::apply_resolution_scale(slice.width, true, slice.target->width()); - auto dst_height = rsx::apply_resolution_scale(slice.height, true, slice.target->height()); + auto [src_width, src_height] = rsx::apply_resolution_scale(slice.width, slice.height, slice.source->width(), slice.source->height()); + auto [dst_width, dst_height] = rsx::apply_resolution_scale(slice.width, slice.height, slice.target->width(), slice.target->height()); slice.transfer_scale_x *= f32(dst_width) / src_width; slice.transfer_scale_y *= f32(dst_height) / src_height; @@ -496,10 +497,8 @@ namespace rsx slice.width = src_width; slice.height = src_height; - slice.src_x = rsx::apply_resolution_scale(slice.src_x, false, slice.source->width()); - slice.src_y = rsx::apply_resolution_scale(slice.src_y, false, slice.source->height()); - slice.dst_x = rsx::apply_resolution_scale(slice.dst_x, false, slice.target->width()); - slice.dst_y = rsx::apply_resolution_scale(slice.dst_y, false, slice.target->height()); + std::tie(slice.src_x, slice.src_y) = rsx::apply_resolution_scale(slice.src_x, slice.src_y, slice.source->width(), slice.source->height()); + std::tie(slice.dst_x, slice.dst_y) = rsx::apply_resolution_scale(slice.dst_x, slice.dst_y, slice.target->width(), slice.target->height()); } } diff --git a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h index 614cfae5a0..3f57f83a3e 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h @@ -287,8 +287,8 @@ namespace rsx // How much of this slice to read? int rebased = int(section.dst_area.y) - slice_begin; - const auto src_x = section.src_area.x; - const auto dst_x = section.dst_area.x; + auto src_x = section.src_area.x; + auto dst_x = section.dst_area.x; auto src_y = section.src_area.y; auto dst_y = section.dst_area.y; @@ -306,20 +306,22 @@ namespace rsx const auto h = std::min(section_end, slice_end) - dst_y; dst_y = (dst_y - slice_begin); - const auto src_width = rsx::apply_resolution_scale(section.src_area.width, true); - const auto src_height = rsx::apply_resolution_scale(h, true); - const auto dst_width = rsx::apply_resolution_scale(section.dst_area.width, true); + const auto [src_width, src_height] = rsx::apply_resolution_scale(section.src_area.width, h, attr.width, attr.height); + const auto [dst_width, unused] = rsx::apply_resolution_scale(section.dst_area.width, RSX_SURFACE_DIMENSION_IGNORED, attr.width, RSX_SURFACE_DIMENSION_IGNORED); const auto dst_height = src_height; + std::tie(src_x, src_y) = rsx::apply_resolution_scale(src_x, src_y, attr.width, attr.height); + std::tie(dst_x, dst_y) = rsx::apply_resolution_scale(dst_x, dst_y, attr.width, attr.height); + out.push_back ({ section.surface->get_surface(rsx::surface_access::read), surface_transform::identity, 0, - rsx::apply_resolution_scale(src_x, true), - rsx::apply_resolution_scale(src_y, true), - rsx::apply_resolution_scale(dst_x, true), - rsx::apply_resolution_scale(dst_y, true), + static_cast(src_x), + static_cast(src_y), + static_cast(dst_x), + static_cast(dst_y), slice, src_width, src_height, dst_width, dst_height @@ -365,20 +367,23 @@ namespace rsx if (scaling) { // Since output is upscaled, also upscale on dst + const auto [_dst_x, _dst_y] = rsx::apply_resolution_scale(static_cast(std::get<1>(clipped).x), static_cast(dst_y - slice_begin), attr.width, attr.height); + const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale(dst_w, height, attr.width, attr.height); + out.push_back ({ section->get_raw_texture(), surface_transform::identity, 0, - static_cast(std::get<0>(clipped).x), // src.x - static_cast(std::get<0>(clipped).y), // src.y - rsx::apply_resolution_scale(static_cast(std::get<1>(clipped).x), true), // dst.x - rsx::apply_resolution_scale(static_cast(dst_y - slice_begin), true), // dst.y + static_cast(std::get<0>(clipped).x), // src.x + static_cast(std::get<0>(clipped).y), // src.y + _dst_x, // dst.x + _dst_y, // dst.y slice, src_w, height, - rsx::apply_resolution_scale(dst_w, true), - rsx::apply_resolution_scale(height, true), + _dst_w, + _dst_h, }); } else @@ -539,8 +544,7 @@ namespace rsx attr2.height < surface_height || force_convert) { - const auto scaled_w = rsx::apply_resolution_scale(attr2.width, true); - const auto scaled_h = rsx::apply_resolution_scale(attr2.height, true); + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(attr2.width, attr2.height); const auto format_class = (force_convert) ? classify_format(attr2.gcm_format) : texptr->format_class(); const auto command = surface_is_rop_target ? deferred_request_command::copy_image_dynamic : deferred_request_command::copy_image_static; @@ -557,8 +561,7 @@ namespace rsx texptr->format_class(), scale, rsx::texture_dimension_extended::texture_dimension_2d, surface_is_rop_target }; } - const auto scaled_w = rsx::apply_resolution_scale(attr2.width, true); - const auto scaled_h = rsx::apply_resolution_scale(attr2.height, true); + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(attr2.width, attr2.height); if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_3d) { @@ -643,8 +646,7 @@ namespace rsx } // If this method was called, there is no easy solution, likely means atlas gather is needed - auto scaled_w = rsx::apply_resolution_scale(attr2.width, true); - auto scaled_h = rsx::apply_resolution_scale(attr2.height, true); + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(attr2.width, attr2.height); const auto format_class = classify_format(attr2.gcm_format); if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_cubemap) @@ -717,8 +719,7 @@ namespace rsx // Calculate transfer dimensions from attr if (level.upload_context == rsx::texture_upload_context::framebuffer_storage) [[likely]] { - mip.src_w = rsx::apply_resolution_scale(attr.width, true); - mip.src_h = rsx::apply_resolution_scale(attr.height, true); + std::tie(mip.src_w, mip.src_h) = rsx::apply_resolution_scale(attr.width, attr.height); } else { @@ -763,8 +764,7 @@ namespace rsx if (apply_upscaling) { auto& mip = sections.back(); - mip.dst_w = rsx::apply_resolution_scale(mip.dst_w, true, level0_attr.width); - mip.dst_h = rsx::apply_resolution_scale(mip.dst_h, true, level0_attr.height); + std::tie(mip.dst_w, mip.dst_h) = rsx::apply_resolution_scale(mip.dst_w, mip.dst_h, level0_attr.width, level0_attr.height); } return true; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 816447a66d..c560a8b54d 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -32,8 +32,9 @@ extern CellGcmContextData current_context; void GLGSRender::set_viewport() { // NOTE: scale offset matrix already contains the viewport transformation - const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true); - const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true); + const auto [clip_width, clip_height] = rsx::apply_resolution_scale( + rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height()); + glViewport(0, 0, clip_width, clip_height); } diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index 4b81db2987..d7cefe8f16 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -48,8 +48,9 @@ gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, cons surface->read_barrier(cmd); image = section.surface->get_surface(rsx::surface_access::read); - info->width = rsx::apply_resolution_scale(std::min(surface_width, static_cast(info->width)), true); - info->height = rsx::apply_resolution_scale(std::min(surface_height, static_cast(info->height)), true); + std::tie(info->width, info->height) = rsx::apply_resolution_scale( + std::min(surface_width, static_cast(info->width)), + std::min(surface_height, static_cast(info->height))); } } } @@ -154,7 +155,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) if (avconfig->_3d) [[unlikely]] { - const auto min_expected_height = rsx::apply_resolution_scale(buffer_height + 30, true); + const auto [unused, min_expected_height] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30); if (image_to_flip_->height() < min_expected_height) { // Get image for second eye @@ -168,7 +169,8 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) else { // Account for possible insets - buffer_height = std::min(image_to_flip_->height() - min_expected_height, rsx::apply_resolution_scale(buffer_height, true)); + const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, buffer_height); + buffer_height = std::min(image_to_flip_->height() - min_expected_height, scaled_buffer_height); } } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index 23dd8fde91..55995ff940 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -108,7 +108,8 @@ namespace gl bool matches_dimensions(u16 _width, u16 _height) const { //Use forward scaling to account for rounding and clamping errors - return (rsx::apply_resolution_scale(_width, true) == width()) && (rsx::apply_resolution_scale(_height, true) == height()); + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(_width, _height); + return (scaled_w == width()) && (scaled_h == height()); } void memory_barrier(gl::command_context& cmd, rsx::surface_access access); @@ -144,10 +145,10 @@ struct gl_render_target_traits ) { auto format = rsx::internals::surface_color_format_to_gl(surface_color_format); + const auto [width_, height_] = rsx::apply_resolution_scale(static_cast(width), static_cast(height)); - std::unique_ptr result(new gl::render_target(rsx::apply_resolution_scale(static_cast(width), true), - rsx::apply_resolution_scale(static_cast(height), true), static_cast(format.internal_format), - RSX_FORMAT_CLASS_COLOR)); + std::unique_ptr result(new gl::render_target(width_, height_, + static_cast(format.internal_format), RSX_FORMAT_CLASS_COLOR)); result->set_aa_mode(antialias); result->set_native_pitch(static_cast(width) * get_format_block_size_in_bytes(surface_color_format) * result->samples_x); @@ -173,9 +174,10 @@ struct gl_render_target_traits ) { auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format); - std::unique_ptr result(new gl::render_target(rsx::apply_resolution_scale(static_cast(width), true), - rsx::apply_resolution_scale(static_cast(height), true), static_cast(format.internal_format), - rsx::classify_format(surface_depth_format))); + const auto [width_, height_] = rsx::apply_resolution_scale(static_cast(width), static_cast(height)); + + std::unique_ptr result(new gl::render_target(width_, height_, + static_cast(format.internal_format), rsx::classify_format(surface_depth_format))); result->set_aa_mode(antialias); result->set_surface_dimensions(static_cast(width), static_cast(height), static_cast(pitch)); @@ -201,8 +203,8 @@ struct gl_render_target_traits if (!sink) { auto internal_format = static_cast(ref->get_internal_format()); - const auto new_w = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width(rsx::surface_metrics::pixels)); - const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height(rsx::surface_metrics::pixels)); + const auto [new_w, new_h] = rsx::apply_resolution_scale(prev.width, prev.height, + ref->get_surface_width(rsx::surface_metrics::pixels), ref->get_surface_height(rsx::surface_metrics::pixels)); sink = std::make_unique(new_w, new_h, internal_format, ref->format_class()); sink->add_ref(); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 03de591b66..ee4e6b0321 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1518,10 +1518,8 @@ namespace rsx framebuffer_status_valid = true; } - region.x1 = rsx::apply_resolution_scale(x1, false); - region.x2 = rsx::apply_resolution_scale(x2, true); - region.y1 = rsx::apply_resolution_scale(y1, false); - region.y2 = rsx::apply_resolution_scale(y2, true); + std::tie(region.x1, region.y1) = rsx::apply_resolution_scale(x1, y1); + std::tie(region.x2, region.y2) = rsx::apply_resolution_scale(x2, y2); return true; } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index cce40171c1..0b6a2f790e 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -952,8 +952,9 @@ VkDescriptorSet VKGSRender::allocate_descriptor_set() void VKGSRender::set_viewport() { - const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true); - const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true); + const auto [clip_width, clip_height] = rsx::apply_resolution_scale( + rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height()); + const auto zclip_near = rsx::method_registers.clip_min(); const auto zclip_far = rsx::method_registers.clip_max(); @@ -2187,8 +2188,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_cached_renderpass = vk::get_renderpass(*m_device, m_current_renderpass_key); // Search old framebuffers for this same configuration - const auto fbo_width = rsx::apply_resolution_scale(m_framebuffer_layout.width, true); - const auto fbo_height = rsx::apply_resolution_scale(m_framebuffer_layout.height, true); + const auto [fbo_width, fbo_height] = rsx::apply_resolution_scale(m_framebuffer_layout.width, m_framebuffer_layout.height); if (m_draw_fbo) { diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 277b63aa0e..44d8302fc5 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -313,8 +313,9 @@ vk::image* VKGSRender::get_present_source(vk::present_surface_info* info, const surface->read_barrier(*m_current_command_buffer); image_to_flip = section.surface->get_surface(rsx::surface_access::read); - info->width = rsx::apply_resolution_scale(std::min(surface_width, static_cast(info->width)), true); - info->height = rsx::apply_resolution_scale(std::min(surface_height, static_cast(info->height)), true); + std::tie(info->width, info->height) = rsx::apply_resolution_scale( + std::min(surface_width, static_cast(info->width)), + std::min(surface_height, static_cast(info->height))); } } } @@ -469,7 +470,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) if (avconfig->_3d) [[unlikely]] { - const auto min_expected_height = rsx::apply_resolution_scale(buffer_height + 30, true); + const auto [unused, min_expected_height] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30); if (image_to_flip->height() < min_expected_height) { // Get image for second eye @@ -483,7 +484,8 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) else { // Account for possible insets - buffer_height = std::min(image_to_flip->height() - min_expected_height, rsx::apply_resolution_scale(buffer_height, true)); + const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, buffer_height); + buffer_height = std::min(image_to_flip->height() - min_expected_height, scaled_buffer_height); } } diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 832792ebde..315457dcf6 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -345,8 +345,9 @@ namespace vk bool matches_dimensions(u16 _width, u16 _height) const { - //Use forward scaling to account for rounding and clamping errors - return (rsx::apply_resolution_scale(_width, true) == width()) && (rsx::apply_resolution_scale(_height, true) == height()); + // Use forward scaling to account for rounding and clamping errors + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(_width, _height); + return (scaled_w == width()) && (scaled_h == height()); } void texture_barrier(vk::command_buffer& cmd) @@ -644,11 +645,13 @@ namespace rsx } std::unique_ptr rtt; + const auto [width_, height_] = rsx::apply_resolution_scale(static_cast(width), static_cast(height)); + rtt = std::make_unique(device, device.get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_TYPE_2D, requested_format, - static_cast(rsx::apply_resolution_scale(static_cast(width), true)), static_cast(rsx::apply_resolution_scale(static_cast(height), true)), 1, 1, 1, + static_cast(width_), static_cast(height_), 1, 1, 1, static_cast(samples), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, @@ -702,11 +705,13 @@ namespace rsx } std::unique_ptr ds; + const auto [width_, height_] = rsx::apply_resolution_scale(static_cast(width), static_cast(height)); + ds = std::make_unique(device, device.get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_IMAGE_TYPE_2D, requested_format, - static_cast(rsx::apply_resolution_scale(static_cast(width), true)), static_cast(rsx::apply_resolution_scale(static_cast(height), true)), 1, 1, 1, + static_cast(width_), static_cast(height_), 1, 1, 1, static_cast(samples), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, @@ -738,8 +743,8 @@ namespace rsx { if (!sink) { - const auto new_w = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width(rsx::surface_metrics::pixels)); - const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height(rsx::surface_metrics::pixels)); + const auto [new_w, new_h] = rsx::apply_resolution_scale(prev.width, prev.height, + ref->get_surface_width(rsx::surface_metrics::pixels), ref->get_surface_height(rsx::surface_metrics::pixels)); auto& dev = cmd.get_command_pool().get_owner(); sink = std::make_unique(dev, dev.get_memory_mapping().device_local, diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 6c0f87b66a..25c09e587a 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -14,6 +14,8 @@ extern "C" #include } +#define RSX_SURFACE_DIMENSION_IGNORED 1 + namespace rsx { // Import address_range utilities @@ -586,33 +588,54 @@ namespace rsx return g_cfg.video.strict_rendering_mode ? 100 : g_cfg.video.resolution_scale_percent; } - static inline const u16 apply_resolution_scale(u16 value, bool clamp, u16 ref = 0) + template + static inline const std::pair apply_resolution_scale(u16 width, u16 height, u16 ref_width = 0, u16 ref_height = 0) { - if (ref == 0) - ref = value; - - if (ref <= g_cfg.video.min_scalable_dimension) - return value; - - else if (clamp) - return static_cast(std::max((get_resolution_scale_percent() * value) / 100, 1)); + u16 ref; + if (width > height) [[likely]] + { + ref = (ref_width) ? ref_width : width; + } else - return static_cast((get_resolution_scale_percent() * value) / 100); + { + ref = (ref_height) ? ref_height : height; + } + + if (ref > g_cfg.video.min_scalable_dimension) + { + // Upscale both width and height + width = (get_resolution_scale_percent() * width) / 100; + height = (get_resolution_scale_percent() * height) / 100; + + if constexpr (clamp) + { + width = std::max(width, 1); + height = std::max(height, 1); + } + } + + return { width, height }; } - static inline const u16 apply_inverse_resolution_scale(u16 value, bool clamp) + template + static inline const std::pair apply_inverse_resolution_scale(u16 width, u16 height) { - u16 result = value; + // Inverse scale + auto width_ = (width * 100) / get_resolution_scale_percent(); + auto height_ = (height * 100) / get_resolution_scale_percent(); if (clamp) - result = static_cast(std::max((value * 100) / get_resolution_scale_percent(), 1)); - else - result = static_cast((value * 100) / get_resolution_scale_percent()); + { + width_ = std::max(width_, 1); + height_ = std::max(height_, 1); + } - if (result <= g_cfg.video.min_scalable_dimension) - return value; + if (std::max(width_, height_) > g_cfg.video.min_scalable_dimension) + { + return { width_, height_ }; + } - return result; + return { width, height }; } /**